CSS 中有一些值可用于绘制形状。例如,circle()
函数是几个 CSS 属性的有效值。不过,“绘制”可能不是合适的词。这与 SVG 中可以创建 <circle>
元素并字面意义上绘制一个圆圈不同。
CSS 中的这些形状用于其他用途。即:clip-path
用于制作剪切蒙版,shape-outside
用于使文本围绕形状流动。
还有一些其他 CSS 属性使用类似 SVG 的形状来执行其功能。例如,offset-path
是沿着矢量路径对元素进行动画处理的一部分,使用 path()
函数。路径很棒。它们是终极的绘图元素,因为它们 可以绘制任何内容,所有其他形状本质上都是路径的语法糖。
基本形状是什么?
有四个 基本形状
polygon()
circle()
ellipse()
inset()
路径是什么?
路径来自 SVG。它们具有 特殊的语法,允许它们绘制任何内容。
<path d="M 25,100 C 25,150 75,150 75,100 S 100,25 150,75" />
path("M 25,100 C 25,150 75,150 75,100 S 100,25 150,75");
事情变得有点奇怪
clip-path
和shape-outside
属性可以采用所有“基本形状”,例如circle()
和polygon()
,但不能采用path()
。offset-path
属性可以采用path()
,但不能采用“基本形状”。- 您也可以通过 CSS 控制
<path>
的d
属性,但不能控制许多其他 SVG 元素的属性。
我不太确定为什么会出现这种情况,我相信随着时间的推移,情况会发生变化,但了解这一点很重要。
让我们详细说明。
clip-path
允许基本形状(但不允许 path()
)
假设您想将方形头像剪切成多边形,以获得有趣的图案。您可以做到!图像可能是 HTML 元素,例如
<img src="avatar.jpg" alt="User Avatar" class="avatar">
.avatar {
clip-path: polygon(0% 5%, 100% 0%, 100% 85%, 65% 80%, 75% 100%, 40% 80%, 0% 75%);
}
查看 CodePen 上 Chris Coyier 的作品 剪切头像 (@chriscoyier)。
但是,假设您想像这样剪切头像

好吧,您做不到。至少不是直接用 CSS。这些曲线需要 path
,而 clip-path 不支持 path
。幸运的是,clip-path 可以采用 url()
,它将接受 <clipPath>
元素的 ID。
查看 CodePen 上 Chris Coyier 的作品 剪切头像 (@chriscoyier)。
offset-path
允许 path(但不允许基本形状)
假设我们要沿着我们刚使用的那个气泡形状的外部移动一个对象。offset-path
属性专门用于此目的。
<div class="move-me"></div>
.move-me {
offset-path: path("M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z");
animation: move 3s linear infinite;
}
@keyframes move {
100% { motion-offset: 100%;}
}
查看 CodePen 上 Chris Coyier 的作品 path 上的 offset-path (@chriscoyier)。
但是,如果您想让元素在圆圈中移动怎么办?圆圈的基本形状版本具有非常简单的语法,例如 circle(50% at 50% 50%)
;但不幸的是,不支持基本形状。规范 允许它们,但它们不起作用。这有一定道理,因为... 您如何定义要移动的方向?
您仍然可以在圆圈中进行动画处理,因为功能强大的路径可以绘制圆圈,例如
.move-me {
/* a circle */
offset-path: path("M100,50a50,50,0,1,1-50-50A50,50,0,0,1,100,50Z");
animation: move 3s linear infinite;
}
@keyframes move {
100% { motion-offset: 100%;}
}
这些命令自然地指定了方向。还有一些 其他方法可以在圆圈中进行动画处理。
shape-outside
允许基本形状(但不允许 path()
)
假设您想让一些文本围绕蛋形包裹,因为... 我不知道,您正在设置一些爱丽丝对赫蒂·邓蒂的对话的文字。蛋形是使用 ellipse()
基本形状的一个好借口。
<div class="page-wrap">
<div class="egg"></div>
<p>"I don't know what you mean by 'glory,'" Alice said.</p>
<p>Humpty Dumpty smiled contemptuously. "Of course you don't—till I tell you. I meant 'there's a nice knock-down argument for you!'"</p>
...
.egg {
float: left;
shape-outside: ellipse(120px 160px at 50% 50%);
width: 280px;
height: 320px;
}
我们可能会设置一个相同的 clip-path
(以实际创建蛋形)并对其进行着色
查看 CodePen 上 Chris Coyier 的作品 形状外部蛋形 (@chriscoyier)。
但是,如果您想让一些文本围绕 *弯曲* 的形状包裹,就像这里在 Illustrator 中所示

不幸的是,shape-outside
不支持 path()
,因此您无法做到。但您可以做到。它支持 url()
,您可以使用它链接到图像(甚至不必是 SVG,但 SVG 很有意义)。图像可以具有一个漂亮的弯曲路径,就像我们想要的那样
查看 CodePen 上 Chris Coyier 的作品 围绕曲线环绕文本 (@chriscoyier)。
url()
甚至可以 成为数据 URL。还要注意,使用 shape-outside
的任何元素都必须 浮动,这可能是 CSS 排除 解决的限制。
<path>
采用 path()
这是一个开始时很有逻辑意义的例子。假设您有一条路径
<svg>
<path d=" ... " />
</svg>
您可以通过 CSS 更改该路径的形状,例如通过悬停
svg:hover path {
d: path(" ... ");
}
查看 CodePen 上 Chris Coyier 的作品 悬停时更改路径 (@chriscoyier)。
您甚至可以 过渡形状,如果它碰巧是具有相同点数的路径数据。
不过,它确实有点令人困惑。假设您有一个 <polygon>
而不是。
<svg>
<polygon points=" ... " />
</svg>
您如何用 CSS 更新它?
polygon {
/* Nope */
points: " ... ";
/* Nope */
points: points(" ... ");
/* Nope */
points: polygon(" ... ");
}
据我所知,没有办法。这似乎很奇怪,因为 polygon 在其他地方都被支持。我想问题的一部分在于 polygon()
函数与 points
属性不同。polygon()
函数在 CSS 中使用百分比和带 *单位* 的数字,而 points
属性使用 *无单位* 数字(与 SVG 中的所有内容一样)。它们是不同的野兽,这种重叠很尴尬。
同样,与基本形状重叠的 SVG 形状也不能被更改。例如,<circle>
的所有属性都可以用 CSS 进行更改
svg:hover circle {
cx: 40;
cy: 40;
r: 40;
}
查看 CodePen 上 Chris Coyier 的作品 更改圆形属性 (@chriscoyier)。
简而言之:通常有一种方法可以完成您想要完成的操作,但支持哪些功能以及不支持哪些功能很令人困惑。
“为什么”主要是许多新功能异步开发,一些功能领先于其他功能。长期目标是肯定要有一套更合理且一致的形状函数。
path()
不在 最初的 CSS 形状规范 中,它是通过运动/偏移路径规范添加的。但是,它的定义应该是可以在任何接受<shape-function>
的 CSS 属性中应用,并且已添加到 CSS Shapes 2 级。如果您想在 clip-path 和 shape-outside 中使用路径函数,请提交/点赞浏览器错误!同样,运动/偏移路径规范 支持所有形状函数,但 Chrome 中的初始实验性实现非常有限。
CSS 中的 SVG 属性选项稍微复杂一些,因为需要与 SVG 中的工作方式保持向后兼容。
d
不定义完整的形状:您需要一个单独的fill-rule
,它只对<path>
元素应用。事情有点半路出局,但现在浏览器正在停止任何新的实现承诺。同样,如果这对您很重要(也就是说,如果浏览器支持更多 SVG-in-CSS 可以让您的生活更轻松),请告知浏览器团队!移动版 Chrome 55 中的 SVG shape-outside 仍然无法正常工作 :(