按钮缩放一下 tooltip 就飘走了——Safari 27 把 anchor 定位的 transform 感知彻底修好了

按钮缩放了一下,tooltip 就飘到了十万八千里外——这不是你的 CSS 写错了,是 Safari 27 之前 anchor positioning 根本「看不懂」transform

Safari 27 修了这个问题。

CSS Anchor Positioning 让 tooltip、popover、注解这类浮动元素锚定到页面任意一个「锚点」上,不再需要 getBoundingClientRect()。用法很简单:锚点元素声明 anchor-name: --x,浮动元素声明 position-anchor: --x 并用 anchor() 函数读锚点边缘。这套机制在 Chrome 125+、Safari 18+ 就已经支持,Firefox 147+ 也在跟进。

但有一个坑,所有人踩了两年都不知道。

当锚点元素带了 CSS transform——比如一个 hover 时 scale(1.1) 的按钮——tooltip 的定位会「漂移」。原因是浏览器的布局引擎在计算锚点位置时,参考的是 transform 变换前的布局框,而不是视觉上的当前位置。换句话说:锚点明明「看」起来在这里,但浏览器认为它还在那里。

来看一个具体场景:

.card {
  position: relative;
  display: grid;
  place-items: center;
  gap: 1rem;
}

.card button {
  anchor-name: --info-btn;
}

.card .tooltip {
  position: absolute;
  position-anchor: --info-btn;
  position-area: top center;
  margin-block-end: 0.5rem;
}
<div class="card">
  <button style="transform: scale(1.1);">i</button>
  <div class="tooltip" role="tooltip">更多信息</div>
</div>

Chrome 144+ 之前的 tooltip 会认为按钮还在 scale(1.0) 的位置,于是 tooltip 偏下;Safari 27 修了,tooltip 正确跟随按钮当前的视觉位置。

怎么检测浏览器是否支持「感知 transform 的锚点定位」?

这正是 @supports named-feature() 的用武之地。这个函数不是检测某个 CSS 属性存不存在,而是检测某种特定行为有没有实现:

/* 渐进增强:先写 fallback */
.tooltip {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}

/* 支持感知 transform 的锚点定位时,覆盖 fallback */
@supports (anchor-name: --x) and (position-anchor: --x) {
  .tooltip-trigger { anchor-name: --info-btn; }
  .tooltip {
    position: absolute;
    position-anchor: --info-btn;
    position-area: top center;
    margin-block-end: 0.5rem;
    top: auto;
    left: auto;
    transform: none;
  }
}

@supports named-feature(anchor-position-follows-transforms) 这个关键字在 Chrome 150+、Firefox 156+、Safari Technology Preview 中可用。Safari 27 正式版本身已经内置了完整的 transform-aware 锚点定位。

这次修复的根源很有意思:WebKit 团队在修复 Safari 27 一个 dialog 内锚点定位在页面滚动后失效的 bug 时,发现这个「transform 感知缺失」其实是同一批代码里的一个遗留问题,修复 dialog 的过程中一并把 transform 感知也修进去了。提交记录里写着:「原来 tracking transformed anchors 的逻辑一直都在,只是没被正确暴露」。

落地的时候注意什么?

目前 Firefox 156 还不支持 anchor-position-follows-transforms 这个关键字本身(虽然基础锚点定位已经支持)。所以渐进增强的策略是:

@supports (anchor-name: --x) {
  .tooltip-trigger { anchor-name: --x; }
  .tooltip {
    position-anchor: --x;
    position-area: top center;
  }
}

/* transform 感知增强(仅 Chrome 144+ Safari 27+) */
@supports named-feature(anchor-position-follows-transforms) {
  .tooltip-trigger:hover {
    transform: scale(1.05);  /* 现在 tooltip 会正确跟随 */
  }
}

transform 只影响视觉,不影响布局流向——也就是说,即使 tooltip 因为浏览器不支持 transform-aware 锚点定位而位置偏了一点,页面本身的排版不会乱,只是 tooltip 视觉上「歪」了。这是对用户体验影响相对可控的一类 bug,用渐进增强来兜底是合理的。

如果你已经在项目里用了 anchor positioning,给 hover/active 状态的 transform 加上 @supports named-feature() 检测,让支持的浏览器获得更准的 tooltip 定位,不支持的保持原样——这是最低成本的升级路径。

评论区

0 条评论

登录后可评论。