直接给 visibility 加 transition 无效,必须协同 opacity 动画:淡出时先降 opacity 再设 visibility: hidden;淡入时先设 visibility: visible 再触发动画;需用 transitionend 精准控制 visibility 切换,并同步处理 pointer-events 和无障碍状态。

直接给 visibility 加 transition 是无效的,动画卡顿、误触、闪一下——这些都不是 bug,是没处理好 opacity 和 visibility 的协同时机。
opacity 动画开始前必须保持 visibility: visible
常见错误是:一触发隐藏就立刻设 visibility: hidden,结果 opacity: 0 动画根本没机会渲染,元素“啪”地消失。浏览器看到 visibility: hidden 就跳过绘制,过渡直接失效。
- 淡出时:先只改
opacity(从 1 → 0),visibility仍为visible - 淡入时:类名切换前,JS 先设
element.style.visibility = 'visible',再加show类触发opacity动画 - 别用
display: none初始化状态——它会中断后续所有 CSS 动画
visibility 切换必须滞后于 opacity 动画结束
visibility 本身不支持插值,但你可以靠 transitionend 事件精准控制它何时生效。这是唯一可靠的方式,纯 CSS 的 step-end 在 IE 和部分旧版 Safari 里不认。
- 监听
transitionend,检查event.propertyName === 'opacity' - 确认是 opacity 动画结束,再设
element.style.visibility = 'hidden' - 反向恢复时,顺序不能颠倒:先
visibility: visible,再改opacity值(或加类) - 如果用了
pointer-events: none,也得在 opacity 动画开始前就加上,否则透明时仍可能拦截点击
无障碍关键:opacity=0 时元素仍能被焦点捕获
屏幕阅读器和键盘导航不会因为 opacity: 0 就跳过该元素。用户按 Tab 键仍可能 focus 到一个“看不见却可操作”的按钮上,这违反 WCAG 4.1.2。
-
visibility: hidden能让元素退出可访问树(accessibility tree),但不释放布局空间 - 若需彻底移除语义,动画结束后应通过 JS 移除 DOM 或加
aria-hidden="true"并同步控制visibility - 不要只依赖
opacity做“隐藏”判断——它只是视觉层,不是语义层 - 对表单控件(如
<input>),visibility: hidden比opacity: 0更安全,前者阻止聚焦,后者不阻止
真正难的不是写两行 CSS,而是把 opacity 的视觉节奏、visibility 的语义切换、pointer-events 的交互屏蔽、以及无障碍 API 的状态同步,全部压在同一帧节奏里——稍有错位,就变成“看得见却点不到”或“看不见却被读出来”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











