你以为浮层防溢出只能靠 JS?配了五年 tooltip,今天 CSS @position-try 把它彻底原生化了

前端的人踩过这个坑——tooltip 放不到视口边缘,一翻就出屏幕,要靠 Popper.js 算坐标、监听 resize、更新位置,一个 tooltip 写下来比业务逻辑还长。

这个坑,CSS 现在原生填上了。

声明锚点,浏览器自动算位置

anchor-name 给触发元素挂个名字,被定位的元素用 position-anchor 指向它:

.btn-help {
  anchor-name: --help-btn;
}
.tooltip {
  position: absolute;
  position-anchor: --help-btn;
  top: calc(anchor(bottom) + 8px);
  left: anchor(center);
  translate: -50% 0;
}

这行 CSS 干了以前 30 行 JS 干的事:把浮层钉在触发元素下方、水平居中。

防溢出不用 JS,靠 @position-try 声明式兜底

tooltip 在视口底部会溢出——这才是让整件事变复杂的原因。以前靠 resize observer 算空间,@position-try 把这个逻辑声明掉了:

.tooltip {
  position-try-fallbacks: flip-block;
}

flip-block 是内置关键字,自动把 tooltip 翻到触发元素上方。也可以写自定义兜底:

@position-try --flip-above {
  top: unset;
  bottom: calc(anchor(top) + 8px);
  margin-top: 0;
  margin-bottom: 8px;
}

@position-try --shift-right {
  left: anchor(right);
  translate: none;
}

.tooltip {
  position-try-fallbacks: --flip-above, --shift-right;
}

浏览器按顺序试每个兜底方案,选第一个不出界的。不用事件监听,不用定时器重算。

配合 Popover API 零 JS 搭下拉菜单

tooltip 配 Popover API,连显示/隐藏都不用 JS:

<button popovertarget="menu" popovertargetaction="toggle" id="menu-trigger">
  打开菜单
</button>
<div id="menu" popover>
  <button>选项一</button>
  <button>选项二</button>
</div>
#menu-trigger {
  anchor-name: --menu-trigger;
}
#menu {
  position: absolute;
  position-anchor: --menu-trigger;
  inset-area: bottom span-all;
  position-try-fallbacks: flip-block;
}

按钮控制显隐,浏览器处理焦点管理、轻触外部自动关闭,CSS 处理定位和溢出翻转。这是以前一整套 React 组件才能做到的事。

浏览器支持:三大引擎全部稳定,Baseline 2026

特性 Chrome Safari Firefox
anchor-name / position-anchor 125+ 18+ 131+
position-try-fallbacks 129+ 26+ 147+
@position-try 自定义规则 125+ 26+ 147+

截至 2026 年 9 月,全球覆盖约 75-80%。对主流用户够了,渐进增强写法兜底:

.tooltip {
  /* 不支持 anchor 的浏览器:静态定位 */
  top: 100%;
  left: 50%;
  translate: -50% 0;
}
@supports (anchor-name: --x) {
  .tooltip {
    position-anchor: --trigger;
    inset-area: bottom center;
    position-try-fallbacks: flip-block;
  }
}

下一步

如果你现在用的是 Popper.js 或 Floating UI,下周抽半天把最常用的 tooltip 组件换掉这个写法——anchor-name 加一行、position-anchor 加一行、position-try-fallbacks 加一个关键字,resize observer 和 scroll listener 整块删掉。实测下来代码量少 60%,性能还更好。

浮层定位这个坑,CSS 早就原生填上了,只是社区传导还需要时间。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 14 阅读