clip-path 进阶:fill-rule、参照盒、url() 与形状动画
裁剪的基本用法见 basic-shape 形状函数一页——形状内保留、形状外透明(被裁掉的区域也不响应点击)。这页讲四个实际使用时才会遇到的细节:自交路径算谁是「内部」(fill-rule)、形状相对哪个盒子算(geometry-box)、怎么让 path 随盒子缩放(url + objectBoundingBox)、以及什么时候 clip-path 能平滑过渡。
1 · fill-rule:被边界圈了好几层的区域,算里还是算外
路径一旦自相交或者有多段子路径,「内部」就不再显然。两套裁决规则:nonzero(默认)从该点发射线,数边界带方向的净穿越数,非零算内部——所以「反着画的内圈」能把净数抵成 0,挖出洞;evenodd
不看方向只数次数,奇数内、偶数外。两组对照:
fill-rule 写在形状函数的第一个参数位:、path(evenodd, "…"),新的 shape() 同理;圆和矩形永远不自交,没有这个参数。
实测警告 (2026): Chromium 系能解析 path(evenodd, "…"),但绘制时忽略这个 fill-rule 参数(恒按 nonzero;而命中测试又遵循它——绘制与点击区域不一致)。polygon() 的 fill-rule 没有此问题,上面五角星就是用它演示的。所以要在 path()
里挖洞,跨浏览器最可靠的是右侧方案:把内圈反向绘制,nonzero 自然把净穿越数抵成 0。
2 · geometry-box:形状相对哪个盒子算
形状的百分比 / 原点默认参照 border-box。在形状函数后面补一个关键字就能换参照盒——同一个 circle(50%),参照盒越大圆越大:
geometry-box 也能单独使用:clip-path: content-box 直接裁成内容盒矩形。另有三个 SVG 专用值 fill-box / stroke-box / view-box,参照 SVG 元素的几何。注意 margin-box 只是把参照系放大——绘制本来就不会画进 margin,所以它只会让裁得更少,不会凭空多画。
3 · url(#clipPath):借助 SVG 让 path 随盒子缩放
path() 的坐标固定为 px,盒子一变宽心形就不再居中。把路径放进 SVG 的 <clipPath clipPathUnits="objectBoundingBox">(坐标全用 0~1),再用 clip-path: url(#heart) 引用——形状就按盒子比例伸缩了:
4 · 形状动画:顶点数相同才平滑
clip-path 可以 transition / animation,但两个形状要能插值:同一个函数、同样的「结构」(polygon 顶点数一致、path 命令序列一致)。结构不同只能跳变: