滚动方向判断必须用差值,不能只看scrollY绝对值;prevScrollPos需初始化为window.pageYOffset;差值小于2px需防抖;transition应始终写在基础类中;移动端需注意fixed宽度错位、sticky失效及padding-top设置。

滚动方向判断必须用差值,不能只看 scrollY 绝对值
很多开发者一上来就写 window.scrollY > 100,结果发现“向上滚不出现”,因为这个条件只管向下滚了多少,不管方向。真正要捕获“向上滚动”动作,得靠连续两次滚动位置的差值。
-
prevScrollPos必须在页面加载时初始化为window.pageYOffset,不能设成 0 - 每次
scroll触发时,先算currentScrollPos = window.pageYOffset,再比较prevScrollPos > currentScrollPos - 差值小于 2px 就忽略(防抖),避免手指滑动抖动误触发
- 别在回调里直接读
offsetTop或调getBoundingClientRect()—— 强制重排,iOS 上明显卡顿
显示/隐藏靠 top 值切换,但 transition 必须始终生效
只给“显示态”加 transition: top 0.4s ease-out 是常见错误。一旦移除类或改 style.top,过渡就断了,导致隐藏瞬间闪退。
- 把
transition: top 0.4s ease-out写在基础导航栏 class 里(比如.navbar),而不是仅在某个状态类中 - 用
top: 0表示显示,top: -72px表示隐藏(数值必须等于导航栏实际高度,用getBoundingClientRect().height动态取更稳) - 移动端要注意:如果用了
transform: scale()或轮播图动画,父容器可能创建新层叠上下文,导致fixed元素 z-index 失效 —— 此时显式加z-index: 1000并检查父级是否含overflow: hidden
position: sticky 在这里基本不可靠
position: sticky 不是“固定”,而是“临界吸附”。它只在元素滚动到包含块顶部时才生效,且极易被破坏。
- 父容器设了
overflow: hidden、transform、filter→ 直接失效 - 导航栏直接挂在
<body>下,但<html>设了overflow-x: hidden→ 视口无法滚动,sticky 彻底不触发 - banner 区域还没滚走,导航就在顶部空等 ——
top值得设成负数(如top: -120px)让它提前入场 - 旧版 Safari(iOS 13 及更早)对 sticky 支持极差,尤其嵌套滚动容器下几乎必挂
移动端 fixed 导航栏的宽度和遮挡问题
在 iPhone 上,width: 100% 会导致导航栏左右缩放时错位,而内容区没加 padding-top 会直接被盖住。
立即学习“前端免费学习笔记(深入)”;
- 导航栏用
width: 100vw替代100%,避免 viewport 缩放偏差 -
<body>或主内容容器必须加padding-top: 72px(值 = 导航栏真实高度),不能靠margin-top撑开 - 别给导航栏设
margin-top——fixed元素的 margin 不参与布局计算,只会造成视觉偏移 - 如果页面有横向滚动区域(比如表格溢出),
100vw可能撑宽视口,此时改用width: calc(100% + 1px)+overflow-x: hidden在 body 上兜底



















