height: auto 无法直接使用 transition,因浏览器无法计算高度差;应改用 max-height、transform 或 JS 测量方案,并注意 overflow、过渡时机及移动端适配。

transition 不能直接作用于 height: auto
这是最常见的卡点:给 height: auto 加 transition 完全无效,浏览器无法计算起始/结束高度差。必须用固定值(如 height: 0 → height: 200px)或替代方案。
- 方案一:用
max-height代替height,设一个足够大的安全上限(比如max-height: 500px),再配合overflow: hidden - 方案二:用
transform: scaleY(0)→transform: scaleY(1),性能更好但需注意子元素布局影响 - 方案三:用 JS 测量真实高度后动态设置
height,适合内容高度差异大且需精确控制的场景
透明度 + 高度组合过渡的写法
推荐用 max-height + opacity 组合,兼顾兼容性与语义清晰。注意两者过渡时机要对齐,否则会出现“先闪出再淡入”或“悬停时半透明菜单突然弹出”等问题。
-
opacity从0→1,同时max-height从0→500px(确保大于所有可能内容高度) - 必须给父容器加
overflow: hidden,否则max-height超出部分会溢出显示 - 过渡时间统一设为
0.25s,缓动函数推荐cubic-bezier(0.4, 0, 0.2, 1)(类似 Material 的标准缓入缓出)
.dropdown-menu {
opacity: 0;
max-height: 0;
overflow: hidden;
transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1),
max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.dropdown:hover .dropdown-menu,
.dropdown-menu:focus-within {
opacity: 1;
max-height: 500px;
}
hover 触发时的常见 bug 和修复
纯 CSS 下拉菜单最常遇到鼠标移入移出间隙导致菜单闪退,尤其在菜单项之间有空隙时。
- 给触发元素(如
.dropdown)和下拉容器(.dropdown-menu)之间加一个「连接区」:用margin-top: -1px或负gap消除视觉断层 - 避免用
:hover直接写在.dropdown-menu上,应写在父级(如.dropdown:hover .dropdown-menu),否则移出触发区瞬间就收起 - 如果支持键盘导航,记得补上
:focus-within,否则 Tab 键无法稳定展开
移动端适配要注意什么
触摸设备没有 hover 状态,纯 :hover 会失效。不能只依赖 CSS,得配合少量 JS 切换 class。
立即学习“前端免费学习笔记(深入)”;
- 给下拉触发按钮加
click事件,切换.is-open类,CSS 改用.is-open .dropdown-menu控制展开 - 用
touchstart+preventDefault()防止双击缩放干扰,但别禁掉所有默认行为 -
安卓 WebView 中
transform+opacity组合比max-height更稳定,尤其是长列表滚动时
max-height 方案够用,但一旦菜单项高度变化频繁(比如图文混排、行数不固定),就得切到 JS 测量方案——不是因为 CSS 不够好,而是浏览器真没法算 auto 的过渡中间值。










