应同时使用 opacity 和 visibility 实现平滑淡入淡出:opacity 控制透明度过渡,visibility 在动画结束后立即切换以彻底移除交互与可访问性影响,避免卡顿、遮挡和读屏器误读。

直接用 opacity 做淡入淡出,页面会“卡住”或“闪一下”,根本不是你想要的平滑切换——因为只改透明度不触发重排,DOM 还在占位、仍可点击、屏幕阅读器照读不误。
为什么只写 transition: opacity 不行
浏览器对 opacity 的过渡是纯合成层操作,不强制触发 layout 或 paint 阶段。结果就是:元素视觉上变透明了,但布局空间还在、事件监听没失效、z-index 层级没释放。尤其在 iOS 15.4+,低功耗模式下帧率掉到两帧,动画直接糊成一块。
-
opacity: 0后元素仍响应click和focus - 屏幕阅读器(如 VoiceOver)不会跳过它,除非加
aria-hidden="true" - 多个引导页叠加时,
opacity: 0的页仍参与 stacking context,可能遮挡后续页的触摸区域
opacity + visibility 必须同时控制
真正退出视觉与交互流程,得靠 visibility: hidden 切断渲染管线,又不破坏文档流(比 display: none 更稳妥)。关键在于两个属性必须在同一时刻生效,不能靠 setTimeout 或 CSS delay 错开。
- 入场动画:
opacity: 0; visibility: hidden;→opacity: 1; visibility: visible; - 退场动画:
opacity: 1; visibility: visible;→opacity: 0; visibility: hidden; - 务必给容器加
transition: opacity 300ms ease, visibility 0s 300ms:让visibility在 opacity 动画结束后立刻切换,避免中间态
移动端引导页的 DOM 结构要点
不要把所有引导页塞进一个 div 然后靠 transform 移动——这会让 PageTransformer 失效,且无法精准控制单页生命周期。推荐用原生 section 并列结构,配合 JS 控制 class:
立即学习“前端免费学习笔记(深入)”;
<section class="guide-page is-active">...</section> <section class="guide-page">...</section> <section class="guide-page">...</section>
- 当前页加
is-active,其余页保持opacity: 0; visibility: hidden; - 切换时先移除旧
is-active,再给新页加,避免双 active 导致 z-index 冲突 - 别给整个
.guide-page加will-change: opacity,内存暴涨,首屏加载明显变慢
iOS 与 Android 的兼容性微调
iOS Safari 对 visibility 的 transition 支持更严格,Android Chrome 则偶尔忽略 visibility 0s 的延迟。稳妥做法是补一层 pointer-events: none 配合:
- 退场页加:
opacity: 0; visibility: hidden; pointer-events: none; - 入场页加:
opacity: 1; visibility: visible; pointer-events: auto; - 避免用
transform: translateZ(0)强制硬件加速——在低端 Android 上反而引发闪烁
最易被忽略的一点:动画结束后的状态清理。比如用户快速连点两次“下一步”,可能触发两轮 opacity 过渡,导致某一页最终停留在 opacity: 0.5 卡死。务必在 transitionend 回调里做终态校验,手动 reset 到 opacity: 0 或 1。这不是锦上添花,是保底逻辑。


















