12k
All articles

CSS Anchor Positioning 详解

CSS Anchor Positioning 允许通过纯 CSS 将工具提示、下拉菜单和弹出层附加到指定元素上,无需 JavaScript 进行位置计算。

OpenReplay Team
OpenReplay Team
CSS Anchor Positioning 详解

多年来,定位工具提示、下拉菜单和弹出框意味着要与复杂的 JavaScript 计算作斗争。你需要测量元素、跟踪滚动位置,并不断重新计算以保持 UI 元素的正确对齐。CSS Anchor Positioning 通过让你使用纯 CSS 将元素相互附加来彻底改变这一点——无需 JavaScript。

关键要点

  • CSS Anchor Positioning 实现了无需 JavaScript 计算的纯 CSS 元素定位
  • 使用 anchor-name 和 position-anchor 在元素之间创建关系
  • position-area 属性提供简单的基于网格的定位
  • 内置的回退机制自动处理视口边缘情况

什么是 CSS Anchor Positioning?

CSS Anchor Positioning 是一个原生浏览器 API,允许你相对于页面上的其他元素来定位元素。可以将其视为在元素之间创建无形的连接:一个充当”锚点”(参考点),另一个充当”目标”(被定位的元素)。

这消除了在构建工具提示、上下文菜单和浮动对话框等常见 UI 模式时对 JavaScript 定位库的需求。浏览器处理所有复杂的计算,包括视口边界和滚动位置。

核心属性:构建锚点关系

使用 anchor-name 设置锚点

首先,你需要通过给元素一个唯一标识符来将其指定为锚点:

.menu-button {
  anchor-name: --main-menu;
}

锚点名称必须以双破折号(--)开头,类似于 CSS 自定义属性。

使用 position-anchor 连接元素

接下来,将目标元素连接到锚点:

.dropdown-menu {
  position: absolute;
  position-anchor: --main-menu;
}

目标元素必须具有 position: absoluteposition: fixed 才能与锚点定位配合使用。

使用 position-area 定位元素

position-area 属性提供了定位目标的最简单方法。它使用以锚点为中心的 3×3 网格模型:

.dropdown-menu {
  position: absolute;
  position-anchor: --main-menu;
  position-area: bottom center;
}

你可以使用物理值(topbottomleftright)或逻辑值(block-startinline-end)以获得更好的国际化支持。span- 前缀允许元素跨越多个网格单元格:

.tooltip {
  position-area: top span-inline;
}

使用 anchor() 函数进行精细调整

要进行精确控制,请将 anchor() 函数与 inset 属性一起使用:

.tooltip {
  position: absolute;
  position-anchor: --trigger;
  top: anchor(bottom);
  left: anchor(left);
}

这将工具提示的顶部边缘定位在锚点的底部边缘,左边缘对齐。你也可以显式引用特定锚点:

.multi-anchor-target {
  top: anchor(--anchor-1 bottom);
  right: anchor(--anchor-2 left);
}

使用 anchor-size() 进行响应式尺寸调整

anchor-size() 函数允许你基于锚点的尺寸来调整元素大小:

.dynamic-tooltip {
  position-anchor: --button;
  width: anchor-size(width);
  max-height: calc(anchor-size(height) * 2);
}

这创建了与锚点成比例缩放的工具提示——非常适合响应式设计。

使用 position-try 处理边缘情况

当你的定位元素碰到视口边缘时会发生什么?position-try 属性提供回退位置:

.context-menu {
  position: absolute;
  position-anchor: --menu-trigger;
  position-area: bottom start;
  position-try: flip-block, flip-inline;
}

当主要位置会导致溢出时,浏览器会自动尝试替代位置。内置关键字如 flip-blockflip-inline 处理常见场景,或者你可以定义自定义回退:

@position-try --compact-menu {
  position-area: top;
  width: 200px;
}

.context-menu {
  position-try: --compact-menu, flip-block;
}

浏览器支持状态

截至 2024 年底,CSS Anchor Positioning 的浏览器支持正在增长:

  • Chrome/Edge:自版本 125 起完全支持
  • Safari:自版本 18 起支持
  • Firefox:正在实现中

对于生产使用,考虑使用 Oddbird polyfill,它提供了对 Firefox 54 和 Chrome 51 的向后兼容性。功能检测很简单:

@supports (anchor-name: --test) {
  /* Anchor positioning 样式 */
}

实际实现技巧

在为工具提示和菜单实现 CSS anchor positioning 时:

  1. 始终重置弹出元素的默认定位:inset: auto
  2. 使用逻辑属性以获得更好的国际化支持
  3. 与 Popover API 结合使用,实现完全无 JavaScript 的交互
  4. 记住可访问性——添加适当的 ARIA 属性以维护语义关系

结论

CSS Anchor Positioning 改变了我们构建浮动 UI 元素的方式。通过将定位逻辑从 JavaScript 转移到 CSS,我们获得了更好的性能、更清洁的代码以及边缘情况的自动处理。在等待完整浏览器支持的同时,polyfill 为生产使用提供了可靠的前进路径。开始尝试工具提示和下拉菜单——你会很快欣赏声明关系而不是计算位置的简单性。

常见问题

我可以在动态创建的元素中使用 CSS Anchor Positioning 吗?

是的,CSS Anchor Positioning 适用于动态创建的元素。只要正确设置了 anchor-name 和 position-anchor 属性,浏览器就会建立定位关系,无论元素何时添加到 DOM 中。

CSS Anchor Positioning 如何处理滚动容器?

CSS Anchor Positioning 自动跟踪容器内的滚动位置。即使发生滚动,定位元素也会保持与锚点的关系,无需任何 JavaScript 事件监听器或手动重新计算位置。

如果多个元素具有相同的 anchor-name 会发生什么?

当多个元素共享相同的 anchor-name 时,DOM 顺序中的最后一个元素成为活动锚点。这种行为可能导致意外的定位,因此最佳实践是为每个定位关系使用唯一的锚点名称。

我可以为使用 CSS Anchor Positioning 的元素添加动画吗?

是的,你可以使用标准的 CSS 过渡和动画为锚点定位的元素添加动画。在动画过程中锚点关系得以维护,并且 position-area 等属性可以在不同值之间平滑过渡,实现流畅的 UI 效果。

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.