CSS 与布局 / CSS Anchor Positioning · 把元素钉在另一个元素旁 待审核 7 页

CSS Anchor Positioning · 把元素钉在另一个元素旁

tooltip、下拉菜单、popover、气泡提示要解决的是同一件事:让 B 元素贴着 A 元素的某条边出现。长期以来这件事有两条路径,各有代价:把 B 放进 A 的 position:relative 容器,它会被 overflow:hidden 裁掉、被 z-index 压住;用 JS 监听滚动与 resize 反复 getBoundingClientRect() 手算坐标,则要自行处理重算与翻转。CSS Anchor Positioning 把它变成纯 CSS:给 A 起一个 anchor-name,让 B 用 anchor()position-area 引用它。B 不必再是 A 的子孙,可以待在 top layer (popover / dialog),也能精确对齐并自带溢出翻转。规范对锚与浮层的先后仍有一条硬约束——锚要在布局上严格先于浮层,且浮层的包含块要能包住锚,详见 细节与边界 页。阅读本系列需要先了解 position: absolute、包含块 (containing block) 与 stacking 的基础,可参考 how-css-worksstacking-contexts 两个系列。

路线图: 给锚元素 anchor-name: --x → 给浮层 position: absolute; position-anchor: --x → 用 anchor() (精确到边) 或 position-area (九宫格,更简洁) 摆位 → 用 position-try-fallbacks 处理接近视口边缘时的翻面。 why · 心智模型

两个角色与跨包含块的定位

传统方案的两条路径各有短板:relative 容器里的浮层被裁剪,JS 手算坐标要监听滚动与 resize。anchor positioning 引入锚元素与浮层两个角色,让视觉对齐脱离 DOM 包含关系。

anchor() · 精确到边

anchor() 与 anchor-size()

两个底层函数。anchor() 用在 inset 属性里,把浮层的某条边钉到锚的某条边;anchor-size() 用在尺寸、inset 与 margin 上,让浮层的尺寸跟随锚。两者都要求浮层是绝对或固定定位。

position-area · 九宫格

position-area 的九宫格摆位

把锚周围看成 3×3 网格,position-area: top center 即把浮层放到正上方,无需触碰 inset。选中的格子成为浮层新的包含块,格内落点再由 justify-self / align-self 决定。

position-try · 自动翻转

溢出回退与 @position-try

首选位置放不下时,position-try-fallbacks 给出一串候选,浏览器挑第一个不溢出的。内置翻转之外可用 @position-try 自定义整套位置,再配选取策略与锚可见性联动。

recipes · 实战 & 支持度

实战配方与渐进增强

把三个基础能力组合成六个实用案例:popover 贴触发按钮、等宽下拉、一锚多浮层、列表锚隔离、校验气泡、图表 tooltip,末节给出 @supports 降级写法与当前支持现状。

connections · 串线

用 anchor() 在两个元素之间画连接线

同一元素的四条 inset 可以分别 anchor() 到两个不同的锚,把它撑成跨越 A 与 B 的盒子;只画左下两条边即得到一根自适应的 thread 连接线,再用 anchor-scope 让一列 thread 各连各的。

gotchas · 细节与边界

细节与边界

主线能力之外的边角:锚与浮层的先后约束、一个元素挂多个锚名、隐式与显式绑定、锚被三种方式隐藏时的实测表现、inset 与 position-area 并存时的实际落点,以及取值速查。

它解决的老矛盾:「让浮层跟着某元素」与「让浮层在 top layer、不被祖先裁剪」从前是互斥的——要跟随就得当子元素,于是受 overflow / clip / transform / stacking 牵连;要自由就得用 JS 手算坐标。anchor positioning 让视觉对齐脱离 DOM 包含关系,两项要求第一次可以同时满足。

相关链接

规范 / 文档

实例与用法 (本系列灵感来源)

  • Custom range slider:anchor positioning + 滚动驱动动画 Frontend Masters 把滑块 thumb 起名 anchor-name: --thumb,让 <output> 气泡 position-area: top 跟着跑;再用 scroll-driven 的 view-timeline 读出实时值、anchor-scope: all 隔离多个滑块。与 css-animation 系列正好串起来。
  • Anchor Interpolated Morphing (AIM) Adam Argyle 进阶用法:把 anchor 与 @starting-style + interpolate-size + transition(allow-discrete)叠加,让 popover 与对话框从触发点生长出来 (纯 CSS、可打断,无需 View Transitions)。同样能接上 css-animation 系列。