shape-outside属性及其应用

前言

shape-outside这个属性实在是太冷门了,要不是去研究<basic-shape>数据类型,还真不会发现这个属性;但是其兼容性也还算可以,PC端完全没问题,移动端iOS是支持比较好的,而安卓端则不太支持:

img

shape-outsideCSS Shapes Module Level 1规范中提出的一个属性,用于设置浮动元素周围内联元素对其包裹的形状,也就是说借助shape-outside属性可以使得浮动元素周围的文字不再是围绕盒模型进行环绕,而是可以指定任意形状进行环绕,达到更丰富的文字环绕效果;比如:

img

shape-outside及相关属性

CSS Shapes Module Level 1规范中不止设计了shape-outside一个属性,还有配合该属性一起搭配使用的属性:shape-image-thresholdshape-margin

shape-outside

shape-outside属性的作用不再多说,语法如下:

none | [ <basic-shape> || <shape-box> ] | <image>[1]

  • none:默认值,即默认的浮动区域(Float area),默认的浮动区域就是margin-box

  • <basic-shape>:基本形状类型;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    @keyframes shape {
    0% {
    clip-path: circle();
    shape-outside: circle();
    }
    25% {
    clip-path: ellipse(50% 30px);
    shape-outside: ellipse(50% 30px);
    }
    50% {
    clip-path: inset(30px 20px round 15px);
    shape-outside: inset(30px 20px round 15px);
    }
    75% {
    clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
    shape-outside: polygon(50% 0%, 100% 100%, 0% 100%);
    }
    100% {
    clip-path: polygon(50% 100%, 0% 0%, 100% 0%);
    shape-outside: polygon(50% 100%, 0% 0%, 100% 0%);
    }
    }
    .container {
    overflow: hidden;
    }
    .box {
    float: left;
    width: 200px;
    height: 200px;
    margin: 10px;
    background-color: coral;
    animation: shape 5s linear alternate infinite;
    }

    img

    上面这个动画就是展示了各种基本形状应用于shape-outside上的效果;

    但是需要注意的是,<basic-shape>数据类型有一个参考盒模型的概念,对于shape-outside属性而言,默认的参考盒模型是margin-box,但是可以在属性中同时使用<shape-box>来指定一个参考盒模型!如:

    1
    2
    3
    .demo {
    shape-outside: content-box circle();
    }

    这样就把shape-outside属性的参考盒模型指定为content-box了!

  • <shape-box>:盒模型类型,包含margin-boxborder-boxpadding-boxcontent-box

  • <image>:图像类型,包括url()函数引入的图像和渐变色;图像作为形状时,是根据图像的alpha通道(即透明通道)来作为形状的边界的,具体的通道阈值要取决于shape-image-threshold属性的值;

shape-margin

这个属性的作用很简单,就是沿着shape-outside属性生成形状再向外扩展相应的距离,不过扩展后的形状不能超过参考盒模型的区域

1
2
3
4
5
6
7
8
9
.box {
float: left;
width: 200px;
height: 200px;
shape-margin: 10px;
background-color: coral;
clip-path: circle();
shape-outside: content-box circle();
}

img

上面这个例子可以看到,尽管shape-margin讲形状向外扩展了10px,但是超出content-box区域外的部分并不视为浮动区域;

那么有没有办法使得浮动区域整体向外扩展相同的距离呢?就像margin属性的效果那样?答案是有,就是将margin-box设置为参考盒模型,然后使用margin属性即可!

1
2
3
4
5
6
7
8
9
.box {
float: left;
width: 200px;
height: 200px;
margin: 10px;
background-color: coral;
clip-path: circle();
shape-outside: circle();
}

img

因为参考盒模型为margin-box,所以设置margin属性可以扩大margin-box的大小,因此浮动区域也相应地扩大了,也就达到了类似一般盒模型中margin的效果;

shape-image-threshold

这个属性是专门用来设置图片形状提取时透明通道的阈值,范围为0 ~ 1,默认值为0;阈值为n代表图片中透明通道值大于n的区域都是浮动区域

1
2
3
4
5
6
7
8
9
.box {
--img: linear-gradient(45deg, rgba(220, 0, 0, 1), rgba(200, 0, 0, 0));
float: left;
width: 200px;
height: 200px;
background: var(--img);
shape-outside: var(--img);
shape-image-threshold: 0.5;
}

img

由于将阈值设置成了0.5,根据上面渐变色的特点可知,透明度为0.5的分界线刚好在左上-右下对角线上,上面这个例子也能看出;不仅如此,chrome浏览器还会贴心地把浮动区域给标记出来:

img

img

上面这个动图就是阈值从01递增的过程,可以看到阈值也是能插值的;

相关应用

上述属性的意图本来就很明显,就是设置不规则的浮动区域,到达更丰富更自然的图文混合效果;所以常用来配合带透明通道的图片进行更贴近图案的图文混合效果。

透明通道图片图文混合

img

上面这个苹果Logo就是带透明通道的,可以看到文字与图片中的图案有更好的贴近效果;

这种效果很适合用来对图片进行讲述的排版,有点类似科普书中那种图文讲解排版,比如这个作品

img

异形文字排列区域

利用各种浮动区域的拼接或者组合,可以将文字包围在一个任意形状中,看起来会有很震撼的效果,比如下面这个作品

img

通过左右两个多边形浮动区域,将文字挤在在一个心形的区域中,很有创意;袁川大佬也有一个类似的作品

img

可以看到这个作品整体呈现脸的轮廓,而那些符号都是随机生成的文字,右侧是有一个由多边形绘制而成的脸轮廓形状的浮动区域,所以左侧的文字贴近右侧浮动区域时就形成了脸的轮廓;当然,这个作品的亮点还不只有shape-outside,这里面还用到了滤镜来组合调制颜色,以及文字渐隐处理所用到的mask,还有随机生成文字用到的CSS变量等等;

更复杂的文字排版

虽说shape-outside属性的初衷是为了不规则形状的浮动,但是也可以用来进行更加复杂和不规则的文字排版,比如有个大神就用CSS grid布局 + shape-outside实现了维恩图文字排版:

img

相关文档


  1. https://drafts.csswg.org/css-shapes/#shape-outside-property ↩︎