你以为 tooltip 只能在窗口边缘靠 JS 翻面?Chrome 125+ 用 @position-try 把这件事彻底原生化了
写过浮动层的人都知道这个流程:先定一个位置,跑一下 getBoundingClientRect,发现超视口了,调 flip(),再跑,再调 shift(),最后还要接一个 resize 监听,防止容器滚动后位置跑了。整个过程全是命令式代码,定位逻辑和 UI 代码搅在一起,30KB 的库就干这一件事。
Chrome 125 给浏览器加了一套 CSS 原生的 fallback 机制,叫 @position-try 和 position-try-fallbacks。现在这件事可以全部交给浏览器在 layout 阶段算完。
最基础的用法一行搞定:
.tooltip {
position: fixed;
position-anchor: --trigger;
position-area: top center;
position-try-fallbacks: flip-block;
}
flip-block 的意思是:如果 tooltip 沿块轴(竖直方向)超出视口,就自动翻到锚元素的另一侧。flip-inline 则是水平方向翻转。两个一起写,基本覆盖所有贴边场景。这两行声明替换的是以前 Floating UI 里整个 flip middleware + 重新计算循环。
如果基础翻转不够用,可以自己定义 fallback 位置:
@position-try --below {
position-area: bottom center;
}
@position-try --right-side {
position-area: right center;
}
.tooltip {
position-area: top center;
position-try-fallbacks: flip-block, --below, --right-side;
}
浏览器按顺序尝试每个 fallback,选第一个不溢出的。也可以让浏览器自己挑空间最大的那个方向:
.tooltip {
position-try-order: most-block-size;
position-try-fallbacks: flip-block;
}
most-block-size 让浏览器比较各位置的可视空间,直接选垂直空间最充裕的方向。这在没有足够样本数据预测用户滚动方向的时候特别有用。
position-try 还能配合 Popover API 一起用,top-layer 的 popover 不受父容器 overflow 限制,定位锚完全靠 CSS,状态管理交给浏览器原生处理,整个组合不需要一行 JS:
[popover] {
position: fixed;
position-anchor: --trigger;
position-area: top center;
position-try-fallbacks: flip-block;
margin-bottom: 8px;
}
浏览器支持情况:Chrome/Edge 125+、Safari 26+、Firefox 147+。Firefox 147 是 2024 年 10 月支持的,覆盖率在 2026 年 1 月突破 Baseline 新增可用门槛。主流浏览器全部就位,生产可用。
渐进增强写法:
@supports not (position-anchor: --x) {
/* 加载 Floating UI fallback */
}
实际上 94% 以上的浏览器已经支持,如果你的用户构成偏新,基本可以直接上,不需要再接任何 JS 定位库。@position-try 把以前需要一个完整中间件栈 + 两个 resize/scroll 监听才能搞定的事情,用几句声明式 CSS 替代了——而且它在浏览器的 layout 阶段就算完了,不占主线程。
评论区
登录后可评论。