12k
All articles

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

CSS shape 函数通过百分比定义响应式 clip path 与运动路径,替代容器尺寸变化时会失效的固定像素坐标。

OpenReplay Team
OpenReplay Team
使用 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() 值之间进行动画吗?

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

对于 clip-path,shape() 和 polygon() 有什么区别?

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

shape() 会影响元素的点击区域或可访问性吗?

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

我可以在 shape() 坐标内使用 CSS 自定义属性吗?

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

Digital experience platform

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.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.