[译]《Smashing》: 用 CSS 形状打造高级排版

原文Take A New Look At CSS Shapes
做者Rachel Andrew 发表时间:september 4, 2018
译者:西楼听雨 发表时间: 2018/9/16
(转载请注明出处)css

摘要:在本文中,咱们将对 CSS 形状的概念,以及如何用图片、渐变和基础形状来建立非矩形类的形状作一个讲解。另外咱们还会讲到 Firefox 的新工具是如何让咱们编辑形状变得简单的。web

展开原文 CSS Shapes Level 1 has been available in Chrome and Safari for a number of years, however, this week it ships in a production version of Firefox with the release of Firefox 62 — along with a very nice addition to the Firefox DevTools to help us work with Shapes. In this article, I’ll take a look at some of the things you can do with CSS Shapes. Perhaps it’s time to consider adding some curves to your designs?

CSS 形状第一阶段规范已经在 Chrome 和 Safari 中实现了有好几年了,而随着 Firefox 62 在本周发布,Firefox 也已经在生产版本中支持了——另外随之发布的还有一个很棒的开发者工具功能,它对咱们使用形状能够带来帮助。在本文中,咱们将看下一能够用 CSS 形状作哪些事情。也许是时候考虑给咱们的设计添加一些曲线效果了!浏览器

什么是 CSS 形状(CSS Shapes)?

The CSS Shapes specification Level 1 defines three new properties:服务器

CSS 形状规范的第一阶段 (CSS Shapes Level 1) 定义了三个新的属性:app

  • shape-outside
  • shape-image-threshold
  • shape-margin

展开原文 The purpose of this specification is to allow content to flow around a non-rectangular shape, something which is quite unusual on our boxy web. There are a few different ways to create shapes, which we will have a look at in this tutorial. We will also have a look at the Shape Path Editor, available in Firefox, as it can help you to easily understand the shapes on your page and work with them.

In the current specification, shapes can only be applied to a float, so any shapes example needs to start with a floated element. In the example below, I have a PNG image with a transparent background in which I have floated the image left. The text that follows the image now flows around the right and bottom of my image.ide

What I would like to happen is for my content to follow the shape of the opaque part of the image, rather than follow the line of the physical image file. To do this, I use the shape-outside property, with the value being the URL of my image. I’m using the actual image file to create a path for the content to flow around.函数

这个规范的制定,目的是为了让内容的排布能够支持环绕着非矩形类形状进行,即那些和咱们 Web 的盒子模型极大不一样的形状。建立形状有多种方式,咱们会在这篇教程中讲到。另外咱们还会对 Shape Path Editor ——可在 Firefox 中找到——作一下介绍,由于它能够帮助咱们理解和使用形状。工具

在当前版本的规范中,规定了形状只能被应用在浮动元素上。在下面的这个例子中,我放了一张背景透明的 PNG 图片,并将其浮动到左边。其后的文本随之排布在了其右侧和底部。flex

在这例子中,我真正但愿的结果是,个人内容能够围绕图片中非透明部分的形状进行排布,而不是这个图片文件的物理边线。因此,为了实现这种效果,我使用的是 shape-outside 属性,并把这个图片的 URL 做为其值。这里我使用的就是图片文件来为个人内容建立环绕路径的。 ui

展开原文 Note that your image needs to be CORS compatible, so hosted on the same server as the rest of your content or sending the correct headers if hosted on a CDN. Browser DevTools will usually tell you if your image is being blocked due to CORS.

This method of creating shapes uses the alpha channel of the image to create the shape, as we have a shape with a fully transparent area, then all we need do is pass the URL of the image to shape-outsideand the shape path follows the line of the fully opaque area.

注意,你的图片须兼容 CORS,因此须要把图片放在和你内容相同的服务器下,或者假如放在 CDN 上的话,须要确保响应正确的 HTTP 头部。若是你的图片由于 CORS 被屏蔽了,能够在浏览器的开发者工具中看到。

(译注:CORS,全称 Cross-Origin Resource Sharing;跨源性资源共享。这里的“图片”指的是 shape-outside 属性中的 URL,而不是指 img 标签——它是无需兼容 CORS 的 )

这种建立形状的方法,使用的是图片的 alpha 通道。由于咱们这张图片里的形状以外都是彻底透明的区域,因此咱们只需把它 URL 给到 shape-outside 属性,便可实现将非透明区域的边线所造成的路径做为形状。

设置外边距

展开原文 To push the line of the text away from the image we can use the `shape-margin` property. This creates a margin between the line of the shape and the content running alongside it.

为了将文本从图片上推开,咱们可使用 shape-margin 属性,它能够在形状及其周围的内容之间设置一个边界。

利用伪类充当形状载体 (Using Generated Content For Our Shape)

展开原文 In the case above, we have the image displayed on the page and then the text curved around it. However, you could also use an image as the path for the shape in order to create a curved text effect without also including the image on the page. You still need something to float, however, and so for this, we can use Generated Content.

上面的例子中,咱们将图片展现在页面中,并使得文本环绕着它弯曲。其实,你也能够作到在不展现那张图片的状况的同时使用那张图片的形状做为环绕路径来得到一样的效果。不过要作到这种效果,咱们仍然须要有一个浮动的元素,为此,咱们能够用生成的内容 (Generated Content;[译注] 这里指伪类) 来充当。

展开原文 In this example, we have inserted some generated content, floated it left, given it a width and a height and then used `shape-outside` with our image just as before. We then get a curved line against the whitespace, but no visible image.

在这个例子中,咱们经过插入生成的内容,并将其浮动到左侧,给其设置宽度和高度,而后使用以前的图片做为 shape-outside 。这样咱们就达到了在没有可见的图片的状况下,仍然得到曲线性地围绕空白区域的效果。

使用渐变做为形状

展开原文 A CSS gradient is just like an image, which means we can use a gradient to create a shape, which can make for some interesting effects. In this next example, I have created a gradient which goes from blue to transparent; your gradient will need to have a transparent or semi-transparent area in order to use shapes. Once again, I have used generated content to add the gradient and am then using the gradient in the value for `shape-outside`.

Once the gradient becomes fully transparent, then the shape comes into play, and the content runs along the edge of the gradient.

CSS 渐变就至关于一张图片,也就是说咱们能够用其来建立形状,这样咱们就能够制做出一些有趣的特效。在下面这个例子中,我建立了一个蓝色到透明的渐变(要使用形状,须要有必定的透明区域或半透明区域)。此次我一样使用了生成的内容做为渐变的载体和 shap-outside 的值。

在渐变过分到全透明的地方,就会造成形状,也是内容所环绕的边界。

使用 shape-image-threshold 来支持环绕半透明图片

展开原文 So far we have looked at using a completely transparent part of an image or of a gradient in order to create our shape, however, the third property defined in the CSS Shapes specification means that we can use images or gradients with semi-opaque areas by setting a threshold. A value for `shape-image-threshold` of `1` means fully opaque while `0` means fully transparent.

A gradient like our example above is a great way to see this in action as we can change the shape-image-threshold value and move the line along which the text falls to more opaque areas or more transparent areas. This property works in exactly the same way with an image that has an alpha channel yet is not fully transparent.

到这里为止,咱们已经看到了如何使用图片或渐变的全透明部分来建立形状。其实,CSS 形状规范中定义的这第三个属性可让咱们经过设置一个透明度阈值来使用图片或渐变的半透明部分建立形状。这个属性的值为 1 时,表示彻底不透明;值为 0 时,表示全透明。

要观察它的效果,前一个例子中的渐变就是一个很好的对象,咱们能够改变其 shape-image-threshold 属性的值来使文本落在更加不透明的区域或更加透明的区域中的位置。对于有 alpha 通道的非全透明的图片,这个属性的效果彻底同样。

展开原文 This method of creating shapes from images and gradients is — I think — the most straightforward way of creating a shape. You can create a shape as complex as you need it to be, in the comfort of a graphics application and then use that to define the shape on your page. That said, there is another way to create our shapes, and that’s by using *Basic Shapes*.

上面这些建立形状的方法,在我看来,是最直接的。你能够经过先在图像处理类软件中按照你的须要建立任意复杂的形状,而后在页面中进行使用。其实我是想说还有另外一种方式建立形状,那就是使用基础形状 (Basic Shapes) 。

用基础形状建立 CSS 形状

展开原文 The Basic Shapes are a set of predefined shapes which cover a lot of different types of shapes you might want to create. To use a basic shape, you use the basic shape *type* as a value for `shape-outside`. This type uses functional notation, so we have the name of the shape followed by brackets (inside which are some values for our shape).

“基础形状”是一系列预约义的形状,它包含了许多你可能想要建立的各种形状。使用基础形状时,咱们使用的是基础形状的类型做为 shape-outside 的值。这种类型使用函数形式来表示的,因此他们的名字的尾部会有一对括号 (括号里面是一些关于咱们所需的形状的值) 。

The options that you have are the following:

你可使用的形状类型有如下这些:

  • inset()
  • circle()
  • ellipse()
  • polygon()
展开原文 We will take a look at the `circle()` type first as we can use this to understand some useful things which apply to all shapes which use the basic shape type. We will also have a look at the new tools in Firefox for inspecting these shapes.

In the example below, I am creating the most simple of shapes: a circle using shape-outside: circle(50%). I’m using generated content again, and I have given the box a background color, and also added a margin, border, and padding to help highlight some of the concepts of using CSS Shapes. You can see in the example that the circle is created centered on the box; this is because I have given the circle a value of 50%. That value is the <shape-radius> which can be a length or a percentage. I’ve used a percentage so that the radius is half of the size of my box.

在下面的例子中,我建立是最简单的形状之一:一个圆,使用的是 shape-outside: circle(50%)。此次我仍是使用生成的内容,并给了这个 box 一个背景色,还设置了一个外边距、边框和内边距,以此来着重展现使用 CSS 形状的一些概念。在这个例子中,你能够看到,这个圆居中在这个 box 中;这是由于我给了这个圆一个 50% 的值。这个值的定义为 <shape-radius> (译注:形状的半径),它能够是一个长度值,也能够是一个百分比。

展开原文 This is a really good to time have a look at the shape that has been created using the Firefox Shape Path Editor. You can inspect the shape by clicking on the generated content and then clicking the little shape icon next to the property `shape-outside`; your shape will now highlight.

如今就是咱们用 Firefox 的 Shape Path Editor 来查看一下这个形状的好时机。点击生成的内容,而后点击其 shape-outside 属性旁的图标,就能够将形状高亮显示出来。

The shape highlighted with a line

展开原文 You can see how the circle extends to the edge of the margin on our box. This is because the initial *reference box* used by our shape is `margin-box`. You already know something of reference boxes if you have ever added `box-sizing: border-box` to your CSS. When you do this, you are asking CSS to use the `border-box` and not the default `content-box` as the size of elements. In Shapes, we can also change which reference box is used. After any basic shape, add `border-box`to use the border to define the shape or `content-box` to use the edge of the content (inside the padding). For example:

你能够看到,这个圆的范围触及到了外边距的外边缘上,这是由于咱们的形状默认使用的参照盒子 (reference box) 是 margin-box。若是你以前有添加过 box-sizing: border-box,你其实就已经知道什么是参照盒子,当你添加这个属性时,就是在告诉 CSS 要使用 border-box 而不是默认的 content-box 做为元素的尺寸。在形状的使用中,咱们一样能够调整其所使用的参照盒子。在任意基础形状以后,加上 border-box 表示使用边框来定义形状,加上 content-box 则使用内容区域 (在 padding 以内) 的边缘的来定义。例如:

.content::before {
    content: "";
    width: 150px;
    height: 150px;
    margin: 20px;
    padding: 20px;
    border: 10px solid #FC466B;
    background: linear-gradient(90deg, #FC466B 0%, #3F5EFB 100%);
    float: left;
    circle(50%) content-box;
}
复制代码

You will see the circle appear to become much smaller. It is now using the width of the content — in this case the width of the box at 150px — rather than the margin box which includes the padding, border, and margin.

这样,你就会发现这个圆看上去严重缩小了,它如今使用的是内容区域的宽度——本例中为 150px ——而不是包含了内边距、边框和外边距的 margin-box。

A smaller circle is highlighted

Inspecting your element in Firefox DevTools will also show you the reference boxes so you can choose which might give you the best result with your particular shape.

在 Firefox 的开发者工具中对这个元素进行审视 (inspecting) ,会展现出它的各种参照盒子,据此你能够选择出特定形状下效果最好的那个。

Highlights showing the margin, border and padding

circle() 的位置值

展开原文 A second value can be passed to `circle()` which is a position; if you do not pass this value, it defaults to `center`. However, you can use this value to pull your circle around. In the next example, I have positioned the circle by using `shape-outside(50% at 30%)`; this changes where the center of the circle is positioned.

circle() 中的第二个值表示的是位置,若是你不指定的话,默认为 center。你能够利用这个值来任意调整你的圆所在的位置。在接下来的例子中,我使用 shape-outside(50% at 30%) (译注:这明显是原文的笔误,正确的是 circle(50% at 30%)) 来设置这个圆的位置,它调整的是这个圆的中心点所处的位置。

clip-path

展开原文 Something useful to know is that the same `` values can be used as a value for `clip-path`. This means that after creating a shape, you can clip away the image or background color that extends outside of the shape. In the example below, I am going to do this with our example gradient background, so that we end up with a circle that has text curved around from our square box.

一个有用的知识是,基础形状一样可使用在 clip-path 上;也就是说在建立了一个形状值后,你能够把超出了形状以外的图片和背景颜色部分剪掉。在下面这个例子中,我将用咱们的渐变背景的例子来展现,咱们会获得一个围绕着弯曲了的文本的圆。

All of the above concepts can be applied to our other basic shapes. Now let’s have a quick look at how they work.

本段讲的这些,对咱们的其余基础形状一样适用。如今让咱们来看下一他们是如何使用的。

INSET()

展开原文 The `inset()` value defines a rectangle. This might not seem very useful as a float is a rectangle, however, this value means that you can inset the content wrapping your shape. It takes four values for top, right, bottom, and left plus a final value which defines a border radius.

In the example below, I am using the values to inset the content on the right and bottom of the floated image, plus adding a border radius around which my content will wrap using shape-outside: inset(0 30px 100px 0 round 40px). You can see how the content is now over the background color of the box:

inset() 值定义的是一个矩形。这看上去好像没什么用,由于浮动元素自己就是矩形;其实它的真正的涵义是你能够将文本内敛 (inset) 进来。它接收四个参数,分别为顶部、右侧,底部和左侧,再加一个圆角半径值。

在下面这个例子中,我使用 shape-outside: inset(0 30px 100px 0 round 40px) 来将内容从右侧和底部内敛进来,在加上一个圆角半径。如今,你能够看到这些内容将如何覆盖到盒子的背景颜色上:

ELLIPSE()

展开原文 An ellipse is a squashed circle and as such needs two radii for x and y (in that order). You can then push the ellipse around just as with circle using the position value. In the example below, I am creating an ellipse and then using clip-path with the same values to remove the content outside of my shape.

椭圆就是被压扁了的圆,因此咱们须要有两个半径:x 和 y (建立时顺序与此一致) 来建立,也一样也能够像圆同样经过位置值来任意调整位置。在下面这个例子中,我建立了一个椭圆并把相同的值使用在 clip-path 属性上。

In the above example, I also used shape-margin to demonstrate how we can use this property as with our image generated shapes to push the content away.

在这个例子中,我还使用了 shape-margin 属性,为的是演示如何配合使用这个属性,将内容推开必定距离。

POLYGON()

展开原文 Creating polygon shapes gives us the most flexibility, as our shapes can be created with three or more points. The value passed to the polygon needs to be three or more pairs of values which represent coordinates.

It is here where the Firefox tools become really useful as we can use them to help create our polygon. In the below example, I have created a polygon with four points. In the Firefox DevTools, you can double-click on any line to create a new point, and double-click again to remove it. Once you have created a polygon that you are happy with, you can then copy the value out of DevTools for your CSS.

多边形形状的建立可让咱们拥有最大的灵活性,由于咱们的形状能够用三个以上的点来建立。传递到多边形中的值须要至少3对表示坐标的值。

这个时候 Firefox 就变得很是有用了,由于他能够帮助咱们建立多边形。下面这个例子中,我建立了一个由四个点组成的多边形,在 Firefox 的开发者工具中,你能够在任意一条边上双击来添加一个新的点,再次双击能够移出这个点。在你建立出了让你满意的多边形后,你就能够将其从开发者工具中拷贝出来用到你的 CSS 中。

兼容性问题 (FALLBACKS)

展开原文 As CSS Shapes are applied to a float, in many cases the fallback is that instead of seeing the content wrap around a shape, the content will wrap around a floated element (in the way that content has always wrapped around floats). Browsers ignore properties they do not understand, so if they don’t understand Shapes, it doesn’t matter that the `shape-outside` property is there.

Where you should take care would be in any situation where not having shapes could mean that content overlaid an area which made it difficult to read. Perhaps you are using Shapes to push content away from a busy area of a background image, for example. In that case, you should first make sure that your content is usable for the non-Shapes people, then use Feature Queries to check for support of shape-outside and overwrite that CSS and apply the shape. For example, you could use a margin to push the content away for non-Shapes visitors and remove the margin inside your feature query.

由于 CSS 形状是应用在浮动元素上的,因此在大多数状况下出现兼容性问题时,咱们看的将会是内容围绕着浮动元素 (就和通常状况下的同样),而不是围绕着形状排布。浏览器会把他所不支持的属性忽略掉,因此若是它们不支持形状,把 shape-outside 属性放上去也不会有什么影响。

你真正须要考虑的问题是,在不支持形状的状况下,会使得内容难以阅读的内容排布情形。一般咱们使用形状,都会把内容隔开必定距离。在这种情形下,你应该首先确保那些不支持形状的用户,而后再使用特性查询(Feature Query)来检查 shape-outside 的支持状况,并进行 CSS 覆盖和应用形状。例如,你能够为不支持形状的用户设置一个外边距,以此将内容推开;而后在特性查询中将这个外边距移除。

.content {
    margin-left: 120px;
}

@supports (shape-outside: circle()) {
    .content {
        margin-left: 0;
        /* add the rest of your shapes CSS here */
    }

}
复制代码
展开原文 With Firefox releasing their support we now only have one main browser without support for Shapes — Edge. If you want to see Shapes support across the board you could go and [vote for the feature here](https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/6263716-shapes), and see if we can encourage the implementation of the feature in Edge.

随着 Firefox 发布了对形状的支持,如今剩下惟一还不支持形状的主流浏览器就是 Edge 了。若是你但愿看到形状广受支持,你能够前往这里为这个特性投一票

更多关于 CSS 形状的信息

展开原文 In this article, I’ve tried to give a quick overview of some of the interesting things that are possible with CSS Shapes. For a more in-depth look at each feature, check out the [Guides to CSS Shapes](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes) over at MDN. You can also read a [guide to the Shape Path Editor in Firefox](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Edit_CSS_shapes).

在本文中,我试着对 CSS 形状可能的用途作了一个概览。关于每一个特性更详细的信息,能够查看 MDN 上的 Guides to CSS Shapes (CSS 形状指导)。另外还能够查看 guide to the Shape Path Editor in Firefox (Firefox 的 Shape Path Editor 使用指导) 。

相关文章
相关标签/搜索