根本原因是绝对定位与transform作用于不同坐标系:absolute基于布局坐标系定位左上角,transform创建新局部坐标系并以自身尺寸为基准偏移,且会改变fixed定位的参照物和子元素的包含块。
绝对定位(position: absolute)和 transform 同时使用时出现错位,根本原因不是代码写错了,而是两者作用的坐标系不同,且 transform 会隐式创建新的局部坐标系,干扰了你对位置的预期。
当设置 top: 50%; left: 50% 时,浏览器把元素的**左上角**(即默认 transform-origin: 0 0)放在父容器内容区的中心点。这个动作发生在布局阶段,是真实的位置计算依据。
如果你没加 transform,元素就以左上角为锚点显示在那里;一旦加上 translate(-50%, -50%),它才真正以自身宽高中心对齐——但这个“-50%”是相对于元素自身的尺寸,不是父容器。
top: 50%; left: 50%,却忘了 transform: translate(-50%, -50%)
transform-origin: top left 却仍按中心思维写 translate(-50%, -50%),结果偏移量被原点改变放大或缩小当一个元素有 transform(非 none),它就会成为其子元素的“包含块”(containing block),尤其影响 position: absolute 子元素的定位参照。更关键的是,它还会创建新的层叠上下文(stacking context)和变换上下文(transform context)。
这意味着:如果你在某个带 transform 的父容器里放了一个 absolute 子元素,它的 top/left 是相对于这个“已变形”的父容器边界计算的,而不是原始布局框。

transform: scale(0.8),子元素 top: 100px 实际会落在缩放后父容器的 100px 处,视觉上比预期更高outline: 1px solid red,对比元素边框与实际渲染位置position: fixed 本该相对于视口(viewport)定位,但一旦其任意祖先元素设置了 transform、filter 或 will-change,浏览器就会把它“降级”为相对于那个祖先元素定位——也就是变成类似 absolute 的行为。
这不是 bug,是 CSS 规范明确规定的:任何创建了“堆叠上下文”或“包含块”的属性,都会让 fixed 失去视口基准。
加 transform: translateX(10px),所有 fixed 元素都跟着偏移或失效transform,要么把 fixed 元素直接挂到 下(用 JS 动态 append),绕过变形祖先先确认问题类型,再针对性处理:
transform: translate(-50%, -50%),或 transform-origin 是否与 translate 配套(如 origin 设为 center,translate 就别用百分比)transform;如有,考虑改用 margin 或 top/left 控制,或把子元素提到父级外transform;找到后优先移除,次选用 JS 移动 DOM 节点top/left 做关键帧位移,统一用 transform: translate(),保持坐标系一致