原文:Take A New Look At CSS Shapes
做者:Rachel Andrew 发表时间:september 4, 2018
译者:西楼听雨 发表时间: 2018/9/16
(转载请注明出处)css
摘要:在本文中,咱们将对 CSS 形状的概念,以及如何用图片、渐变和基础形状来建立非矩形类的形状作一个讲解。另外咱们还会讲到 Firefox 的新工具是如何让咱们编辑形状变得简单的。web
CSS 形状第一阶段规范已经在 Chrome 和 Safari 中实现了有好几年了,而随着 Firefox 62 在本周发布,Firefox 也已经在生产版本中支持了——另外随之发布的还有一个很棒的开发者工具功能,它对咱们使用形状能够带来帮助。在本文中,咱们将看下一能够用 CSS 形状作哪些事情。也许是时候考虑给咱们的设计添加一些曲线效果了!浏览器
The CSS Shapes specification Level 1 defines three new properties:服务器
CSS 形状规范的第一阶段 (CSS Shapes Level 1) 定义了三个新的属性:app
shape-outside
shape-image-threshold
shape-margin
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
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-outside
and 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
属性,便可实现将非透明区域的边线所造成的路径做为形状。
为了将文本从图片上推开,咱们可使用 shape-margin
属性,它能够在形状及其周围的内容之间设置一个边界。
上面的例子中,咱们将图片展现在页面中,并使得文本环绕着它弯曲。其实,你也能够作到在不展现那张图片的状况的同时使用那张图片的形状做为环绕路径来得到一样的效果。不过要作到这种效果,咱们仍然须要有一个浮动的元素,为此,咱们能够用生成的内容 (Generated Content;[译注] 这里指伪类) 来充当。
在这个例子中,咱们经过插入生成的内容,并将其浮动到左侧,给其设置宽度和高度,而后使用以前的图片做为 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
的值。
在渐变过分到全透明的地方,就会造成形状,也是内容所环绕的边界。
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 通道的非全透明的图片,这个属性的效果彻底同样。
上面这些建立形状的方法,在我看来,是最直接的。你能够经过先在图像处理类软件中按照你的须要建立任意复杂的形状,而后在页面中进行使用。其实我是想说还有另外一种方式建立形状,那就是使用基础形状 (Basic Shapes) 。
“基础形状”是一系列预约义的形状,它包含了许多你可能想要建立的各种形状。使用基础形状时,咱们使用的是基础形状的类型做为 shape-outside
的值。这种类型使用函数形式来表示的,因此他们的名字的尾部会有一对括号 (括号里面是一些关于咱们所需的形状的值) 。
The options that you have are the following:
你可使用的形状类型有如下这些:
inset()
circle()
ellipse()
polygon()
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>
(译注:形状的半径),它能够是一个长度值,也能够是一个百分比。
如今就是咱们用 Firefox 的 Shape Path Editor 来查看一下这个形状的好时机。点击生成的内容,而后点击其 shape-outside
属性旁的图标,就能够将形状高亮显示出来。
你能够看到,这个圆的范围触及到了外边距的外边缘上,这是由于咱们的形状默认使用的参照盒子 (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。
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) ,会展现出它的各种参照盒子,据此你能够选择出特定形状下效果最好的那个。
circle()
中的第二个值表示的是位置,若是你不指定的话,默认为 center
。你能够利用这个值来任意调整你的圆所在的位置。在接下来的例子中,我使用 shape-outside(50% at 30%)
(译注:这明显是原文的笔误,正确的是 circle(50% at 30%)
) 来设置这个圆的位置,它调整的是这个圆的中心点所处的位置。
一个有用的知识是,基础形状一样可使用在 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.
本段讲的这些,对咱们的其余基础形状一样适用。如今让咱们来看下一他们是如何使用的。
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)
来将内容从右侧和底部内敛进来,在加上一个圆角半径。如今,你能够看到这些内容将如何覆盖到盒子的背景颜色上:
椭圆就是被压扁了的圆,因此咱们须要有两个半径: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
属性,为的是演示如何配合使用这个属性,将内容推开必定距离。
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 中。
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 */
}
}
复制代码
随着 Firefox 发布了对形状的支持,如今剩下惟一还不支持形状的主流浏览器就是 Edge 了。若是你但愿看到形状广受支持,你能够前往这里为这个特性投一票。
在本文中,我试着对 CSS 形状可能的用途作了一个概览。关于每一个特性更详细的信息,能够查看 MDN 上的 Guides to CSS Shapes (CSS 形状指导)。另外还能够查看 guide to the Shape Path Editor in Firefox (Firefox 的 Shape Path Editor 使用指导) 。