CSS Shapes 101

编辑推荐: 掘金是一个高质量的技术社区,从 CSS 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货。 点击链接查看最新前端内容,或到各大应用市场搜索「 掘金」下载APP,技术干货尽在掌握中。

本文由99根据SARA SOUEIDAN的《CSS Shapes 101》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://alistapart.com/article/css-shapes-101,以及作者相关信息

作者:SARA SOUEIDAN

译者:99

方块套方块:这是我们网页一直以来的样子。通过使用CSS,我们一直试图摆脱这种创建几何形状的限制,但这些形状没有影响形状内的内容,或者与页面其他元素相互影响。

Adobe在2012年中期提出的新的CSS shapes 规范 改变了这一现状。它的目标是为web设计人员提供一种新的方式,来使内容流入或者环绕在任意复杂的形状上——除了使用javascript,我们从来不曾做到这点。

例如,注意以下设计中,周围的文本流环绕在圆形图片周围。没有css shapes,文本将形成矩形,从而失去了元素相互之间的联系,而这个联系是可以让设计更上一层楼的。

CSS Shapes 101

注意这个例子中文本环绕在碗周围这个设计。使用CSS shapes,我们可以创建类似的web设计。让我们了解css shapes是如何工作的,以及如何开始使用它们

浏览器支持

CSS shapes目前只在Webkit Nightly和Chrome Canary版本支持,,但其规范的模块级别1已经达到候选推荐标准状态,所以规范中定义的属性和语法是相当稳定的。他们在其他浏览器中实现的时间不会很久。这个级别侧重于使用形状属性,来改变一个环绕在某形状旁的内容流的布局。更具体地说,它关注的是shape-outside属性及其相关属性。

结合其他先进功能,如剪切和蒙版,CSS滤镜,合成和混合模式,CSS shapes 将使我们在无须诉诸做图软件(如photoshop或者indesign)的情况下,创造更多绚丽且复杂的设计。

未来的CSS形状将专注于形状内的内容。例如,我们很容易使用css创建菱形形状:元素旋转45度,然后旋转内容,使内容保持水平。但菱形里面的内容不会受到其容器的菱形形状的影响,并将永远是矩形。CSS形状shape-inside属性实现时,我们能够使内容也排列成菱形,从而使使布局如下图所示。

CSS Shapes 101

很快,CSS形状也允许文本内部形状,像这样的菱形一样,适应它的容器的边缘,而不是溢出或被切断。为了在Chrome canary上使用CSS形状,你必须启用实验功能。

如果你不知道如何做到这一点,看看Adobe的博客上介绍的方法

建立一个CSS形状

你可以使用shapes属性,把一个形状应用到一个元素上。你需要把形状属性的值定义为一个形状函数。形状函数传递参数,从而定义你想要适用于元素的形状。

CSS Shapes 101

形状可以通过以下的函数来创建:

  • circle()
  • ellipse()
  • inset()
  • polygon()

每一个形状是都是由一组点定义的。有些函数把点作为参数,另外一些则采用偏移量--最终他们都会在元素上绘制一个由一组点组成的形状。我们在下面的例子中覆盖到每个函数的参数。

形状也可以经由从图像中提取的alpha通道来定位。当一个图像传递给形状属性时,浏览器将基于shape-image-threshold属性来提取图像的形状。

定义的形状是alpha值大于设定的threshold(阈值)的那些像素。图像必须是CORS兼容的。如果提供的图片因任何理由不能显示 (例如图片不存在),元素不会被应用任何的形状。

以下的形状属性,接受上面的函数做为值:

  • shape-outside:在一个形状(外)包裹内容
  • shape-inside:在一个形状内包裹内容

可以使用shape-outside属性结合shape-margin属性添加一个带有边距的形状,从而将内容推离形状,以便在形状和内容之间创造更多的空间。同样我们也可以把shape-insideshape-padding属性相配合,来增加文字跟形状的距离。

可以简单的添加一行CSS,来使用形状属性和函数来声明一个元素上的形状:

.element {
    shape-outside: circle(); /* content will flow around the circle defined on the element */
}

或者:

.element {
    shape-outside: url(path/to/image-with-shape.png);
}

如果你把这条CSS应用到元素上,形状不会应用到元素上,除非满足两个条件:

  1. 元素必须是浮动状态的。下一级别的css shapes可能会允许我们在未浮动元素上定义形状,但不是现在。
  2. 元素必须包含维度。给元素设置好高度和宽度即可给元素建立一个维度坐标系。

如您所见,在上面的函数定义中,定义了构成形状的点集。因为这些点都包含坐标,因此一个坐标系统是很重要的,坐标系统可以让浏览器知道元素上每个位置该放置哪个点。所以,上面的例子如果包括以下类似代码,形状就会生效:

.element {
    float: left;
    height: 10em;
    width: 15em;
    shape-outside: circle();
}

然而,给予一个元素内在维度并不影响其响应性(稍后我们将进一步讨论)。

因为每个形状是由一组坐标点定位的,改变一个点的坐标将直接影响创建的形状。例如,下面的图片显示了一个六角形状,可以使用polygon()函数创建。形状是由6个点构成的。改变橙色点的水平坐标,会改变产生的形状,并将影响任何应用这种形状元素内部及外部的内容。

CSS Shapes 101

如果元素向右浮动,并应用这种形状,当polygon()函数内,橙色点的坐标改变时,左边的内容将会改变。

Shape的参考盒模型

CSS shapes 通过参考盒来定义并且创建,这个盒子用来绘制元素上的形状。除了元素的高度和宽度,元素的盒模型——margin box,content box,padding box,和border-box也作为指定元素形状的参考。

有关于box-sizing的相关知识,可以点击早前的相关教程进行了解。——@大漠

默认情况下,使用margin box盒模型作为参考,因此如果你想应用形状的那个元素底部有一个边距,你在元素上定义的那个形状将扩展到外边距的边缘,而不是元素的边缘。如果您想要使用另一种盒模型,您可以同时指定盒模型与形状函数,之后传递给形状属性:

shape-outside: circle(250px at 50% 50%) padding-box;

上面的规则中padding-box关键字表明,形状会适用于元素的padding box(padding 盒模型)。circle()函数定义了元素上形状为圆形,以及圆形的大小和位置。

用shape函数来定义shapes

我们以把一些信息包裹在圆形头像周围作为尝试,你有可能会用这个去展示用户档案信息。

CSS Shapes 101

使用CSS shapes,文本不会保持矩形,而会包裹在圆形头像的周围。

我们会使用circle()函数来给一个头像应用圆形,使用下面的html:

<img src="http://api.randomuser.me/0.3.2/portraits/men/7.jpg" alt="profile image" />

<p>Lorem ipsum dolor sit ...</p>

<p>Assumenda blanditiis ...</p>

你可能会问,为啥不用border-radius来让图片变成圆形?

答案是这样的,border-radius属性对元素外部或者内部的内容流没有影响-他不会影响元素的内容区域,或者浮动在元素周围的内容区域。

它只会影响一个元素的边界或者背景。背景区域是通过应用圆角属性,对圆角进行裁切创造的,仅此而已。元素的内容仍将保持矩形,内容以外的元素看起来仍会把这个元素当作一个矩形,因为元素本来还是矩形。我们使用圆角边框属性可以把元素或者图片变为圆角,如下图所示:

img {
    float: left;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    margin-right: 15px;
}

CSS Shapes 101

没有CSS shapes,文本认为图像是矩形的,因此会包裹在一个矩形周围,而不是一个圆形。在浏览器不支持CSS shapes的情况下,圆形图周围的内容仍然会环绕着这个圆形。这也是一个旧浏览器的回退(优雅降级)方案。

为了改变内容来适应特定的形状,使用形状属性。

img {
    float: left;
    width: 150px;
    height: 150px;
    border-radius: 50%;

    shape-outside: circle();
    shape-margin: 15px;
}

这段代码,文本将“观测到”图片是圆形的,随后环绕这个圆形,如第一个截图所示。(你可以在线看效果)。在不支持的浏览器下面,它将回退到第二个图片所展示的结果。

您可以直接使用circle()函数,或者传递参数给这个函数。其官方的语法是:

circle() = circle( [<shape-radius>]? [at <position>]? )

问号表示,这些参数是可选的,可以省略。如果省略,参数被浏览器设置为其默认值。当你使用circle(),且不显式地设置它的位置,它将默认为一个圆心在元素中心的的圆。

你可以使用任何单位指定圆的半径长度 (px,em,pt等)。您还可以使用closest-sidefurthest-side来指定半径,默认为closest-side,这意味着浏览器将使用从元素的中心到距离最近的边缘的长度作为半径。farthest-side使用从中心到最远的边缘的长度作为半径。

shape-outside: circle(farthest-side at 25% 25%); /* defines a circle whose radius is half the length of the longest side, positioned at the point of coordinates 25% 25% on the element’s coordinate system*/

shape-inside: circle(250px at 500px 300px); /* defines a circle whose center is positioned at 500px horizontally and 300px vertically, with a radius of 250px */

CSS Shapes 101

除了半径参数,ellipse()函数类似circle()函数,具有相同的参数列表。而半径这个参数在ellipse函数中则是两个:一个为x轴的半径的长度,另一个为y轴。

ellipse() = ellipse( [<shape-radius>{2}]? [at <position>]? )

当形状不是一个圆或椭圆,可以使用inset()函数用于在元素内创建矩形形状。因为元素已经是矩形的,我们不需要生成更多的矩形。相反,inset()可以帮助我们创建内容环绕在四角的圆角矩形。

CSS Shapes 101

inset()函数接受一个到四个偏移值,指定相对于参考盒的偏移量。这些值标明了矩形是如何插入到元素中的。函数还有一个可选参数用以把内部的矩形圆角化。这个参数跟border-radius指定的圆角是完全一样的,可以配合round关键字,使用一到四个值。

inset() = inset( offset{1,4} [round <border-radius>]? )

下面的代码将会在一个浮动元素中创建一个圆角矩形:

.element {
    float: left;
    width: 250px;
    height: 150px;
    shape-outside: inset(0px round 100px) border-box;
}

点击查看在线效果

最后一个形状函数是polygon(),它使用任意数量的点,定义了更复杂的任意形状。函数接收一组坐标作为参数,每一组坐标指定一个点的位置。这些点集合组成形状。在接下来的例子中,一个图像向右浮动,占据整个屏幕的高度。我们想要使左边的文本包裹右边的沙漏,需要使用polygon()函数来定义一个形状不规则的图像。

CSS Shapes 101

以上图片的css类似下面的代码:

img.right {
    float: right;
    height: 100vh;
    width: calc(100vh + 100vh/4);
    shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
}

正如我这里写的一样,你可以用长度单位或百分比设置点的坐标,来定义形状。

这段代码本身就会产生上述结果,但如你所见,形状函数不影响你定义的形状以外,其余部分的图片。事实上,在元素上应用形状函数,比如一个容器,一张图片等,只会影响内容流区域,背景、边界等一切保持不变。

这里文章写得很晦涩。。其实意思就是虽然图片变成了漏斗型,但这个形状只影响旁边的文字,你还会看到一张完整的图片。——@99

为了可视化观察我们创建的多边形的形状,我们需要“裁切”掉形状外面的图像。这就是clip-path属性,这个属性可以从CSS mask 模块中找到。

clip-path接收与形状属性相同的形状函数和值。如果我们定义相同的多边形形状,同时用于shape-outsideclip-path属性上,它将裁掉图像上你定义的形状之外的图像。

img.right {
    float: right;
    height: 100vh;
    width: calc(100vh + 100vh/4);
    shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
    /* clip the image to the defined shape */
    clip-path: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
}

结果如下

CSS Shapes 101

带有-webkit-前缀的clip-path属性可以被chrome支持,你可以在这里查看在线演示

clip-path属性跟形状属性是一对好基友,因为它有助于可视化创建的形状和裁剪形状之外的元素,所以你可能会发现,很多情况下这两个属性会一起使用。

多边形polygon()函数也接受一个可选的关键词作为参数,可以是nonzeroevenodd。这指定当多边形内部出现相交时,如何确认是否为多边形的内部区域。有关详细信息,请参阅SVG fill-rule属性。

有关于SVG的更多参考资实可以点击这里这里。——@99

利用图片来定义一个形状

使用一个图像来定义形状,图像需要一个alpha通道才可以让浏览器提取形状。

形状是由这样定义的:当图像内像素的alpha值大于某个阈值。这个阈值默认值为0.0(完全透明),或者你可以直接使用shape-image-threshold属性。因此,图像中任何不透明的像素,都会被用来定义形状。

未来的CSS形状估计可以定义一个开关变量,来切换是否使用图像的alpha通道或者是图像的亮部数据。如果有这种情况,shape-image-threshold将根据开关状态,来确定alpha通道或亮度的阈值。

我们将用下面的图像定义一个形状,并用文字包裹起来:

CSS Shapes 101

使用shape-outsideurl()值来指向这张图片,我们可以用这个属性来让内容围成树叶的形状。

.leaf-shaped-element {
    float: left;
    width: 400px;
    height: 400px;
    shape-outside: url(leaf.png);
    shape-margin: 15px;
    shape-image-threshold: 0.5;
    background: #009966 url(path/to/background-image.jpg);
    mask-image: url(leaf.png);
}

当然,如果你要把叶子形状作为元素背景,那图像中形状之外的需要被裁减掉。你可以使用mask-image属性(用适当的前缀)做到这一点,因为clip-path属性并不能接收一个alpha图片作为值。结果如下所示:

CSS Shapes 101

如果你需要创建复杂的形状,您可能想要使用图像定义一个形状。你可以在Photoshop中制作图像,来代替手动定义的点。

你也可以用图片来生成一个形状,这个形状非常复杂,你需要很多浮动在上面的部分。如果图片包含多个区域,浏览器将从图像中提取这些区域并应用到元素上。

响应式设计中的css shapes

CSS shapes 可以融入我们的响应式工作流吗?当前规范中shape-outside是可以的,因为它允许通过百分比或其他的尺寸长度单位来指定元素,点定义的形状(形状函数的参数)也可以用百分比表示。这意味着一个元素的shape-outside是充分响应的,就像任何浮动中应用比例尺寸一样。shape-inside是不能响应的,但那是因为它是属于模块级别 2级的。目前很多的限制将在未来解决。

Shape工具

使用形状函数创建复杂的形状有可能非常艰难,特别是如果你通过许多的点和坐标,通过polygon()函数创建一个多边形时。

值得庆幸的是,Adobe的web平台团队一直致力于开发交互式工具使这更容易。贝尔特拉维斯已经创建了一个形状工具,使我们能够可视化的创建多边形形状。这个工具可以根据形状生成形状函数。这是非常有用的,但如果你想创建一个基于特定图像的形状就不可以了,因为这个工具不支持插入图像然后创建形状。

更先进,更富有交互力图形工具是由Adobe网络平台团队开发的。近日发布的工具作为Adobe免费的Brackets编辑器的扩展。它允许您可视化的在浏览器中直接编辑形状,并提供实时预览功能,当改变它们的形状时更新样式表的值。你的更改会有即时的视觉反馈,让你能够了解到你的形状是如何与页面上的其他元素进行交互的。

CSS Shapes 101

在浏览器中编辑多边形形状,并在右边使用bracket的实时预览模式来预览。Razvan Caliman进行屏幕截图。

此工具将是不可或缺的,因为它有助于创建、编辑和调试我们的形状。Razvan Caliman 在博客上写了一篇文章,解释了如何在brackets中使用图形编辑器,。你可以现在就尝试使用一下它。

未来css exclusion

CSS shape规范包含CSS shape和exclusion规范,但这两个规范是分离的。CSS shapes定义了shape-inside形状和shape-outside,CSS exclusion将允许我们让非浮动元素周围包裹内容,如绝对定位元素。这将有可能造成以下效果:来自不同方向的内容包裹了整个形状,如下图所示。

CSS Shapes 101

使用图形元素并且元素绝对位在中间的布局,也可以让元素的文本围绕在各个方向,也可以是以他为中心围绕。

未来的css shapes

当前的CSS形状规范仅仅是第一步。很快,我们将会拥有更多的选择来创建形状和在其周围包装内容,使我们只需要几行代码,就可以把我们的html转化为生动的设计。今天,规范的制定者在关注shape-outside,您可能会看到CSS shapes 在2014年底得到更多的浏览器支持。

你今天可以把使用css shapes作为一个渐进增强工作的一部分,同时对于不支持的浏览器也有回退方案可以处理。我最近开始将它们应用到自己的网站,并且在不支持的浏览器下显示很正常。“对于更复杂的设计,你可以使用一个脚本检查浏览器是否支持css shapes,且提供任何你想要的回退方案。您还可以使用此脚本扩展Modernizr的测试来测试浏览器是否支持shape-outside,或者下载一个包含这个测试的自定义构建版本。

CSS shapes 给打印与web页面带来了更高的区分度。本文中的示例很简单,但打好了基础,你可以实现杂志或者出版物一般的设计效果——而不需要担心在屏幕上需要重新设计一遍。你所探索的,从非矩形布局动画形状——是时候搞起了。

译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!

关于玖玖

阿里巴巴国际站前端工程师,关注javascript应用与数据可视化。个人博客新浪微博Github,欢迎与同学一起共勉。

如需转载烦请注明出处:

英文原文:http://alistapart.com/article/css-shapes-101

中文译文:http://www.w3cplus.com/css3/css-shapes-101.html

返回顶部