View Transitions API工作原理
View Transitions API是浏览器原生的页面过渡动画方案,无需JavaScript动画库即可实现流畅的页面切换效果。它的核心机制是在DOM变更前捕获当前页面快照(Old State),执行DOM更新后再捕获新快照(New State),浏览器自动对两组快照执行交叉淡入淡出(Cross-Fade)动画。
最基本的调用只需一行代码:
document.startViewTransition(() => {
document.querySelector(".content").innerHTML = newContent;
});
浏览器执行流程:1) 捕获当前页面快照作为::view-transition-old伪元素;2) 执行回调函数更新DOM;3) 捕获新页面快照作为::view-transition-new伪元素;4) 对两组伪元素执行默认的300ms交叉淡入淡出动画。
自定义过渡动画与关键帧控制
默认的淡入淡出过于简单,通过CSS伪元素可以精细控制每个元素的过渡动画。浏览器为每个参与过渡的元素生成一组伪元素树:
::view-transition {
animation-duration: 0.5s;
}
::view-transition-group(card) {
animation-duration: 0.4s;
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
::view-transition-old(card) {
animation-name: fade-out-and-shrink;
}
::view-transition-new(card) {
animation-name: fade-in-and-grow;
}
@keyframes fade-out-and-shrink {
from { opacity: 1; transform: scale(1); }
to { opacity: 0; transform: scale(0.9); }
}
@keyframes fade-in-and-grow {
from { opacity: 0; transform: scale(1.1); }
to { opacity: 1; transform: scale(1); }
}
通过view-transition-name属性给元素命名,使其独立参与过渡计算。未命名的元素使用默认root过渡,命名元素拥有独立的过渡动画组。这允许同一页面中不同区域有完全不同的过渡效果。
跨文档导航(MPA模式)
Chrome 111+支持跨文档的View Transitions,适用于多页面应用(MPA)的整页导航。启用方式在meta标签中声明:
<meta name="view-transition" content="same-origin">
同一origin下的页面导航自动触发过渡动画。旧页面离场和新页面入场在浏览器层面协同,无需JavaScript介入。页面间如果存在同名的view-transition-name元素,浏览器会自动执行morphing动画——旧页面的元素平滑变形为新页面的对应元素,而非简单的淡入淡出。
典型应用场景是列表页到详情页的过渡:列表页的卡片图片设置view-transition-name: card-image,详情页的主图也设置相同名称,浏览器自动将小图动画放大为详情页的大图,实现视觉连续性。
SPA路由切换中的过渡方案
在React/Vue等SPA框架中,路由切换使用View Transitions API需要与框架的生命周期配合。以React为例,通过useViewTransition自定义Hook封装:
import { useTransition } from "react";
function useViewTransition(callback) {
const [isPending, startTransition] = useTransition();
const transition = () => {
if (!document.startViewTransition) {
callback();
return;
}
const vt = document.startViewTransition(() => {
startTransition(() => {
callback();
});
});
return vt;
};
return { transition, isPending };
}
function Navigation() {
const { transition } = useViewTransition();
return (
<Link onClick={() => transition(() => navigate("/detail"))}>
查看详情
</Link>
);
}
React的startTransition确保DOM更新在回调中执行,View Transitions API的回调完成后再捕获新快照,时序正确。
性能优化与降级策略
View Transitions API在快照捕获时会额外渲染一帧,对复杂页面可能引入延迟。优化手段包括:
1. 减少参与过渡的元素:只给需要动画的关键元素设置view-transition-name,其余元素使用默认root过渡
2. contain属性隔离:对静态区域设置contain: layout paint,避免不必要的重绘参与快照
3. prefers-reduced-motion适配:尊重用户的无障碍偏好设置
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.01ms !important;
}
}
4. 特性检测降级:不支持View Transitions的浏览器(Firefox、Safari尚未完整支持)直接执行DOM更新,功能不降级只是没有动画。检测方式:
if (document.startViewTransition) {
document.startViewTransition(updateDOM);
} else {
updateDOM();
}
View Transitions API将页面过渡从JavaScript动画库的复杂手动管理简化为声明式CSS控制,在不牺牲定制灵活性的前提下大幅降低了过渡动画的开发门槛。对SPA和MPA两种架构都有完整支持,是当前Web平台在视觉体验方面最值得投入学习的原生能力。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/cssviewtransitionsapi-ye-mian-guo-du-dong-hua-shi-xian-yu/