height: auto 无法触发 transition 动画,因浏览器无法插值计算;须用固定高度值(如 64px→48px),transition 必须写在基础 class 上,配合 scroll 事件节流监听与 class 切换实现双向平滑过渡。

transition 不能直接动画 height: auto
这是最常卡住的地方:你写了 transition: height 0.3s,但导航栏从「正常高度」缩到「内容撑开的高度」时,过渡完全失效。因为 height: auto 无法被浏览器插值计算——transition 只认具体数值(比如 64px → 48px),不认 auto。
常见错误现象:
滚动时导航栏瞬间变小,没过渡;或者压根不变,控制台也没报错。
- 必须用固定数值替代
height: auto,比如设成height: 64px(展开态)和height: 48px(收缩态) - 如果内容行高/内边距会变,优先改
padding或line-height,而不是依赖height自适应 - 用
box-sizing: border-box避免 padding 变化导致实际高度计算偏移
用 scroll event + class 切换比纯 CSS 更可靠
CSS 的 :hover 或伪类没法响应滚动位置,必须靠 JS 监听 scroll 事件来加减 class。别信“纯 CSS 实现滚动缩放”的方案,它们要么用 position: sticky 做障眼法,要么靠视差 hack,都不真正控制 height 过渡。
使用场景:需要在页面滚动超过某个阈值(比如 100px)后触发缩小。
立即学习“前端免费学习笔记(深入)”;
- 监听
window.addEventListener('scroll', ...),但记得节流(用requestAnimationFrame或简单时间戳判断) - 用
document.documentElement.scrollTop(非 Chrome 旧版可能要用body.scrollTop)获取滚动距离 - 给导航栏元素添加 class 如
nav--scrolled,CSS 里写.nav--scrolled { height: 48px; padding: 8px 16px; }
transition 要写在基础 class 上,不是只在 hover 或动态 class 里
很多人把 transition 写在 .nav--scrolled 里,结果只有「缩小」有动画,「恢复」是瞬时的。因为 transition 必须定义在初始状态(即未滚动时的 class)上,才能双向生效。
性能影响:只过渡 height、padding、line-height 这几个属性,避免动 width 或 transform 外的布局属性,否则可能触发重排(reflow)。
- 正确写法:
.nav { height: 64px; padding: 16px 16px; transition: height 0.3s, padding 0.3s; } - 错误写法:
.nav--scrolled { transition: height 0.3s; }(恢复时无过渡) - 如果用了
transform: scale()替代 height,要加will-change: transform提前提示渲染层,但注意这会增加内存开销
移动端 Safari 的 scroll event 触发延迟问题
iOS Safari 默认启用「滚动回弹」和「异步滚动」,scroll 事件可能滞后甚至不连续触发,导致导航栏闪烁或切换不及时。
兼容性影响:仅限 iOS 15 及更早版本;iOS 16+ 有所改善,但仍建议兜底。
- 给
加touch-action: manipulation减少手势判定延迟 - 监听
scroll时加上{ passive: true }(现代浏览器默认,但显式声明更稳妥) - 关键逻辑别只依赖 scroll 事件,可结合
IntersectionObserver监控顶部区域是否离开视口,作为辅助判断


















