首选 position: sticky 因其天然支持滚动吸附、不破坏文档流、无需监听 scroll;但需设 top 值、父容器禁用 overflow 隐藏,且 IE 不支持;fixed 则需手动处理布局空缺、z-index 和 iOS 键盘错位等问题。

顶部导航固定,优先用 position: sticky;只有需要兼容 IE 或必须脱离文档流时,才退回到 position: fixed。
为什么 position: sticky 是首选
它天然支持“滚动到某位置才吸附”,不破坏文档流,不影响后续元素布局,也不需要手动计算高度或监听 scroll 事件。
- 必须设置一个有效的
top值(如top: 0),否则无效 - 父容器不能有
overflow: hidden|auto|scroll,否则会截断粘性行为 - 只对块级元素生效,
display: block或flex容器内的子项均可 - IE 完全不支持,Edge 16+ 开始支持,移动端 Safari 从 iOS 12.2 起稳定支持
position: fixed 的实际用法和坑点
它强制脱离文档流,常用于需要覆盖内容、或滚动时始终压在最上层的场景,但代价是需手动处理布局空缺和 z-index 冲突。
- 必须加
width: 100%(否则默认收缩为内容宽度) - 要预留下方内容的
margin-top或padding-top,值等于导航高度,否则会被遮挡 - 若页面有横向滚动,
fixed元素可能错位,需配合left: 0; right: 0;锁定水平范围 - 在 iOS Safari 中,键盘弹出时
fixed元素可能错位,需监听focusin/focusout临时切回absolute
如何让 sticky 导航在滚动后保持阴影/背景变化
单纯靠 CSS 无法检测“是否已粘住”,但可以利用 :not(:placeholder-shown) 这类伪类做间接判断——不行。真实可行的是:用 JS 监听 getBoundingClientRect().top 是否 ≤ 0,然后切换 class。
立即学习“前端免费学习笔记(深入)”;
- 推荐轻量方案:给导航加
data-sticky-state属性,JS 更新为"stuck"或"unstuck" - CSS 中写
[data-sticky-state="stuck"] { box-shadow: 0 2px 8px rgba(0,0,0,.1); background: white; } - 避免在
scroll事件里直接操作 DOM,用requestAnimationFrame节流
真正麻烦的不是写法本身,而是不同设备下滚动触发时机、父容器 overflow 隐藏、以及 fixed 在软键盘唤起时的错位——这些细节不测真机,光看桌面预览永远发现不了。










