直接用 opacity + transition 实现淡入动画最可靠,关键在于预设类(如.fade 和 .fade.show)并正确触发,避免直接改 style 或误用 transition: all;逐字淡入需遍历 DOM 节点包裹字符,而非操作 innerHTML。

直接用 opacity + transition 就能实现可靠、高性能的淡入动画,不需要 JS 也能工作,但必须写对触发时机和初始状态。
为什么 class 切换比直接改 style 更稳
很多人用 JS 直接写 element.style.opacity = '1',结果动画不执行——因为浏览器没机会“看到”从 0 到 1 的变化过程。CSS 过渡依赖“状态切换”,不是“值变更”。
正确做法是预设好两个类:.fade(opacity: 0; transition: opacity 0.3s ease;)和 .fade.show(opacity: 1;),再用 classList.add('show') 触发。
常见错误:
- 把
transition写在.show里,首次添加类时无过渡(因为初始状态没声明 transition) - 用
display: none配合 opacity,导致元素瞬间消失,过渡被截断 - 忘记加
visibility: hidden,让opacity: 0的元素仍可点击、占位、影响 tab 键顺序
transition 属性名不能偷懒写 all
transition: all 0.3s ease 看起来省事,但风险明显:如果后续不小心改了 height 或 margin,这些属性也会参与过渡,造成布局抖动或意外动画。淡入只该动透明度。
务必写全:transition: opacity 0.3s ease-in-out;
额外注意:
- IE9+ 支持
opacity和transition,无需前缀 - 时间别设太短(
0.1s)或太长(1.2s),0.2–0.4s 是人眼感知最自然的区间 - 如果元素默认是
display: none,得先设成display: block(或 inline/block-level 合适值),再加.show类,否则 transition 不生效
需要逐字淡入?别碰 innerHTML +=
想实现“一个字一个字浮现”的效果,千万别用循环拼接字符串再赋给 innerHTML。这会破坏所有嵌套结构:<strong></strong> 失效、<a></a> 变纯文本、事件监听器全丢、甚至 HTML 实体(如 )解析错乱。
安全做法是遍历 DOM 节点:
- 用
Node.childNodes深度遍历,识别Text节点 - 对每个文本节点,拆成字符数组,用
setTimeout或requestAnimationFrame逐个包裹进<span class="fade-char"></span> - 为
.fade-char单独设opacity: 0+transition,再逐个加show类
这样保留原始语义、样式继承和交互能力,只是多几行 JS。
animation 和 transition 选哪个
纯淡入淡出,transition 足够;但如果你要控制节奏(比如淡入同时上移 4px)、循环播放、或定义中间帧(0% → 30% 加速 → 100% 缓入),就得用 @keyframes + animation。
关键区别:
-
transition是“有状态变化才动”,适合用户交互触发(点击/悬停) -
animation是“到时间就动”,适合自动播放、复杂时序,但结束帧默认不保留(除非加animation-fill-mode: forwards) - 用
animation时,opacity只是其中一帧属性,别漏写from { opacity: 0; }和to { opacity: 1; }
最容易被忽略的是:用 animation-fill-mode: forwards 后,元素最终 opacity 被锁定为 1,后续想淡出,得手动重置或切换另一套动画类——这不是 bug,是设计如此。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











