Back

使用 CSS Shape 函数进行创意设计

使用 CSS Shape 函数进行创意设计

你想要一个装饰性箭头来裁剪你的主图。你使用 clip-path: path(),写出 SVG 坐标,它确实有效——直到容器调整大小。箭头保持在其原始像素尺寸,而其他所有内容都在缩放。这就是 CSS shape() 函数所解决的核心限制。

核心要点

  • CSS shape() 函数使用原生 CSS 单位(如百分比和 calc())创建响应式裁剪路径,而 path() 使用固定像素值
  • shape() 可用于 clip-path 进行视觉裁剪和 offset-path 进行运动动画,但不支持 shape-outside 的文本环绕
  • 浏览器支持包括 Safari 18.4+ 和基于 Chromium 的浏览器,但 Firefox 尚不支持——生产环境中始终使用 polygon() 作为降级方案
  • shape() 与 CSS 自定义属性和容器查询单位结合使用,可创建在多种上下文中自适应的形状,无需 JavaScript

CSS shape() 函数的实际作用

shape() 函数是一种 CSS 原生方式,使用熟悉的 CSS 单位(如百分比、calc() 和容器查询单位)来定义复杂形状。与借用 SVG 语法并将所有值解释为像素的 path() 不同,shape() 允许你构建能够适应其容器元素的响应式 CSS 形状。

这是关键区别。使用 path():

clip-path: path("M0 0 L 100 0 L 150 50 L 100 100 L 0 100 z");

这些数字是固定像素。调整元素大小,形状保持相同尺寸。

使用 shape():

clip-path: shape(from 0% 0%, 
  line to calc(100% - 50px) 0%, 
  line to 100% 50%, 
  line to calc(100% - 50px) 100%, 
  line to 0% 100%, 
  close);

现在形状随元素缩放。百分比相对于元素尺寸解析。你可以混合固定值和相对值,创建在容器尺寸变化时保持比例或保留特定角度的形状。

shape() 的应用场景:clip-path 和 offset-path

CSS shape() 函数目前适用于两个具有不同用途的属性。

CSS clip-path shape() 定义元素的哪些部分保持可见。形状外的所有内容都会被裁剪掉。这纯粹是视觉效果——元素的盒模型保持矩形,布局计算完全忽略裁剪。

CSS offset-path shape() 定义动画的运动路径。与 offset-distance 结合使用,你可以沿着自定义曲线和直线移动元素。形状描述的是轨迹,而非可见性。

这些与 shape-outside 有本质区别,后者影响浮动元素周围的文本流。该属性属于 CSS Shapes Level 1,目前不支持 shape() 函数——仅支持 circle()ellipse()polygon() 等基本形状。

浏览器支持:2025 年末的现状

shape() 函数已在 Safari 18.4 中发布,并已登陆基于 Chromium 的浏览器。Firefox 尚不支持。这意味着你不能将其视为基线 CSS。

特性检测很简单:

@supports (clip-path: shape(from 0% 0%, line to 100% 0%)) {
  /* 支持 shape() */
}

对于生产环境使用,渐进增强至关重要。从近似你的形状(不含曲线)的 polygon() 降级方案开始,然后为支持的浏览器添加 shape() 版本:

.element {
  clip-path: polygon(0 0, 80% 0, 100% 50%, 80% 100%, 0 100%);
  clip-path: shape(from 0% 0%, 
    line to 80% 0%, 
    line to 100% 50%, 
    line to 80% 100%, 
    line to 0% 100%, 
    close);
}

第二个声明仅在理解它的浏览器中覆盖第一个。

值得探索的创意用例

装饰性裁剪在形状响应布局时变得更加实用。无论视口宽度如何,对角分区分隔符都可以保持其角度。当卡片在网格中尺寸变化时,带缺口的卡片角可以保持比例。

响应式蒙版用于图像时,可以从混合单位中受益。在整体形状随图像容器缩放的同时,保持固定半径的曲线切口。

运动路径在可以用百分比表示路径点时获得灵活性。无论容器的实际尺寸如何,元素都可以围绕容器中心运行。

当你将 shape() 与 CSS 自定义属性和容器查询单位结合使用时,真正的威力就会显现。单个形状定义可以适应多种上下文,无需 JavaScript 重新计算。

总结

CSS shape() 函数解决了一个特定问题:在不离开 CSS 的情况下使复杂的裁剪路径和运动路径具有响应性。它使用原生语法,支持 calc(),并与基于百分比的坐标配合使用。

它不能替代需要像素精度的固定尺寸形状的 path()。它不适用于文本环绕的 shape-outside。在 Firefox 支持到来之前,它需要降级方案。

对于需要缩放的创意视觉效果,shape() 是一直缺失的工具。使用明确的降级策略,你的装饰性裁剪最终将像响应式布局的其余部分一样运作。

常见问题

可以,如果两个形状具有相同数量和类型的命令,你可以在 shape() 值之间进行动画。浏览器会在对应的坐标值之间插值。如果命令结构不同,动画将无法平滑运行,可能会在状态之间突然切换而不是过渡。

polygon() 仅支持点之间的直线,使用更简单的语法。shape() 通过 arc 和 curve 命令支持曲线,允许在坐标内使用 calc() 表达式,并对复杂形状提供更多控制。对于简单的角形状使用 polygon(),并将其作为更广泛浏览器支持的降级方案。

不会。带有 clip-path 的 shape() 函数纯粹是视觉效果。元素的矩形边界框对于指针事件、焦点轮廓和可访问性树计算保持不变。用户仍然可以点击视觉上被裁剪的区域,这可能需要额外处理以实现直观的交互。

可以,CSS 自定义属性可以在 shape() 坐标内使用。你可以为重复值定义变量或创建可配置的形状。将它们与 calc() 结合使用以进行动态调整。这使得形状定义可重用,并且更易于在不同组件或响应式断点之间维护。

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay