给元素设了 position: fixed,它却跟着父容器的 margin 一起偏移。这不是浏览器的问题,而是规范里明确的行为:偏移属性缺省时,元素停在它的静态位置上。

复现
.wrap { margin-left: 120px; }
.badge {
position: fixed;
/* 没有写 top 与 left */
}
元素脱离文档流,但水平与垂直位置仍取自它原本在流中的占位,父级的 margin 直接进入这个计算结果。外观上表现为「跟着父容器走」。
修正
.badge {
position: fixed;
top: 16px;
left: 16px;
}
显式给出偏移后,位置改由包含块计算,固定定位下包含块是视口,父级 margin 不再参与。需要贴边铺满时用 inset 一次写四边。
两个容易混淆的例外
- 祖先上的 transform、filter、backdrop-filter、will-change、contain 会创建新的包含块,fixed 元素改按该祖先定位,视口基准随之失效。
- 祖先创建层叠上下文后,z-index 的比较范围被限制在该上下文内,跨区域的遮挡关系需要重新核对。
排查顺序
- 先确认偏移属性是否写全,这是出现频率最高的一条;
- 再逐级向上检查祖先是否带 transform 一类会创建包含块的属性;
- 最后核对层叠上下文与 z-index 的比较范围。
写法约定
固定定位的元素统一写偏移值或 inset,不依赖静态位置;弹层类组件挂在 body 下,避开中间层创建包含块带来的差异。
