z-index 是局部的,不是全局的
设置了 z-index: 9999 的元素不会自动浮在页面所有元素之上。z-index 只在层叠上下文内部排序。祖先通过 transform、filter、小于 1 的 opacity、isolation: isolate,或 position 加 z-index 创建新上下文,就成为边界。子元素无论 z-index 多大,都无法逃出祖先的层叠顺序。
.card {
transform: translateZ(0); /* creates a stacking context */
}
.card .badge {
position: absolute;
z-index: 9999; /* still below elements outside .card's context */
}
找到上下文边界
在 DevTools 中检查元素的计算 position 和 z-index,再沿树向上查找。第一个带 transform、filter、opacity、isolation 或定位 z-index 的祖先就是边界。临时移除该属性可以快速确认。还要检查元素是否是 flex 或 grid item:这类 item 上的 z-index 即使没有定位也会创建层叠上下文。
修正结构
对于模态框和 tooltip,应通过 portal 渲染到文档根节点,而不是和祖先上下文较劲。分层 UI 要定义一小组 z-index 刻度(base、dropdown、sticky、modal、toast),并应用到层所有者而不是每个子元素。确实需要局部上下文时使用 isolation: isolate。不要不断加数字,那只会掩盖结构问题,并在新的 transform 容器出现时再次失败。
跨布局验证
在桌面和移动宽度下,分别用浮层对照 header、侧边栏、带 transform 的卡片和 sticky 元素测试。确认元素已定位、预期层叠上下文有文档记录,并且指针事件和焦点都能到达浮层。破坏键盘访问的视觉修复不算完成。