CSS Shapes:打破矩形设计的限制
本文由尤小博根据Patrick Catanzariti的《CSS Shapes: Breaking the Rectangular Design Shackles》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明原作者相关信息http://www.sitepoint.com/css-shapes-breaking-rectangular-design。
——作者:Patrick Catanzariti
——译者:尤小博
HTML5和CSS3的功能完全超越5年前我们在web上所能做的事。CSS Shapes Module Level 1(CSS形状模块标准1)规范有可能打破web中矩形盒模型的限制而且将网页设计提升到新的高度。它允许元素设计成不同的形状(圆形或五边形的div
),并且用更自然的方式让文字环绕着元素(文字可以环绕着你的曲线设计而不一定要有直角边界)。本文将通过一些小演示来检测CSS Shapes的可能性,并且帮助你开始探索之旅!
关于Shapes规范
该规范是一份向相关工作小组或W3C团队以外的人群公开征求参考实现和技术反馈的候选推荐标准。
基本上,这意味着在web开发社区里web开发者准备为尽可能达成一致的规范而进行尝试,并分享他们的想法和创意。虽然现在还不是主流用法,但是现阶段他们在探索其如何在未知领域使用显得至关重要。
如果你只是一个开发人员而平时不会摆弄那些不广泛使用也不跨浏览器兼容的东西,那么这篇文章可能不适合你,但是我鼓励你有时间去尝试一两个演示,也希望看到你有可能将这些新特性应用到你未来的设计中。
你需要用什么来试验CSS Shapes
为了开发和试验这个规范,你需要确认你正在使用一款受支持的浏览器。目前支持以下版本:
如果正使用Chrome浏览器(非Canary版本),可以粘贴以下代码到地址栏:
chrome://flags/#enable-experimental-web-platform-features
然后在“启用实验性网络平台功能”下点击“启用”,最后选择“立即重新启动”来重启浏览器,给其全新的CSS超级功能。
有了那些介绍扫清阻碍,让我们开门见山看看Shapes规范提供些什么功能。
shape-outside
属性
我们将探索的第一个领域是shape-outside
新属性,其在元素的周围定义一个与众不同的浮动区域。元素把围绕在它周围的文字流包裹成圆形、多边形或者椭圆形,而不只是矩形。它在元素的浮动盒子边界里裁剪好一个可以被文字环绕的新区域。
我将从F. Winslow的《The children's fairy geography, or, A merry trip round Europe》一书中带来一些生活片段贯穿到我的演示里。大英博物馆最棒的地方在于它可以让一堆作品进入到公共领域,而儿童类书籍刚好是其中之一(也恰好有一堆不同大小的图像!)
我们第一个超级简单的例子如下:
HTML看起来如下:
<h1>Laplanders</h1>
<img src="http://www.patrickcatanzariti.com/experiments/css3/cssshapes/lapland.png" class="lapland" />
<p>They can bend bows most easily that the most powerful Swedes or Norwegianscould not bend at all. They dress,as you see, altogether in skins or coarse wool. The women dress very like the men, turning their hair up in a funny kind of knot.</p>
我们为图片元素(.lapland
)添加shape-outside
属性:
.lapland {
float: left;
shape-outside: inset(1% round 45%);
}
结果是图片的转角变得与图形的自然边框半径很吻合:
请在支持的浏览器上查看,这儿有一个CodePen演示:
在下一节,我们将更仔细地介绍这个例子和inset
函数设置。
可能会有什么样的形状
shape-outside
属性允许我们使用一些不同的函数来定义形状:
inset()
inset()
函数允许你在浮动区域里边定义一个内部矩形。如果你想要把文字和图片重合在一起,这种想法将会是有用的。也许你不介意将文字移进到周围有一点血色的图片里面,或者想在图片的周围保留一些空白,或者想要其他的样式。inset()
函数都能使这些成为可能!
定义矩形的top
、right
、bottom
、left
位置与你如何定义margin
和padding
相似:
shape-outside: inset(10px, 5px, 10px, 5px);
就像在改变margin
/padding
的值一样,你可以缩短它们的长度,所以下面给出一个内嵌矩形,其离元素所有边缘长度相差1% 。
shape-outside: inset(1%);
你也可以给这个矩形设置各种border-radius
样式,为圆形容器提供各种可能性。这实际上就是我看到inset()
函数在设计中特别有价值的地方。
如果你添加“圆”,然后使用常规border-radius
语法指定大小,那么就会出现上述举出的圆形容器。这是我们在上面Laplander例子中所做的。
我会做一些变动来解释我们更早前的例子。下面的代码给元素一个10像素border-radius
,其插图离图片边缘的长度差1%:
shape-outside: inset(1% round 10px);
我们在上面的例子遵循这一模式,但是用更大的圆的半径来匹配我们的图片:
shape-outside: inset(1% round 45%);
你可以进一步用这些设置在每个圆角上给予不同的border-radius
值,例如:下面给予左上角(top left
)5px,右上角(top right
)10px,右下角(bottom right
)5px,左下角(bottom left
)5px:
shape-outside: inset(1% round 5px 10px 5px 5px);
circle()
如果在你的图片里有一个真正的圆形,那么你可以这样设置浮动区域来匹配这个圆形:
shape-outside: circle();
为了论证这是如何执行的,让我们说一说下面这个案例:
通过添加上面的代码到图片(在上面屏幕截图的右上角)里,我们得到一下效果:
在CodePen上的实例:
设置圆的半径
你可以在circle()
函数的第一个参数里设置圆的半径。
默认情况下,圆的半径是元素宽度的一半:
shape-outside: circle(50%);
你可以将半径设置为25%来设置圆形浮动区域,相当于元素的一半宽。
shape-outside: circle(25%);
有另外两个更新但相当整洁的方法来设置圆的半径:closest-side
和 farthest-side
,它们定义浏览器应该如何利用元素自身的边界来计算出圆的半径。这两个方式只用在有矩形元素的情况下,而当元素是一个正方形的时候,这些方法将没有区别。
closest-side
计算从元素的边缘到中心的最近距离为圆的半径。这是默认值,所以使用circle()
本身会等效于circle(closest-side)
。如果我们有个矩形元素并且如下使用:
shape-outside: circle(closest-side);
closest-side
将确保圆紧贴着容器的内部如下图所示(我已经在图片的边缘添加橙色边框,所以你可以看到边界在哪里):
在CodePen上查看一下:
farthest-side
,换句话说,计算从边缘到中心的最远距离为圆的半径。这将在一对边上修剪圆。如果我们有一个像上面一样的新矩形元素,但有一张被裁剪过的圆形图片,我们可以用farthest-side
:
shape-outside: circle(farthest-side);
将允许我们像这样在元素上包裹文字:
在CodePen上查看一下效果:
移动圆心
你可以使用关键词at
来移动圆的中心。在圆没有恰恰在图片的中心的情况下,或者在你希望从一条边缘来实现一个半圆的情况下,你可以使用这个。比如:如果我们在一个高大的图片上使用这个CSS:
shape-outside: circle(farthest-side at left);
我们可以实现一个圆,它的中心是在图片的左边,而它的高恰好是元素的高:
在CodePen上查看效果:
你可以为圆的中心使用一连串不同的定位值。理论上,CSS position 语法所允许的情况,他都支持:
shape-outside: circle(closest-side at center);
shape-outside: circle(closest-side at 10% 10%);
shape-outside: circle(closest-side at center);
你甚至可以得到很具体的半径和位置。例如:下面的CSS将创建一个圆,其宽度是元素的宽度一半,中心在元素的左边(0)以及距离顶部25%的位置:
shape-outside: circle(25% at 0 25%);
ellipse()
如果你要一个椭圆形而不是一个圆形,你可以使用ellipse()
函数。就这个,椭圆的高和宽将分别是图片的高和宽,你可以像定义圆的半径一样来定义椭圆的半径——仅需要两个值:一个是x
半径,另一个是y
半径。
如下代码:
shape-outside: ellipse();
结果像这样:
在CodePen上查看效果:
设置椭圆的大小
我们可以用定义圆的半径一样的方法来构造不同大小的椭圆形,仅用到两个值:第一个是宽,第二个是高:
shape-outside: ellipse(25% 10%);
我这里仅仅是提供一种想法而已,可能还有更好的例子。我已经按上面定义的大小得到一张包含更小椭圆的图片(我已经再次添加橙色边框来展示图片的位置):
在CodePen上查看一下:
你也可以像定义圆一样通过closest-side
和farthest-side
定义椭圆的宽和高,只是对于椭圆,我们又得用两个值:宽和高:
shape-outside: ellipse(closest-side closest-side);
移动椭圆的圆心
你可以使用和circle
元素同样的方法来移动椭圆的中心:
shape-outside: ellipse(25% 10% at 0 25%);
polygon()
polygon()
函数可以对形状定义任意数量的点,使得文字流环绕着图片形状,哪怕是最难看的形状!
通过设置每个点的坐标来定义多边形,而坐标可以使用像素值或百分比,并且第一个点必须能够连接到最后一个点。
shape-outside: polygon(x1 y1, x2 y2, x3 y3, x4 y4, x5 y5);
举个例子,在页面开始,我们可以用非常华丽的插图组成一个“D”形:
然后我们可以像这样定义一个多边形浮动区域:
shape-outside: polygon(88% 0, 90% 15%, 83% 22%,
93% 31%, 100% 36%, 72% 73%,
35% 75%, 19% 100%, 0 100%,
0 0);
这些代码将调整浮动区域以便文字环绕着我们定义的特殊多边形:
在CodePen上查看效果:
但是...计算出多边形的坐标很难!
我同意。当涉及到复杂图片的时候,这是一件很痛苦的工作,尤其是用到百分比!这里有一个扩展(a Brackets extension)将可以帮助你走出困惑。
如果你不想使用扩展(Brackets),那么有一个简单的在线工具 可以计算出你想用的多边形形状。
你当然可以尝试一下是否能够寻找到一种更快获取多边形坐标的方法。或者你可以使用图片自身来设定多边形形状,下面我将讨论这个!
源自图片的形状
CSS Shapes非常便利的功能之一就是,如果你得到一个透明的PNG或者GIF图片,那么你可以使用alpha通道来定义浮动区域。正如下面两行代码一样简单:
shape-outside: url(b.png);
shape-image-threshold: 0.0;
URL格式就像是通常用来指定背景图片一样,它可以是与元素相同或者完全不同的图片。如果你很想要的话,你可以创建新图片,其唯一的目的是为形状定义alpha通道。这个比多边形稍微容易点,但是将会多一个额外的HTTP请求。
shape-image-threshold
属性定义你想要得到的不透明水平。0.0
是完全透明而1.0
是完全不透明。
在我的例子中,我已经用到0.0因为我的图片有完全透明的浮动区域:
上面的实例代码将有如下结果:
这儿有CodePen演示:
很重要的一点——如果你从文件系统 (e.g.file:///Users/philkensebben/Web/yourfile.html) 加载HTML,而不是从web服务器,你将会碰到一个这样的跨域资源共享错误:
Image from origin 'file://' has been blocked from loading by Cross-Origin Resource Sharing policy: Received an invalid response. Origin 'null' is therefore not allowed access.
因此要确保在远程web服务器上测试这个,以避免任何不能工作的困惑!
源自盒子模型的形状
定义浮动区域的另一个选择是使用被内置于盒子模型的元素。对于简单的圆角,你也可以通过对浮动区域使用盒子模型获得圆角效果。
你可以使用各种盒子模型区域作为浮动区域。我已经在下面添加一张图片来提醒你盒子模型的各个部分。
- 蓝色区域是margin-box
。这是由元素的margin
组成,并且在元素边界的外面。 - 黑色区域是border-box
。在上面例子中,我们设置了2像素的边框。 - 橙色区域是padding-box
。这是围绕着你的内容(比如:我们的图片)的区域。 - 图片自身在content-box
里面。这是包含我们图片的盒子区域。
你可以像这样使用这些边界区域作为浮动区域:
shape-outside: margin-box;
shape-outside: border-box;
shape-outside: padding-box;
shape-outside: content-box;
基本上,无论你定义哪一个都将会是文字围绕型。如果你定义shape-outside
作为margin-box
,那么文字将环绕着margin
的边缘(比如:上面例子中的蓝色区域)。如果你定义shape-outside
作为 border-box
,那么文字将环绕着边框的边缘,等等。
这个的简单应用之一是给图片浮动区域设置圆角(除了有点容易实现和维护以外,就像我们使用inset
一样)。这个CSS将在图片和文字之间添加5像素空隙,同时文字围绕着border-radius
值为150像素的图片:
border-radius: 150px;
margin: 5px;
shape-outside: margin-box;
它看起来如下:
在CodePen上查看效果:
border-radius
与border-box
、padding-box
和content-box
一起使用可以得到同样的效果—它只是改变文字如何靠近图片的方式而已。
shape-margin 属性
你也可以选择在你定义的CSS 形状的浮动区域周围添加空白区域来确保文字不会碰到图片的边缘。在你不对形状使用盒子模型值的情况下,这是非常方便的做法。
规范指明可以使用length
(比如:px
、em
、rem
等单位)、百分比或者calc()
函数值。目前只有Chrome Canary版本的浏览器支持百分比,但Chrome 能稳定支持长度单位和calc()
函数(只是calc()
函数不包括百分比)。列出如下几个例子:
shape-margin: 10px;
shape-margin: 1em;
shape-margin: 5%;
shape-margin: calc(2em - 1px);
结合一些理念并探索!
不要被我例子中的古老插图所愚弄—规范可以被应用到更为现代的设计中去:
在CodePen上查看效果(插入这个演示太不适合了)
请加入我们,试验和分享你的发现来帮助开发规范,这是将来我们会自信和快乐的事情。你可以在W3C这里提供反馈,或者联系Adove Web Platform团队。
扩展阅读
如果你超级热衷以及想要阅读更多有关CSS Shapes 规范,看看下面的链接:
- 使用CSS Shapes的Regions创建更好的阅读体验
- CSS Shapes 101来自A List Apart 网站(强烈推荐,在我们还在写这篇文章的时候,它已经发布了)(中文译文)
- W3C CSS Shapes模块标准1
- The Web Platform page on CSS Shapes 带有各种演示案例
- 由the Adobe Web Platform团队收纳了更多资料链接的文章
- 用到CSS Shapes模块的《爱丽丝梦游仙境》演示 (里边用到了 CSS Shapes模块标准2 的一些特性,我在这里没有涵盖到。)
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
关于尤小博
原名尤增博,充满呆萌爱,有点小追求,专注小前端,新浪微博,期待与你交流学习。
如需转载烦请注明出处:
英文原文:http://www.sitepoint.com/css-shapes-breaking-rectangular-design/
中文译文:https://www.fedev.cn/css3/css-shapes-breaking-rectangular-design.html
Women's Clothing, Footwear & Accessories