@starting-style 已被 w3c 正式移除,主流浏览器均不支持,无法触发首次显示过渡;其设计前提为元素已存在于 dom 且参与样式计算,对 display: none 或动态插入元素无效。

@starting-style 目前在任何主流浏览器中都不起作用,写上它不会报错,但也不会触发任何初始过渡效果。
为什么 @starting-style 无法用于首次显示的过渡
它被设计用来解决“元素首次样式更新时 transition 跳过起始值”的问题,但前提是元素已存在于 DOM 中、且参与样式计算。一旦元素是 display: none 或刚动态插入,浏览器根本不会读取或应用 @starting-style 声明。
常见错误现象包括:
- 元素从
display: none切换为block后,opacity或transform过渡直接跳到终值,没有动画 - DevTools 的 Computed 面板里查不到
@starting-style设置的值 - 即使写了
@starting-style { opacity: 0; transform: translateY(20px); },实际动画仍从opacity: 1开始
替代方案:用 visibility + requestAnimationFrame 强制初始帧
这是目前最稳定、兼容性最好的手动控制方式,核心是让浏览器“意识到”初始状态存在,再触发重绘。
关键步骤:
- 元素初始设为
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);
// 强制触发样式计算
getComputedStyle(el).opacity;
requestAnimationFrame(() => {
el.style.visibility = 'visible';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
});
更现代的选择:animate() API + fill: 'backwards'
如果你不需要支持 IE 或旧版 Safari,Element.animate() 是真正可控的入场方案,fill: 'backwards' 能准确指定动画未开始时的视觉状态。
优势包括:
- 不依赖 CSS 类切换时机,避免 race condition
- 可精确控制 easing、duration、iteration,且默认启用
fill: 'backwards' - 动画结束后可自然保留在终态(配合
fill: 'forwards')
示例:
el.animate(
[
{ opacity: 0, transform: 'translateY(20px)' },
{ opacity: 1, transform: 'translateY(0)' }
],
{ duration: 300, easing: 'ease-out', fill: 'both' }
);
@starting-style 的真实现状(截至 2026 年 6 月)
它已被 W3C 从 Animations Level 4 规范中正式移除;Chrome 125、Firefox 127、Safari 17.5 均不解析该规则;所有文档中提到的“支持”都指向已废弃的实验性 flag 或误读的早期 Chromium 行为。
最容易被忽略的一点是:即使你看到某篇教程演示成功了,大概率是因为它混用了 animation + forwards 或 JS 控制逻辑,而非 @starting-style 本身生效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











