display无法参与transition,因其取值无数值关系不可插值,浏览器直接丢弃该规则;元素设为none时脱离渲染树,导致其他过渡属性失效;正确方案是opacity与visibility协同控制,并用transition-delay错开时机。
因为 display 是离散属性,浏览器根本不计算中间状态,transition 根本不会启动——不是卡住,是压根没机会运行。
display 的取值(none、block、flex 等)之间没有数值关系,无法插值。浏览器渲染引擎在解析 transition: display 0.3s 时,会直接丢弃这条规则——你在 DevTools 的 “Computed” 面板里根本找不到它。
更关键的是:display: none 会让元素彻底脱离渲染树。一旦脱离,连样式计算都停止,opacity、transform 等本可过渡的属性也一并失效。
transition: all 0.3s 没用,只要涉及 display 切换,整个过渡链就断了el.style.display = 'block' 再加 el.classList.add('fade-in'),浏览器会合并重绘,起始帧丢失display: none,子元素哪怕写了 transition: opacity 0.3s,也完全不触发必须两个属性协同控制,且过渡时机要错开:让 visibility 在 opacity 动画结束那一刻才切换,否则会出现“闪一下”或“悬停可点但不可见”的问题。
立即学习“前端免费学习笔记(深入)”;
opacity: 0 + visibility: hidden + pointer-events: none
transition: opacity 0.3s ease, visibility 0s 0.3s(visibility 延迟 0.3s 才生效)opacity: 1 + visibility: visible + pointer-events: auto + transition-delay: 0s
transitionend 事件,检查 event.propertyName === 'opacity',再设 el.style.display = 'none' 和 aria-hidden="true"
仅限框架约束强、无法改 CSS 的场景。核心是打断浏览器的批量优化,让它“看到”元素已就位。
parent.style.display = 'block'
parent.offsetHeight(不能用 getComputedStyle,必须是 layout 触发属性)opacity 或 transform
所有方案都依赖元素始终保留在渲染树中。一旦你提前删 DOM、或过早设 display: none,过渡就彻底没了——不是没效果,是根本没启动。
更隐蔽的是:动画结束但没清理 tabindex 或焦点状态,键盘用户可能卡在不可见元素上;父容器有 overflow: hidden 时,visibility: hidden 仍占位,可能引发滚动条抖动。