css3中的几何图形shape研究

前言

估计大家在日常工作中都会用到css形状,但是目前天朝中使用到最多的估计就是圆(circle)、椭圆(ellipse)、各种三角形形状,但是你肯定很少看见过用几何图形或者多边图形。假如你不懂什么叫做几何图形,那么请前往百度百科,就算是我们用:after :before 这些伪元素来构造我们所需要的形状或者利用边框来曲线救国,但是对于代码来说还是太长了,有没有直接定义几何图形或者是多边形的属性。今天来说说 shape

摘要

关于shape的应用,个人感觉有点奇葩,为什么这么说,因为只能应用于float 值中,假如不是浮动元素,那么对不起,不适用。所以个人觉得一般用这个 shape 来构造一个我们工作中的形状,应该是带有浮动的图像,像impressivewebs这种左侧图像右侧文字的头像特别适用
博客头像

不过,只能应用于带有浮动属性的元素才能使用这个 shape 属性,想必兼容性应该也不咋地,通过caniuse 可以看得出这个属性兼容性在各个浏览器,哪怕是移动端的兼容性惨不忍睹,只见飘红不见绿。

学习还是要的,说不定哪天用得着呢?

既然这货是给带有float属性的元素使用,那么是时候说说浮动元素了

浮动行为和盒子模型

对于浮动,想必大家在进入到这行的时候,只要是设计稿有明显的左右设计,那么就很喜欢用 float浮动属性,浮动有好也有不足,浮动可以轻松实习各种左右布局,但是也会引起塌陷。但这并不是浮动带来的BUG,而是正常行为,因为外包裹warp并没有足以恰好的包裹整个浮动区域(float area),假如浮动区域(如图片)有固定的维度,而包含带有浮动属性的图片的元素没有指定高度,或者其内容没有比图片本身维度高的话,那就会形成塌陷,对于怎样清除浮动引起的塌陷,不妨回头看看之前写过的一篇博文:利用:after伪类元素清除浮动float所产生的塌陷,或者不妨看看鑫哥很久之前写的一篇博文专门研究float属性,想必你会对浮动有着不一样的认识。

一般来说我们正常的浮动区域都是以矩形框的形式存在,如上图的头像所在红色框框就是其浮动区域,那么这个浮动区域的维度就是一个矩形框,文字都是围绕这个矩形框,对于带有浮动的元素指定一个shape属性的话,那么也许它就会变成这样

博客头像

文字不必整齐地排在一起,还可以沿着圆形头像环绕,这才是这个shape属性使文字环绕图片真正意义。

因此,shape其实是减少浮动区域,而不是增加浮动区域,这点要搞清楚,因为只有减少浮动区域,那些在矩形框的文字才能进来嘛,衣服都脱了,你就让我们整齐站门口把守?

支持的基本形状

目前的规范支持 shape-outside 属性,但是还没有规定 shape-inside属性,将来的版本可能会有内形状也不一定。假如要指定一个 shape-outside 那么还要指定这个浮动区域(float area)一定的宽高。因此常规css中语法如下:

.left {
      shape-outside: shape函数;
      float: left;
      width: 100px;
      height: 100px;
    }

目前shape支持4种函数定义的形状

inset() = inset( < shape-arg >{1,4} [round < border-radius >]? ) //凹形  
circle() = circle( [< shape-radius >]? [at < position >]? )        //圆形  
ellipse() = ellipse( [< shape-radius >{2}]? [at < position >]? )  //椭圆形  
polygon() = polygon( [< fill-rule >,]? [< shape-arg > < shape-arg >]# )    //多边形  

其中

shape-arg =<length> | <percentage>;
<shape-radius> = | <percentage> | closest-side | farthest-side
position = top,right,bottom,left

其实说白了就是长度值,不管是shape-arg还是shape-radius,只不过跟我们平常所写的css值不太一样的地方就是多了at或者round。

inset()函数

inset()函数中可以定义一个凹形体,让文字围绕凹形体。

shape-arg函数为长度值,可以是px或者percentage。允许1~4个值,分别是toprightbottomleft的简写值,对于inset的介绍我们可以用下面的图来解释

inset图

css中的很多属性值假如用到的都是简写值,那么都是按照这么一个排序,对于简写还不明白的请去参考之前写过的一篇小文章:margin简写值

那么假如定义一个inset凹形体距离顶端为10px,距离右侧为20px,距离底部为10%,距离左侧为0的话,css如下写到

.inset{
    float:left;
    width:100px;
    height:100px;
    background-color:#FF0;
    shape-outside:inset(10px 20px 10% 0);
}

效果如下:
inset效果图

墨绿色区域为浮动区域(float area)减少的值,黄色区域为现在的浮动区域。

round,可选值,环绕的意思。后面紧接的 border-radius是我们在熟悉不过的圆角属性,可定义凹形体中四个角的圆滑程度,也是有1~4个值,分别是左上角、右上角、右下角、左下角。假如有不懂的情况可查阅一下之前写过的:border-radius属性值详解,因此,在刚刚那个凹形体中想要定义成一个椭圆半径值为20px和50px,那么可以如下写到

.inset{
    float:left;
    width:100px;
    height:100px;
    background-color:#FF0;
    shape-outside:inset(10px 20px 10% 0 round 20px 50px);
}

效果如下:
inset椭圆效果图

墨绿色区域为浮动区域(float area)减少的值,黄色区域为现在的浮动区域。该浮动区域是由一个距离顶部10px,右侧20px,底部10%,左侧0的矩形框左上角和右下角圆角弧度为20px,右上角和左下角弧度为50px的椭圆组成。

circle()与 ellipse()函数

对于上面这两个圆形形状函数和椭圆形函数的值都是一个样,所以索性直接合并在一起将比较好。他们的值都是:< shape-radius >]? [at < position >]?,椭圆有点小区别下面说。

shape-radius可选值,代表半径比例,对于圆来说只有一个数值定义圆的半径,但是椭圆就可以定义两个值,一个是X轴半径,一个是Y轴半径,但不管是圆还是椭圆半径值不允许负值。使用百分比将会从参考箱子计算值,也可以使用常见的长度值作为单位,想要半径为50px的圆,那么直接直接写circle(50px),当然还可以使用closest-side或者farthest-side来定义,对于长度值(length)或者是百分比(percentage)我们都好理解,里面的数值的就是规定圆的半径大小。但是对于closest-side或者farthest-side就稍微复杂一点。
closest-side从圆心到靠近边缘的边的最短距离作为半径,对于圆来说,值都相等,对于椭圆来说最短的边。如下图中椭圆红色为半径。
farthest-side从圆心到靠近边缘的边的最长距离作为半径,对于圆来说,值都相等,对于椭圆来说最长的边。如下图中椭圆蓝色为半径。
circle效果图

at < position>可选值,定义圆或者椭圆的圆心位置。假如这么写 shape-outside: circle(20px at 50px 30px),那么圆的半径为20px,圆心距离左侧为50px,距离顶部为30px的点。

效果如下:
circle效果图
放大300%后的截图

假如是shape-outside: circle(closest-side at 50px 40px)那么圆心的位置应该是距离顶部40px,左侧50px处,刚上面也提到了关于 closest-side的半径是到参考框最短边的距离,那么此时最短距离应该是40px,而不是50px,所以这个圆的半径应该是为40px如图显示:
circle效果图

polygon()多边形函数

<fill-rule>可选值,填充规则。这个规则定义shape内部的表现形状,具体请查考这里:fill-rule

< shape-arg >,这是设置多边形的值,最少三个值起,因此必须是这么写polygon(40% 0, 100% 0,50% 50%),当然你也可以用其他数值,不一定要百分比。括号中的第一个数值是水平位移,第二个值是垂直位移,可以重复N次。假如我们想要在100*100矩形框内构造一个等边五边形,如下图
css 五边形
对应的A,B,C,D,E的点的坐标应该是如下
css 五边形
因此,相应的css应该可以写成

.polygon{
    float:left;
    width:100px;
    height:100px;
    background-color:#000;
    shape-outside:polygon(50px 0,100px 37px,82px 100px,19px 100px,0 37px);
}

当然这么写,是可以构造出一个矩形框,但是假如你想更加具象的五边形,那么就需要添加 clip-path,这个裁剪属性,这个其实有点像图像多边形热点工具,大意就是把图像中某一个需要的部分抠出来,那么完整的代码如下

.polygon{
    float:left;
    width:100px;
    height:100px;
    background-color:#000;
    shape-outside:polygon(50px 0,100px 37px,82px 100px,19px 100px,0 37px);
    -webkit-clip-path:polygon(50px 0,100px 37px,82px 100px,19px 100px,0 37px);
}

请使用谷歌浏览器打开右侧demo→:css等边五边形

效果如下:
css 五边形

后话

css3中shape形状属性还跟box-sizingmargin-boxpadding-boxborde-box有关系,比较大家css中最最最最最基础的就是盒子模型,shape形状也是基于盒子模型进化而来,为了也是适应时代的需求,再也不可能100年都是矩形、正方形或者圆形。当然,w3c中还可以定义图像的shape形状,这些就不一一去说了,个人觉得假如可以以后这个属性有一天对浏览器们都兼容了,那我们看见的头像可能是五边形、六边形或者是N边形并是非常有可能的,不在仅仅局限于我们目前所见的这些常规形状。当然,这些文字围绕某个多边形图片转转非常适合运用到时尚周刊上的排版去。

那么,更加精彩的等你去研究吧。

对了附上一篇国外妹纸写一篇文章CSS Shapes 101

参考资料:
http://dev.w3.org/csswg/css-shapes/
https://developer.mozilla.org/en-US/docs/Web/CSS/shape

本文地址:http://xiaoho.com/?p=881