实战配方:Popover 组合、等宽下拉、anchor-scope
把 anchor()、position-area、position-try 各页的基础能力组合成实用案例。这些配方各自只有几行 CSS,但在此之前都得写一大段 JS。
1 · 配方 1 · Popover API + anchor:天然契合
popover 把元素放进 top layer(永远在最上、不被任何祖先裁剪;Popover API 的行为详见 dialog 系列的 popover 页),但它不会帮你贴着触发按钮——默认是屏幕居中。anchor positioning 正好补上这块:给按钮
anchor-name、给 popover position-anchor,零 JS 就贴上了。点击试试:
2 · 配方 2 · 等宽下拉:面板宽度 = 触发它的字段
「下拉面板要和上面的输入框一样宽」是个老难题,从前得用 JS 测量宽度再写死。现在 width: anchor-size(width) 一行解决,字段多宽面板就多宽:
把 #ddBtn 的 width 调大调小,面板会自动跟着变宽——它从不读固定值,只读 anchor-size(width)。
3 · 配方 3 · 一个锚,挂多个浮层
同一个 anchor-name 可以被任意多个浮层引用。下面四个标签都锚定正中那个锚,各占一边:
4 · 配方 4 · anchor-scope:列表里同名锚互不干扰
渲染一个列表,每行都要给自己的小圆点挂个 badge。若每行的锚都叫 --row,名字会冲突——浮层可能全跑去贴某一行。anchor-scope: --row 把这个名字限制在每行子树内,各认各的:
5 · 配方 5 · 表单字段的校验气泡(带小箭头)
把配方 1、2 组合成一个常见场景:输入框聚焦时,下面弹出一个带小箭头的提示气泡(格式说明 / 校验提示),开始输入便收起。气泡用 popover(进 top layer,不被表单容器裁剪)+ anchor 贴在字段下方,再 anchor-size(width) 等宽,小箭头用一个 CSS 三角
::before。点输入框聚焦观察气泡,开始输入观察它收起:
箭头为什么不用单独锚定?气泡已经 anchor-size(width) 等宽于字段、左缘 anchor(left) 对齐字段,所以「箭头相对气泡居中」就等于「相对字段居中」,字段变宽 / 移动时箭头始终对准。若气泡会 position-try 翻到字段上方,记得把箭头也翻到底边(换个
fallback 里的样式)。
popover 的两个易错点:其一,默认 [popover] 有居中的 UA 样式,要先 inset: auto; margin: 0 清除再用 anchor 摆位;其二,想用聚焦而非点击来开关,用 popover="manual" 自己调 showPopover() /
hidePopover()(auto popover 会被点击空白处自动关掉)。
6 · 配方 6 · 数据图表的 hover tooltip(每个点一个锚)
这是 anchor positioning 最具代表性的用法之一(灵感来自 tooltip-chart)。给图表里每个数据点循环生成一个唯一锚名 --pt-0 / --pt-1 / …,每个点的 tooltip 用
position-anchor 咬住自己那个点、position-area: right center 摆右边、position-try-fallbacks: flip-inline 在靠右边缘时翻到左侧。悬停的显示完全靠 CSS(相邻兄弟 + opacity),无需一行跟随 JS。把鼠标移到各个点上(尤其试试最右边几个,观察 tooltip 翻面):
为什么这比传统图表 tooltip 省事?传统做法要在 hover 时用 JS 测出点的坐标、计算 tooltip 位置、监听 resize/scroll 重算、还要自己判断翻转。这里位置、跟随、翻转、显示全交给 CSS:JS 只负责画点 + 设一次 anchor-name。点的位置变化时 tooltip
自动跟随,容器到边缘时自动翻转。
为什么用「唯一锚名」而不是 anchor-scope?两种方式都可行:这里每点一个 --pt-i 最直接(数据驱动循环里顺便就设好了);若所有点想共用同一个名字 --pt,就给每个点的容器加 anchor-scope: --pt 隔离(「画连接线」页那样)。
7 · 渐进增强:用 @supports 覆盖不支持的浏览器
anchor positioning 还没全面铺开(见下方实测)。生产里应先写不依赖它的降级布局,再用 @supports 增强,这样不支持的浏览器至少能正常使用、不至于浮层错位:
8 · 浏览器支持现状
这是个较新的特性,各家进度不同。本页顶部那条横幅,就是你当前浏览器的实测结果(由 CSS.supports('anchor-name','--x') 探测):
小结:视觉对齐从此脱离 DOM 结构——浮层不必是锚的子孙也能对齐;anchor() 精细、position-area 简洁,二选一或混用;position-try-* 把贴边自适应交给浏览器;和 Popover API 天然契合;上线时用 @supports 提供降级。