position: sticky 与 fixed 的根本差异在于文档流参与方式:sticky 在未触发时保持正常流布局,触发后仅在滚动祖先内临时表现为 fixed;fixed 则始终脱离文档流、相对于视口定位。

sticky 不会自动脱离文档流,fixed 一设就脱离
这是最根本的差异。position: fixed 声明生效的瞬间,元素立刻脱离文档流,不占原始位置,后续内容直接上移填补空缺;而 position: sticky 在未触发粘性条件前,完全按 normal flow 渲染,保留自身高度、影响父容器布局,就像没加定位一样。
常见错误现象:给一个 .nav 加了 position: sticky; top: 0,但滚动后页面内容“跳了一下”——大概率是父容器高度塌陷或兄弟元素 margin 被误判,不是 sticky 本身的问题,而是你忘了它前期仍参与流式布局。
sticky 的“脱离”是滚动时动态切换,fixed 是静态绑定视口
position: sticky 的行为分两段:滚动前是 relative(相对自身正常位置),滚动中到达 top/bottom/left/right 阈值后才临时表现为 fixed,且仅限于其最近的滚动祖先容器内有效;一旦滚出该容器范围,它又退回 relative 行为。
关键限制点:
立即学习“前端免费学习笔记(深入)”;
-
sticky必须指定且仅能指定top、bottom、left或right中的一个(不能同时写top和bottom) - 其父容器不能有
overflow: hidden|auto|scroll,否则粘性行为被截断(iOS Safari 尤其敏感) - 父容器需有明确高度或内容撑开,否则无滚动空间,
sticky永远不触发
fixed 完全无视滚动上下文,sticky 严格依赖滚动容器
position: fixed 总是相对于 viewport(可视窗口)定位,不管你在哪个 iframe、哪个嵌套滚动区域里,它都钉在屏幕固定坐标上;position: sticky 则只对“最近的可滚动祖先”起作用——比如一个 div 设了 overflow-y: auto,里面放一个 sticky 元素,那它只在这个 div 内部粘住,不会跑到整个页面顶部。
典型踩坑场景:
- 在 modal 弹窗里用
sticky头部,但 modal 自身用了overflow: hidden→ 粘性失效 - 把
sticky元素放在transform: translateZ(0)的父容器里 → Chrome 旧版可能禁用 sticky(现已基本修复,但低版本 Android WebView 仍有问题) - 用
display: flex+flex-direction: column布局,子项设sticky,但父项没设height→ 滚动容器不存在,sticky 不响应
z-index 行为也不同:sticky 受限于层叠上下文边界
position: fixed 默认创建新的层叠上下文(只要 z-index 不是 auto),能自由盖过其他内容;position: sticky 是否创建层叠上下文,取决于它是否满足「形成层叠上下文」的条件——比如父容器是 flex 且自身 z-index 不为 auto,或者它自己是 sticky 且设置了 z-index。
这意味着:一个 sticky 元素即使写了 z-index: 999,若其父容器是普通 div 且没触发层叠上下文,它依然会被同级的 fixed 元素压住——这不是 bug,是规范要求的层叠顺序。
最容易被忽略的一点:sticky 的“粘住”效果只发生在滚动方向上,横向滚动(overflow-x)触发的 sticky 行为在部分浏览器(如旧版 Safari)支持极差,不要默认它能稳定工作。


















