你以为浮层定位只能靠 JS 算坐标?今天 CSS 把这件事彻底原生化了

每次写 tooltip、dropdown、popover,都要先 npm install 一个库,然后用 getBoundingClientRect() 算坐标、监听 scroll 和 resize 重新算、写一整套 flip 逻辑防止超屏。Popper.js 每周 7780 万次下载,Floating UI 每周也有几百万次。这个问题存在了十几年。今天,CSS Anchor Positioning 彻底把它原生化了。

这个问题存在了十几年

做浮层 UI 的人都知道这个痛:按钮上挂一个 tooltip,要先读按钮的坐标,加 scroll 偏移,再设 top/left。页面一滚动、窗口一 resize,整个逻辑要重跑一遍。Popper.js 解决的是这件事,但它自己也是个 npm 包——需要初始化、管理生命周期、还是在主线程跑 JavaScript。

三行 CSS 替代一整套库

CSS Anchor Positioning 核心就三个属性:

/* 按钮:声明自己是一个锚点 */
.trigger {
  anchor-name: --my-tooltip;
}

/* 浮层:绑定到锚点,然后定位 */
.tooltip {
  position: absolute;
  position-anchor: --my-tooltip;
  top: anchor(bottom);      /* 浮层顶部 = 按钮底部 */
  left: anchor(center);     /* 浮层左边 = 按钮水平中点 */
  translate: -50% 0;        /* 水平居中 */
}

不需要 JS,不需要库,不需要 refs,不需要 middleware。

比库更好的性能

CSS Anchor Positioning Floating UI
打包体积 0 KB(浏览器原生) ~12 KB
计算位置 GPU(合成器线程) 主线程 CPU
滚动/Resize 重新定位 浏览器自动 手动 observers
视口越界翻转 position-area 一行 flip() middleware

Mintec 在 Q2 2026 迁移了三个项目,测量到含 30+ tooltip 的页面 INP 改善 40-80ms。一个开发者把一个 Webflow SaaS 页面的 Lighthouse 分数从 71 提到 92,只因为把 Tippy.js 和 Floating UI 换成了纯 CSS。

视口越界不用 JS 了

之前最麻烦的部分是”浮层超屏了怎么办”——Floating UI 要写一整套 flip middleware。CSS 用 position-area 或者 @position-try

.tooltip {
  position: absolute;
  position-anchor: --my-tooltip;
  position-area: top center;           /* 优先放上面 */
  position-try-fallbacks: flip-block;  /* 不够位置就翻到下面 */
}

这就是 Floating UI 几十行 JS 做的事,一行 CSS 搞定。

配合 Popover API 连展示逻辑都不用 JS

HTML 的 popover 属性(Baseline 2024)处理显示/隐藏、Esc 关闭、点击外部关闭、top-layer 层级:

<button popovertarget="tip">hover me</button>
<div id="tip" popover>tooltip 内容</div>

popover 处理展示,position-anchor 处理位置,两个原生 API 组合起来,零 JS 替代整个 tooltip 库。

浏览器支持

  • Chrome 125+(2024 年 5 月)
  • Firefox 132+(2024 年 9 月)
  • Safari 18.2+(2024 年 12 月)
  • Baseline 2026,覆盖约 91% 全球流量

渐进增强写法

/* 现代浏览器:原生定位 */
@supports (anchor-name: --test) {
  .tooltip {
    position-anchor: --trigger;
    inset-area: top center;
  }
}

/* 老浏览器:静态回退位置 */
@supports not (anchor-name: --test) {
  .tooltip {
    top: 0;
    left: 50%;
    transform: translateX(-50%);
  }
}

什么时候还要用 Floating UI

  • 虚拟元素(锚点不在 DOM 里,比如 canvas 上跟随鼠标的 tooltip)
  • 需要平滑的定位过渡动画(CSS 切换位置没有动画,Floating UI 可以做)
  • 极老的浏览器用户还占相当比例的企业场景

下一步

下次写 tooltip、dropdown 或者 popover,先去 caniuse 查一下 Anchor Positioning 的支持率。如果你的用户主要是 2024 年以后的浏览器,直接写 CSS,删掉那个 npm 包。

实测步骤:

  1. 查 caniuse.com 查询 anchor-name 支持率
  2. 给 trigger 加 anchor-name: --my-anchor
  3. 给浮层加 position-anchor: --my-anchorposition-area
  4. @supports 包一层老浏览器回退
  5. 删 npm 包,看 Lighthouse 分数变化

评论区

0 条评论

登录后可评论。

阿柯·前端架构 15 阅读