CSS View Transitions API 详解:实现平滑页面过渡效果
CSS View Transitions API 详解:实现平滑页面过渡效果
引言
在现代 Web 开发中,页面间的平滑过渡效果对于提升用户体验至关重要。CSS View Transitions API 是一个强大的新特性,它允许开发者轻松实现页面元素的过渡动画,而无需复杂的 JavaScript 代码。
什么是 View Transitions
View Transitions API 提供了一种机制,让开发者能够在不同 DOM 状态之间创建平滑的过渡动画。它自动捕捉元素的"旧"状态和"新"状态,并在它们之间创建过渡效果。
基础用法
基本过渡
::view-transition { animation-duration: 0.5s; animation-timing-function: ease-in-out; } ::view-transition-old(root) { animation: fade-out 0.5s ease-in-out forwards; } ::view-transition-new(root) { animation: fade-in 0.5s ease-in-out forwards; } @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }配合 JavaScript 使用
async function navigateToPage(url) { // 开始过渡 const transition = await document.startViewTransition(() => { // 更新 DOM document.body.innerHTML = await fetchAndRenderPage(url); }); // 过渡结束回调 transition.finished.then(() => { console.log('Transition completed'); }); }自定义过渡效果
命名过渡
::view-transition-old(hero-image) { animation: slide-left 0.4s ease-out forwards; } ::view-transition-new(hero-image) { animation: slide-right 0.4s ease-out forwards; } @keyframes slide-left { from { transform: translateX(0); opacity: 1; } to { transform: translateX(-100%); opacity: 0; } } @keyframes slide-right { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }HTML 中标记过渡元素
<img src="image.jpg" style="view-transition-name: hero-image;" alt="Hero image" >高级过渡技巧
自定义过渡时长和时序
::view-transition { --view-transition-duration: 0.6s; --view-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --view-transition-delay: 0s; } ::view-transition-old(root) { animation-duration: 0.4s; } ::view-transition-new(root) { animation-duration: 0.5s; animation-delay: 0.1s; }多个元素的协调过渡
::view-transition-old(title) { animation: title-out 0.5s ease-out forwards; } ::view-transition-new(title) { animation: title-in 0.5s ease-out forwards; } ::view-transition-old(content) { animation: content-out 0.4s ease-out 0.1s forwards; } ::view-transition-new(content) { animation: content-in 0.4s ease-out 0.2s forwards; } @keyframes title-out { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-20px); opacity: 0; } } @keyframes title-in { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }利用伪元素创建叠加效果
::view-transition-group(root) { mix-blend-mode: multiply; } ::view-transition-new(root) { mix-blend-mode: screen; }实战案例:页面切换过渡
淡入淡出效果
::view-transition-old(root) { animation: fade-scale-out 0.3s ease-in-out forwards; } ::view-transition-new(root) { animation: fade-scale-in 0.3s ease-in-out forwards; } @keyframes fade-scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.95); } } @keyframes fade-scale-in { from { opacity: 0; transform: scale(1.05); } to { opacity: 1; transform: scale(1); } }滑动过渡效果
::view-transition-old(root) { animation: slide-up-out 0.4s ease-out forwards; } ::view-transition-new(root) { animation: slide-up-in 0.4s ease-out forwards; } @keyframes slide-up-out { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-100%); opacity: 0; } } @keyframes slide-up-in { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }旋转缩放过渡
::view-transition-old(root) { animation: rotate-out 0.5s ease-in-out forwards; } ::view-transition-new(root) { animation: rotate-in 0.5s ease-in-out forwards; } @keyframes rotate-out { from { transform: rotate(0deg) scale(1); opacity: 1; } to { transform: rotate(-180deg) scale(0); opacity: 0; } } @keyframes rotate-in { from { transform: rotate(180deg) scale(0); opacity: 0; } to { transform: rotate(0deg) scale(1); opacity: 1; } }图片过渡优化
平滑图片过渡
::view-transition-old(hero-image) { animation: image-out 0.5s ease-out forwards; } ::view-transition-new(hero-image) { animation: image-in 0.5s ease-out forwards; } @keyframes image-out { from { clip-path: inset(0 0 0 0); opacity: 1; } to { clip-path: inset(100% 0 0 0); opacity: 0; } } @keyframes image-in { from { clip-path: inset(0 0 100% 0); opacity: 0; } to { clip-path: inset(0 0 0 0); opacity: 1; } }进度指示过渡
::view-transition { --view-transition-progress-bar-color: #667eea; } ::view-transition-progress { height: 3px; background: linear-gradient(90deg, var(--view-transition-progress-bar-color), #764ba2); animation: progress-grow 0.5s ease-out forwards; } @keyframes progress-grow { from { width: 0%; } to { width: 100%; } }JavaScript API 详解
startViewTransition 方法
const transition = await document.startViewTransition(updateDOMFunction); transition.finished.then(() => { console.log('Transition finished'); }); transition.ready.then(() => { console.log('Transition ready'); }); transition.skipTransition();检测浏览器支持
if ('startViewTransition' in document) { // 支持 View Transitions API useViewTransitions(); } else { // 降级方案 fallbackTransition(); }动态设置过渡名称
function setTransitionName(element, name) { element.style.viewTransitionName = name; } function clearTransitionName(element) { element.style.viewTransitionName = 'none'; }性能优化建议
避免过度使用
/* 只在需要的元素上设置过渡名称 */ .hero-image { view-transition-name: hero-image; } /* 其他元素使用默认过渡 */使用 will-change 优化
.hero-image { will-change: transform, opacity; view-transition-name: hero-image; }控制过渡复杂度
/* 避免复杂的动画 */ ::view-transition-new(root) { animation: simple-fade-in 0.3s ease-out forwards; }兼容性处理
降级方案
async function navigateWithTransition(url) { if ('startViewTransition' in document) { await document.startViewTransition(() => { updatePage(url); }); } else { // 降级到简单的 CSS 过渡 document.body.classList.add('transitioning'); await updatePage(url); document.body.classList.remove('transitioning'); } }CSS 降级样式
/* 不支持 View Transitions 时的降级样式 */ .transitioning { opacity: 0; transition: opacity 0.3s ease; }总结
CSS View Transitions API 为 Web 开发者提供了一种简洁而强大的方式来实现页面过渡效果。通过结合 CSS 和 JavaScript,我们可以创建出流畅、优雅的用户体验。
关键要点:
- 使用
::view-transition-old和::view-transition-new伪元素定义过渡效果 - 通过
view-transition-name属性标记需要特殊处理的元素 - 使用
document.startViewTransition()启动过渡 - 配合 CSS 动画实现各种视觉效果
随着浏览器支持的不断完善,View Transitions API 将成为现代 Web 开发的必备技能。
