view transitions api 直接接管主题切换动画,通过startviewtransition()捕获dom变更前后的视觉快照,css仅定义::view-transition-old(root)和::view-transition-new(root)的动画行为,无需手动控制过渡时机或属性;它不支持css自定义属性过渡,且要求dom更新必须同步执行、不可异步延迟。

View Transitions API 不是用来“配合 CSS 换肤”的补丁,而是直接接管换肤过程的动画控制权——只要 DOM 状态变了,它就自动拍快照、做过渡,CSS 只负责定义怎么动,不用管“何时动”或“动哪些属性”。
为什么直接改 :root 变量 + transition 会失效
常见错误是这样写:
:root {
--bg: #fff;
--text: #000;
transition: --bg 0.3s, --text 0.3s;
}
.theme-dark {
--bg: #121212;
--text: #eee;
}
这段代码在绝大多数浏览器里根本不会触发过渡动画。原因很实在:
- CSS
transition不支持自定义属性(--xxx)作为可过渡属性,这是规范限制,不是兼容性问题 - 即使某些实验性版本能动,也只限于极少数属性(如
color、background-color),且无法协调几十个变量同步变化 - DOM 没有结构变化,浏览器不会触发重绘帧调度,
transition失去执行上下文
document.startViewTransition() 怎么用在主题切换里
核心就一行:把「切换 class」或「更新 data-theme」的动作包进 startViewTransition 回调里。浏览器会自动捕获切换前后的整页视觉状态。
示例(配合 useDark):
const { isDark, toggle } = useDark({
storageKey: 'theme',
onChanged: (val) => {
// 关键:所有 DOM 更新必须在这里完成,且包裹进 view transition
if (document.startViewTransition) {
document.startViewTransition(() => {
document.documentElement.setAttribute('data-theme', val ? 'dark' : 'light')
})
} else {
document.documentElement.setAttribute('data-theme', val ? 'dark' : 'light')
}
}
})
注意点:
- 不要在
onChanged外部手动改data-theme,否则会绕过过渡 -
startViewTransition必须在 DOM 更新语句的**同一同步调用栈**里,不能丢进setTimeout或Promise.then - 它不关心你用的是 class、
data-属性还是style,只认“DOM 是否变了”
::view-transition-old(root) 和 ::view-transition-new(root) 怎么定制
这两个伪元素代表整个页面的旧视图和新视图快照,是主题过渡的主战场:
::view-transition-old(root) {
animation: fade-out 0.4s ease-out;
z-index: 100;
}
::view-transition-new(root) {
animation: fade-in 0.4s ease-in;
z-index: 99;
}
<p>@keyframes fade-out {
from { opacity: 1; }
to { opacity: 0.85; } /<em> 留一点余光,避免全黑/全白闪屏 </em>/
}
@keyframes fade-in {
from { opacity: 0.85; }
to { opacity: 1; }
}</p>
实用技巧:
- 动画时长建议设为
0.3s–0.5s,太短没感知,太长像卡顿 - 避免用
opacity: 0→1的硬切,用0.85 → 1更柔和,尤其对深色模式 - 加
z-index是为了防止新旧层错位,老版本 Chrome 有渲染层叠 bug - 如果想做“涟漪扩散”效果,得配合
view-transition-name绑定点击元素,而不是用root
兼容性兜底和容易被忽略的细节
Chrome 111+ 原生支持,Firefox 和 Safari 已进入实现阶段(2026 年中预计全覆盖),但当前仍需判断:
- 检查
if ('startViewTransition' in document),别只看document.startViewTransition是否存在(有些 polyfill 会挂空函数) - SSR 场景下,服务端渲染的初始
data-theme必须和客户端一致,否则首次切换会因 DOM 不匹配导致过渡失败 - 第三方组件(如图表库、富文本编辑器)若直接操作
style或内联color,可能不响应:root变量,需要额外加!important或用color-scheme做基础适配 - 过渡动画期间,
pointer-events: none会默认加在::view-transition-group上,所以别在动画中试图点击按钮——这不是 bug,是浏览器防误触机制
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











