<p>anchor-name 和 anchor() 是已稳定支持的原生 CSS 锚点定位方案,Chrome 125+、Safari 17.5+ 默认启用,Firefox 正在落地;需用 -- 前缀命名锚点,仅支持 absolute/fixed 元素,anchor() 可混合像素偏移,浏览器自动响应滚动缩放无需 JS 监听。</p>

anchor-name 和 anchor() 是真正能甩掉 JavaScript 定位计算的原生方案,不是“又一个实验特性”——Chrome 125+、Safari 17.5+ 已稳定支持,Firefox 正在落地。它解决的不是“能不能做”,而是“要不要再写 200 行 getBoundingClientRect + scroll 监听 + 边界判断”。
用 anchor-name 定义锚点时命名必须带 -- 前缀
这是硬性语法限制,不是可选约定。浏览器会直接忽略不带双短横的值,比如 anchor-name: tooltip-anchor; 无效,必须写成 anchor-name: --tooltip-anchor;。
常见错误现象:position-anchor 找不到目标,锚定元素始终按普通 absolute 渲染(即相对于最近定位祖先,而非你期望的按钮)。
- 只允许字母、数字、连字符,不能有下划线或空格
- 区分大小写:
--MyAnchor和--myanchor是两个不同锚点 - 多个元素可用同一个锚点名,但需确保 DOM 中至少有一个匹配元素存在
anchor() 函数比 position-anchor 更灵活,但要求 position: absolute 或 fixed
position-anchor 是早期草案中的声明式写法,目前主流支持的是函数式定位:用 top: anchor(--my-anchor bottom) 这类表达式直接参与布局计算。
为什么推荐函数式?因为你可以混合使用锚点边缘和像素偏移,比如:
立即学习“前端免费学习笔记(深入)”;
.tooltip {
position: absolute;
top: anchor(--trigger bottom) + 8px;
left: anchor(--trigger center);
translate: -50% 0;
}
注意点:
-
anchor()只能在top/right/bottom/left或inset等可计算长度的属性中使用 - 不支持在
margin或transform里直接调用(translate里的数值仍得手动写) - 若锚点元素不可见(
display: none或visibility: hidden),anchor()返回 0,可能导致错位
滚动/缩放/视口边界变化时无需监听事件
这是和 JS 方案最本质的区别:浏览器原生接管了所有响应逻辑。只要锚点元素在视口内可见,锚定元素就会自动重算位置;如果空间不足(比如 tooltip 贴着页面底部),部分浏览器已开始支持智能翻转(如改到上方),虽语法尚未完全统一,但基础避让已生效。
典型省掉的代码:
- 不用再
window.addEventListener('scroll', updatePosition) - 不用
window.addEventListener('resize', updatePosition) - 不用手写
if (tooltipBottom > window.innerHeight) { ... }边界检测
但要注意:锚点元素自身不能被 overflow: hidden 的父容器裁剪,否则其 getBoundingClientRect 在底层可能失真——这不是 CSS 锚点的问题,而是 DOM 可见性前提。
兼容性不是“能不能用”,而是“要不要降级”
截至 2026 年 5 月,Chrome 125+(含 Edge)、Safari 17.5+ 已默认启用,覆盖全球约 85% 的桌面与 iOS 流量。Firefox 尚未默认开启,但可通过 about:config 启用 layout.css.anchor-positioning.enabled。
实际项目中建议的姿势:
- 先写纯
anchor()版本作为主逻辑 - 用
@supports (top: anchor(--test top))包裹,内部写降级样式(比如 fallback 到top: 100%+left: 50%) - 避免用 JS 检测支持性再插入 class——这反而引入了旧式定位的复杂度
真正容易被忽略的点是:锚点元素必须在触发锚定元素渲染前完成布局。如果锚点是动态插入的(比如通过 innerHTML 或框架 v-if),要确保它已挂载且完成首次 layout,否则 anchor() 可能取到 0。

















