@starting-style 已被 w3c 移除且所有主流浏览器均不支持,它仅在元素已布局并发生状态变更时才生效,对动态插入或 display: none 元素无效;推荐用 getcomputedstyle 强制重排后 requestanimationframe 切换样式,或使用 element.animate() 配合 fill: 'backwards' 实现可靠入场动画。

@starting-style 已被 W3C 正式移除,当前任何主流浏览器都不支持它。你写上它不会报错,但也不会触发任何动画效果——它就是个“静默失效”的规则。
如果你正试图用 @starting-style 让一个刚插入 DOM 的元素(比如 document.createElement('div'))产生首次显示的 transition 动画,那这条路走不通。
@starting-style 为什么不起作用
- 它的设计前提是:元素已存在于 DOM 中、且已参与样式计算(即已 layout),只是首次应用某个 class 或状态变更。
- 对
display: none元素、动态插入后立刻加 class 的元素、或服务端渲染后首屏直接带 class 的元素,@starting-style完全不生效。 - DevTools 的 Computed 面板里查不到它设置的值,说明浏览器压根没读取这条规则。
- 常见现象:元素从隐藏到显示时,
opacity或transform直接跳到终值,没有过渡。
替代方案:手动控制初始帧(兼容性最好)
这是目前最稳定、无需 polyfill、所有现代浏览器都支持的做法:
- 元素插入前设为
visibility: hidden+ 初始动画样式(如opacity: 0,transform: translateY(20px)) - 插入 DOM 后立即调用
getComputedStyle(el).opacity(或其他任意可读属性),强制触发 layout - 在
requestAnimationFrame回调中移除visibility: hidden并设为目标样式
el.style.visibility = 'hidden';
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
document.body.appendChild(el);
<p>// 强制读取,触发重排
getComputedStyle(el).opacity;</p><p>requestAnimationFrame(() => {
el.style.visibility = 'visible';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
});</p>
注意:
- 不要用
offsetTop或clientWidth等可能触发重排的属性代替getComputedStyle,容易引发 layout thrashing -
visibility: hidden是关键:它让元素在渲染树中但不可见,确保 transition 能捕获起始状态
更现代的选择:Element.animate() + fill: 'backwards'
如果你不需要支持 IE 或 Safari ≤ 16.6,推荐直接用原生动画 API:
el.animate(
[
{ opacity: 0, transform: 'translateY(20px)' },
{ opacity: 1, transform: 'translateY(0)' }
],
{
duration: 300,
easing: 'ease-out',
fill: 'backwards' // ← 关键:动画未开始时就应用起始帧
}
);
优势:
- 不依赖 CSS 类名切换时机,无 race condition
-
fill: 'backwards'确保元素一插入就呈现初始状态,transition 无法做到这点 - 动画结束后可自然保留在终态(配合
fill: 'forwards')
@starting-style 的核心问题在于它试图用声明式语法解决一个需要精确时序控制的问题——而浏览器渲染管线并不给它这个机会。真正可控的入场动画,必须显式干预“何时读取初始样式”和“何时触发动画”,这点靠纯 CSS 规则已经力不从心。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











