固定顶部导航栏需用position: fixed并设top: 0、left: 0、width: 100%、z-index≥1000,body加padding-top防遮挡;推荐flex布局替代float;下拉菜单父级需position: relative;滚动效果须JS监听并节流;移动端注意viewport、iOS抖动及触摸穿透问题。

用 position: fixed 是最直接的方式
固定顶部导航栏的核心就是让导航容器脱离文档流,并始终贴在视口顶部。必须设置 position: fixed,同时指定 top: 0 和 left: 0(或 right: 0 配合 width: 100%),否则可能偏移或不覆盖全宽。
常见错误是只加 position: fixed 却忘了设 top,结果导航栏卡在默认文档位置;或者没设 z-index,被后续内容遮挡。
- 必须加
width: 100%,否则宽度按内容收缩,不是横贯整个屏幕 - 推荐加
z-index: 1000以上,避免被轮播图、弹窗等覆盖 - 记得给
<body>或主内容区加padding-top(值 ≥ 导航高度),否则页面首屏内容会被导航遮住
导航内部用 flex 布局比 float 更可靠
老方案常用 float: left 排列菜单项,但容易塌陷、换行错乱,响应式时更难控制。现代写法直接用 display: flex,天然支持居中、等分、自动换行(配合 flex-wrap)。
注意:如果导航里有下拉菜单,子菜单需用 position: absolute 定位,且父级要设 position: relative,否则会相对于视口定位,飘到页面任意位置。
立即学习“前端免费学习笔记(深入)”;
-
justify-content: space-between适合 logo 左对齐、登录按钮右对齐 - 用
flex: 1给中间导航项可实现弹性均分(慎用于文字长度差异大的场景) - 移动端收起菜单时,别只靠
display: none切换——要配合aria-expanded和键盘焦点管理,否则可访问性失效
滚动时加阴影或背景色变化需要监听 scroll 事件
纯 CSS 无法判断页面是否滚动,所以“滚动后变深色/加阴影”这类效果必须用 JS 监听 window.onscroll 或 IntersectionObserver(后者性能更好)。
直接绑定 scroll 容易触发过频,导致卡顿。务必节流(throttle)或用 requestAnimationFrame 包裹状态更新逻辑。
- 简单方案:
document.addEventListener('scroll', () => { nav.classList.toggle('scrolled', window.scrollY > 10) }) - 用
IntersectionObserver观察导航下方第一个 section 的boundingClientRect.top是否 ≤ 0,更精准 - 不要在 scroll 回调里反复调用
getBoundingClientRect()或操作 DOM 样式,改用 class 切换 + CSS 过渡
移动端适配要注意 viewport 和触摸穿透
没有正确的 <meta name="viewport" content="width=device-width, initial-scale=1">,fixed 在 iOS Safari 上会失效或错位。另外,iOS 15+ 中 fixed 元素在页面滚动时可能出现“抖动”或“回弹”,本质是 Safari 对视口计算的 bug。
更隐蔽的问题是:点击汉堡菜单后,底层内容仍能响应点击(尤其是 map、video 等原生组件),这是 pointer-events: none 没关干净导致的。
- 加
touch-action: manipulation到导航上,减少 iOS 误识别为拖拽 - 展开菜单时,给
<body>加overflow: hidden,防止滚动穿透 - 避免在
fixed导航内使用transform: translateZ(0)强制硬件加速——某些安卓 WebView 会因此导致点击区域偏移



















