CSS transition 不会自动执行,仅响应属性值变化;页面加载时的动画需用 @keyframes + animation 实现,并配 animation-fill-mode: forwards,否则易出现 FOUC 或闪退。

它不会自动执行——这是最常见的误解。CSS transition 从不“自动播放”,只响应属性值的**变化过程**;页面一打开就动,其实是你误用了 animation,或 JS 在挂载时悄悄触发了状态变更。
transition 为什么不能在页面加载时自己动
transition 不是动画播放器,它只是浏览器对「两个已知值之间如何过渡」的声明。没有属性值变化,就没有过渡发生。
- 写
.box { opacity: 0; transition: opacity 0.3s; }→ 元素永远是opacity: 0,不会淡入 - 写
.box { opacity: 0; transition: opacity 0.3s; } .box.loaded { opacity: 1; }→ 必须通过 JS 添加loaded类,才触发 0→1 的变化 - 如果 JS 在
DOMContentLoaded后才加类,而 DOM 已渲染完成,用户会看到“先闪一下再动”,本质是 FOUC(Flash of Unstyled Content)
真正“一开就动”的其实是 @keyframes + animation
能实现零 JS、秒启动的,是 @keyframes 配合 animation,不是 transition。
-
animation是主动播放机制:只要样式被解析、元素已渲染,就会立即开始(下一帧) - 必须加
animation-fill-mode: forwards,否则播完瞬间回退到初始态(比如opacity: 0导致文字闪没) - Safari 等 WebKit 浏览器对
animation初始化更稳定,但若关键帧里用到了未定义的 CSS 变量,仍可能跳变
JS 触发 transition 时容易踩的坑
你以为加个类就完事了?浏览器渲染流水线会让你措手不及。
立即学习“前端免费学习笔记(深入)”;
- 直接
el.classList.add('loaded')后立刻读取getComputedStyle(el).opacity→ 强制同步重排,打断过渡流程 - 在
requestAnimationFrame回调外修改样式 → 浏览器可能把多次变更合并成一次渲染,导致过渡丢失 - 用
display: none或visibility: hidden包裹待动画元素 → 元素脱离渲染流,transition和animation都失效 - 服务端未注入主题类,JS 等
DOMContentLoaded才加dark类 → 页面先按亮色渲染一帧,再突变,造成“闪”
真正可控的首次加载动画,要么靠 @keyframes 写死起止态并确保变量提前定义,要么用 JS 在 documentElement 上内联写入 class(非 DOMContentLoaded 时机),否则“自动动”只是错觉,背后全是时机和渲染层的博弈。


















