position: sticky 最省事,需父容器有明确高度且可滚动、设 top 值、禁用 overflow: hidden;fixed 需手动留白、高度固定;滚动必须作用于内容容器而非 body;iOS Safari 旧版对 sticky 有限制。

固定头部用 position: sticky 最省事
只要父容器有明确高度且可滚动,position: sticky 就能天然实现“滚动时吸附顶部、超出后释放”的效果,比 fixed 更符合文档流,也不用额外计算偏移。
- 必须设置
top值(如top: 0),否则不生效 - 父容器不能是
overflow: hidden,否则 sticky 区域被裁剪,行为异常 - 父容器需有明确高度或内容溢出(比如设了
max-height+overflow-y: auto) - 不支持 IE,Edge 15+ 才开始支持;移动端 Safari 9.0+ 支持,但旧版 iOS 有渲染抖动问题
.header {
position: sticky;
top: 0;
background: #fff;
z-index: 100;
}
.scroll-container {
max-height: 400px;
overflow-y: auto;
}
position: fixed 要手动处理布局留空
用 fixed 固定头部会脱离文档流,下面的内容会直接顶上来,必须给主体区域加 margin-top 或 padding-top 补齐头部高度,否则内容被遮挡。
- 头部高度必须已知或可预测(比如固定
60px),否则得用 JS 动态读取offsetHeight - 如果页面缩放或字体加载导致头部高度变化,
margin-top可能错位 -
fixed元素默认相对于视口定位,若父容器有transform、perspective或filter,会创建新的 containing block,导致定位异常
.header-fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
z-index: 100;
}
.main-content {
margin-top: 60px; / 必须和 header 高度一致 /
}
滚动内容区域必须显式定义可滚动范围
无论用 sticky 还是 fixed,真正滚动的必须是内容容器本身,而不是整个 body —— 否则固定头部会随页面滚动一起消失(fixed)或失效(sticky)。
- 避免对
html或body设置overflow: auto,这会让整个页面滚动,头部失去“相对滚动容器”的锚点 - 推荐把滚动容器设为一个独立区块(如
.content-wrapper),并控制其尺寸与溢出 - 若使用
flex布局,注意flex: 1容器需配合min-height: 0才能正确触发内部滚动
.layout {
display: flex;
flex-direction: column;
height: 100vh;
}
.header { / ... / }
立即学习“前端免费学习笔记(深入)”;
.content-wrapper {
flex: 1;
min-height: 0; / 关键:允许 flex 子项收缩并触发内部滚动 /
overflow-y: auto;
}
移动端 iOS Safari 的 sticky 兼容性陷阱
iOS 15.4 之前,position: sticky 在 overflow-scrolling: touch(已废弃)或某些 flex 容器中会完全失效,或只在首次滚动时生效。这不是 bug,而是 WebKit 对 sticky 触发条件的严格限制。
- 确保滚动容器没有
-webkit-overflow-scrolling: touch(现代 iOS 已不需要) - 避免在
sticky元素上设置backface-visibility: hidden或will-change: transform,这些会干扰粘性计算 - 若必须兼容老 iOS,降级方案是监听
scroll事件 +getBoundingClientRect().top判断位置,再切fixed类名
真正麻烦的不是写法,而是不同场景下“谁在滚、谁该停、谁要让位”这三者的边界是否清晰——漏掉任意一环,头部就可能消失、重叠或卡住不动。










