shape()

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

shape() CSS 函数用于为 clip-pathoffset-path 属性定义形状。它将一个初始起点与一系列定义形状路径的形状命令相结合。shape() 函数是 <basic-shape> 数据类型的一员。

语法

css
/* <fill-rule> */
clip-path: shape(nonzero from 0 0, line to 10px 10px);

/* <move-command>, <line-command>, and close */
offset-path: shape(from 10px 10px, move by 10px 5px, line by 20px 40%, close);

/* <hvline-command> */
offset-path: shape(from 10px 10px, hline by 50px, vline to 5rem);

/* <curve-command> */
offset-path: shape(
  from 10px 10px,
  curve to 80px 80px with 160px 1px / 20% 16px
);

/* <smooth-command> */
offset-path: shape(from 10px 10px, smooth to 100px 50pt);

/* <arc-command> */
offset-path: shape(
  from 5% 0.5rem,
  arc to 80px 1pt of 10% ccw large rotate 25deg
);

/* Using a CSS math function */
offset-path: shape(
  from 5px -5%,
  hline to 50px,
  vline by calc(0% + 160px),
  hline by 70.5px,
  close,
  vline by 60px
);

clip-path: shape(
  evenodd from 10px 10px,
  curve to 60px 20% with 40px 0,
  smooth to 90px 0,
  curve by -20px 60% with 10% 40px / 20% 20px,
  smooth by -40% -10px with -10px 70px,
  close
);

参数

<fill-rule> 可选

指定如何填充形状的重叠区域。可能的值包括:

  • nonzero:如果从某点绘制的射线穿过从左到右的路径段多于从右到左的路径段,从而导致非零计数,则该点被认为在形状内部。这是省略 <fill-rule> 时的默认值。

  • evenodd:如果从某点绘制的射线穿过奇数个路径段,则该点被认为在形状内部。这意味着射线每次进入形状时,并没有退出相等的次数,表明进入次数为奇数且没有相应的退出。

警告:<fill-rule>offset-path 中不受支持,使用它会使该属性无效。

from <coordinate-pair>

将第一个 <shape-command> 的起点定义为一对坐标,该坐标从参考盒的左上角开始测量。坐标以空格分隔的 <x> <y> <length-percentage> 值的形式指定,分别表示左偏移和上偏移。百分比值分别相对于元素参考盒的宽度和高度。在此参数后添加一个逗号。

<shape-command>

指定一个或多个用逗号分隔的命令列表,这些命令定义了形状,其语法类似于 SVG 路径命令。命令包括 <move-command><line-command><hv-line-command><curve-command><smooth-command><arc-command>close。每个命令的起点是前一个命令的终点,形状的第一个点由 from <coordinate-pair> 参数定义。

大多数形状命令的语法是一个提供指令的关键字(如 moveline),后跟 byto 关键字,以及一组坐标。

by:表示 <coordinate-pair> 相对于命令的起点(“相对”值)。

to:表示 <coordinate-pair> 相对于参考盒的左上角(“绝对”值)。

备注: 如果 <coordinate-pair> 中的坐标被指定为百分比,则该值是相对于参考盒各自的宽度或高度计算的。

可以指定以下 <shape-command><move-command><line-command><hv-line-command><curve-command><smooth-command><arc-command>close

<move-command>:指定为 move [by | to] <coordinate-pair>。此命令向形状命令列表中添加一个移动到(MoveTo)命令。它不绘制任何东西,而是为下一个命令指定起始位置。byto 关键字分别指定 <coordinate-pair> 点是相对的还是绝对的。如果 <move-command> 跟在 close 命令之后,它将标识下一个形状或子路径的起点。

<line-command>:指定为 line [by | to] <coordinate-pair>。此命令向形状命令列表中添加一个画线到(LineTo)命令。它从命令的起点到终点绘制一条直线。byto 关键字分别指定由 <coordinate-pair> 指定的终点是相对的还是绝对的。

<hv-line-command>:指定为 [hline | vline] [by | to] <length-percentage>。此命令向形状命令列表中添加一个水平(hline)或垂直(vline)的画线到(LineTo)命令。使用 hline 时,从命令的起点绘制一条水平线 to(到)或 by(偏移)由 <length-percentage> 定义的 x 位置。使用 vline 时,从命令的起点绘制一条垂直线 to(到)或 by(偏移)由 <length-percentage> 定义的 y 位置。byto 关键字分别确定终点是相对的还是绝对的。此命令等同于 <line-command>,其中一个坐标值由单个 <length-percentage> 设置,而另一个坐标值与其起始命令保持不变。

<curve-command>:指定为 curve [by | to] <coordinate-pair> with <coordinate-pair> [/ <coordinate-pair>]。此命令向形状命令列表中添加一个贝塞尔曲线命令byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线终点是相对的还是绝对的。with 关键字指定贝塞尔曲线的控制点。

  • 如果只提供一个 <coordinate-pair>,该命令将绘制一条二次贝塞尔曲线,该曲线由三个点(起点、控制点和终点)定义。
  • 如果提供了两个 <coordinate-pair> 值,该命令将绘制一条三次贝塞尔曲线,该曲线由四个点(起点、两个控制点和终点)定义。

<smooth-command>:指定为 smooth [by | to] <coordinate-pair> [with <coordinate-pair>]。此命令向形状命令列表中添加一个平滑的贝塞尔曲线命令byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线终点是相对的还是绝对的。

  • 如果省略 with <coordinate-pair>,该命令将绘制一条平滑的二次贝塞尔曲线,该曲线使用前一个控制点和当前端点来定义曲线。
  • 如果包含可选的 with 关键字,它将通过 <coordinate-pair> 指定曲线的控制点,绘制一条由前一个控制点、当前控制点和当前端点定义的平滑三次贝塞尔曲线。

平滑曲线确保了形状的连续过渡,而二次曲线则不然。平滑二次曲线使用单个控制点保持无缝过渡,而平滑三次曲线则使用两个控制点提供更精细的过渡。

<arc-command>:指定为 arc [by | to] <coordinate-pair> of <length-percentage> [<length-percentage>] [<arc-sweep> | <arc-size> | rotate <angle>]。此命令向形状命令列表中添加一个椭圆弧曲线命令。它在起点和终点之间绘制一个椭圆弧。byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线终点是相对的还是绝对的。

椭圆弧曲线命令定义了两个可能的椭圆,它们都与起点和终点相交,并且每个椭圆都可以顺时针或逆时针绘制,从而根据弧的大小、方向和角度产生四种可能的弧。of 关键字指定了弧所在的椭圆的大小:第一个 <length-percentage> 提供椭圆的水平半径,第二个 <length-percentage> 提供垂直半径。

指定以下参数以选择使用四条弧中的哪一条:

  • <arc-sweep>:指示所需的弧是沿椭圆顺时针(cw)还是逆时针(ccw)绘制的弧。如果省略,则默认为 ccw
  • <arc-size>:指示所需的弧是两条弧中较大(large)还是较小(small)的一条。如果省略,则默认为 small
  • <angle>:指定椭圆相对于 x 轴旋转的角度,以度为单位。正角度使椭圆顺时针旋转,负角度使其逆时针旋转。如果省略,则默认为 0deg

特殊情况处理如下:

  • 如果只提供一个 <length-percentage>,则水平和垂直半径都使用相同的值,从而有效地创建一个圆形。在这种情况下,<arc-size><angle> 没有影响。
  • 如果任一半径为零,则该命令等同于到终点的 <line-command>
  • 如果任一半径为负,则使用其绝对值。
  • 如果水平和垂直半径所描述的椭圆不够大,无法同时与起点和终点相交(在按指定的 <angle> 旋转后),则半径会按比例均匀放大,直到椭圆刚好足够大,可以与两个点相交。
  • 如果弧的起点和终点恰好位于椭圆的相对两侧,则只有一个可能的椭圆和两条可能的弧。在这种情况下,<arc-sweep> 指定要选择的弧,而 <arc-size> 没有影响。

close:向形状命令列表中添加一个闭合路径(ClosePath)命令,从当前位置(上一个命令的终点)到 from <coordinate-pair> 参数中定义的路径的第一个点绘制一条直线。要闭合形状而不绘制线条,请在 close 命令之前包含一个带有起始坐标的 <move-command>。如果 close 命令紧跟着一个 <move-command>,它将定义下一个形状或子路径的起点。

描述

shape() 函数允许你定义复杂的形状。它在几个方面与 path() 形状函数相似:

  • shape() 函数中的 <fill-rule> 参数与 path() 函数中的相同参数完全一样。
  • shape() 函数需要指定一个或多个 <shape-command>,其中每个命令都使用一个底层的路径命令,例如MoveToLineToClosePath

然而,与使用 path() 相比,shape() 提供了几个优势:

  • shape() 使用标准的 CSS 语法,使其更容易在样式表中直接创建和修改形状。相比之下,path() 使用 SVG path 语法,对于不熟悉 SVG 的人来说不太直观。
  • shape() 支持多种 CSS 单位,包括百分比、remem。而 path() 将形状定义为单个字符串,且单位仅限于 px
  • shape() 还允许使用 CSS 数学函数,如 calc()max()abs(),在定义形状时提供了更多的灵活性。

正式语法

<shape()> = 
shape( <'fill-rule'>? from <position> , <shape-command># )

<fill-rule> =
nonzero |
evenodd

<position> =
<position-one> |
<position-two> |
<position-four>

<shape-command> =
<move-command> |
<line-command> |
close |
<horizontal-line-command> |
<vertical-line-command> |
<curve-command> |
<smooth-command> |
<arc-command>

<position-one> =
left |
center |
right |
top |
bottom |
x-start |
x-end |
y-start |
y-end |
block-start |
block-end |
inline-start |
inline-end |
<length-percentage>

<position-two> =
[ left | center | right | x-start | x-end ] && [ top | center | bottom | y-start | y-end ] |
[ left | center | right | x-start | x-end | <length-percentage> ] [ top | center | bottom | y-start | y-end | <length-percentage> ] |
[ block-start | center | block-end ] && [ inline-start | center | inline-end ] |
[ start | center | end ]{2}

<position-four> =
[ [ left | right | x-start | x-end ] <length-percentage> ] && [ [ top | bottom | y-start | y-end ] <length-percentage> ] |
[ [ block-start | block-end ] <length-percentage> ] && [ [ inline-start | inline-end ] <length-percentage> ] |
[ [ start | end ] <length-percentage> ]{2}

<length-percentage> =
<length> |
<percentage>

示例

使用 shape() 定义路径

此示例演示了如何在 offset-path 属性中使用 shape() 函数来定义元素可以遵循的路径形状。

第一个形状 shape1 遵循由 curve to 命令定义的立方贝塞尔曲线路径。接下来,close 命令从曲线的终点画一条直线回到 from 命令中定义的初始点。最后,shape1 移动到其新位置 0px 150px,然后沿着一条水平线前进。

第二个形状 shape2 最初沿着一条水平线,然后移动回其起始位置 50px 90px。接下来,它沿着一条垂直线前进,然后闭合路径回到初始点。

两个形状都以其原始颜色开始,并在 move 动画结束时逐渐过渡到 hotpink,在动画重新开始时恢复其初始颜色。这种循环的颜色变化为你提供了关于动画进展和重新启动的视觉提示。

css
.shape {
  width: 50px;
  height: 50px;
  background: #2bc4a2;
  position: absolute;
  text-align: center;
  line-height: 50px;
  animation: move 6s infinite linear;
}

.shape1 {
  offset-path: shape(
    from 30% 60px,
    curve to 180px 180px with 90px 190px,
    close,
    move by 0px 150px,
    hline by 40%
  );
}

.shape2 {
  offset-path: shape(
    from 50px 90px,
    hline to 8em,
    move to 50px 90px,
    vline by 20%,
    close
  );
}

@keyframes move {
  0% {
    offset-distance: 0%;
  }
  100% {
    offset-distance: 100%;
    background-color: hotpink;
  }
}

结果

使用 shape() 定义元素的可见部分

此示例演示了如何在 clip-path 属性中使用 shape() 函数为剪切区域创建不同的形状。第一个形状(shape1)使用由直线定义的三角形。第二个形状(shape2)包括曲线和平滑过渡;它还演示了在 close 命令之后使用 <move-command>,这会在剪切区域中添加一个矩形形状。

css
.shape {
  width: 100%;
  height: 100%;
  background: #2bc4a2;
  position: absolute;
  text-align: center;
  line-height: 50px;
}

/* Triangular clipping region */
.shape1 {
  clip-path: shape(from 0% 0%, line to 100% 0%, line to 50% 100%, close);
}

/* A Heart clipping region using curve and arc transitions
   and a box using hline and vline transitions */
.shape2 {
  clip-path: shape(
    from 20px 70px,
    arc to 100px 70px of 1% cw,
    arc to 180px 70px of 1% cw,
    curve to 100px 190px with 180px 130px,
    curve to 20px 70px with 20px 130px,
    close,
    move to 150px 150px,
    hline by 40px,
    vline by 40px,
    hline by -40px,
    close
  );
}

结果

规范

规范
CSS 形状模块 Level 2
# shape-function

浏览器兼容性

另见