用@keyframes实现淡入动画需显式定义from/to(或0%/100%)的opacity变化,配合animation属性及animation-fill-mode:forwards保持结束状态,避免display:none冲突、父容器裁剪或JS重排导致失效。

如何用 @keyframes + opacity 做淡入动画
直接加 animation 就行,但得配对写 @keyframes,不能只改 opacity 就以为完事了。浏览器不会自动补帧,0% 和 100% 的状态必须显式声明。
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }- 元素上加
animation: fade-in 0.3s ease-out; - 别漏
from/to—— 写成0% { opacity: 0; }和100% { opacity: 1; }也行,但少写一行就可能白跑 - 动画默认不触发:元素得先在 DOM 里、且初始状态是
opacity: 0(或靠 class 控制),否则一上来就 1,看不出“淡入”
为什么加了动画却没效果?常见三类原因
多数不是写错了,而是被 CSS 层叠或渲染时机卡住。
- 父容器有
overflow: hidden且子元素初始位置超出视口,动画过程中被裁掉——先确保元素能“露出来”再动 - 动画 class 是 JS 动态加的,但加完立刻触发重排(比如读
offsetHeight),导致浏览器跳过首帧——加个setTimeout(() => el.classList.add('fade-in'), 0)或用requestAnimationFrame - 用了
display: none控制显隐,它和opacity冲突:display: none时元素不参与渲染,opacity根本不生效——该用visibility: hidden配合opacity
animation-fill-mode: forwards 必须加吗?
必须。不加的话,动画播完会瞬间回退到 opacity: 0(或初始值),用户只看到一闪。
-
animation-fill-mode: forwards让元素保持最后一帧的样式(即opacity: 1) - 如果同时用了
transition控制其他属性(比如transform),forwards只管animation里定义的属性,不影响transition行为 - 兼容性没问题:Chrome 43+、Firefox 16+、Safari 9+、Edge 12+ 都支持
淡入慢、卡顿或闪一下?检查这些细节
性能问题往往藏在合成层和重绘逻辑里。
立即学习“前端免费学习笔记(深入)”;
- 避免在
@keyframes里同时改opacity和height/margin—— 后者触发布局(layout),拖慢动画 - 如果淡入对象是图片或带阴影的卡片,加
will-change: opacity提前提示浏览器升层,但别滥用,会增加内存开销 - 移动端 Safari 对
opacity动画优化好,但若父容器有backface-visibility: hidden或transform: translateZ(0),反而可能干扰合成——先去掉试试 - 动画时长低于 0.15s 用户感知弱,超过 0.4s 容易觉得慢;0.25s 是较稳妥的中间值
display: none 锁死——这点在 JS 控制显隐的场景里,几乎每次都要手动验证一遍。


















