transition-delay 对鼠标移出看似无效,实则双向生效导致“双向卡顿”;真正控制移出延迟需用 :not(:hover) 单独绑定延迟,并配合 visibility: hidden 与 opacity 联动过渡以禁用交互。

transition-delay 为什么对鼠标移出没效果?
因为 transition-delay 不区分 hover 进入还是离开——只要属性值变了,它就等那么久才开始过渡。写成 .menu { transition: opacity 0.2s ease 0.3s; },结果是:鼠标刚移入要等 0.3s 才淡入,移出也要等 0.3s 才淡出。这不是“移出延迟”,这是“双向卡顿”。
真正控制移出延迟的写法是用 :not(:hover)
必须把延迟逻辑单独绑在「隐藏态」上,让入场无延迟、退场有延迟:
- 默认状态(收起)设
opacity: 0; visibility: hidden;,并配完整过渡:transition: opacity 0.2s ease, visibility 0.2s ease; -
:hover状态只改opacity: 1; visibility: visible;,不加transition-delay - 关键一步:用
.nav-item:not(:hover) .submenu规则显式加延迟:transition-delay: 0.2s;
这样,只有鼠标离开时,:not(:hover) 生效,触发带延迟的收起;入场则立刻响应。
为什么一定要配 visibility: hidden?
opacity: 0 只是透明,元素仍在文档流里、仍可点击、仍接收事件。用户在延迟期内划过菜单区域,可能误点到看不见的子项。
立即学习“前端免费学习笔记(深入)”;
- 仅靠
opacity+transition-delay无法禁用交互 -
visibility: hidden能真正移除交互能力,但它本身不可过渡——所以必须和opacity联动,且两者transition-duration必须一致 - 别写
visibility: hidden单独过渡,浏览器会忽略;必须写成transition: opacity 0.2s, visibility 0.2s;
多级菜单怎么倒序设延迟?
transition-delay 不继承,也不按 DOM 深度自动累加。你得手动给每级设不同值,并确保视觉上最后出现的,退出延迟最短。
- 一级菜单展开的子菜单,退出延迟设
0.3s - 二级菜单展开的子菜单,退出延迟设
0.2s - 三级菜单展开的子菜单,退出延迟设
0.1s - 所有延迟都写在对应层级的
:not(:hover)规则里,例如:.submenu-1:not(:hover) .submenu-2
移动端要特别注意:iOS Safari 对 :not(:hover) 支持不稳定,必须用 JS 监听 touchstart 并临时加类 fallback。


















