为开发者提供的关于使用 CSS 视图过渡 API 为 SPA 和 MPA 创建无缝、类似应用程序的页面导航的全面指南。学习核心概念和高级技术。
CSS 视图过渡 API:实现流畅页面导航的终极指南
几十年来,Web 导航一直被一个令人不快的现实所定义:空白的白色屏幕。点击一个链接意味着完整的页面重新加载,短暂的虚无闪烁,然后是新内容的突然出现。虽然功能齐全,但这种体验缺乏用户期望从原生应用程序中获得的流畅性和润色。单页应用程序 (SPA) 出现作为一种解决方案,使用复杂的 JavaScript 框架来创建无缝过渡,但通常以架构简单性和初始加载性能为代价。
如果我们能拥有两全其美呢?多页应用程序 (MPA) 的简单服务器渲染架构与 SPA 的优雅、有意义的过渡相结合。这就是 CSS 视图过渡 API 的承诺,这是一项突破性的浏览器功能,有望彻底改变我们思考和构建 Web 用户体验的方式。
本综合指南将带您深入了解视图过渡 API。我们将探讨它是什么,为什么它是 Web 开发的一个重要转变,以及您今天如何实现它——无论是对于 SPA,还是更令人兴奋的传统 MPA。准备好告别白色闪烁,迎接无缝 Web 导航的新时代。
什么是 CSS 视图过渡 API?
CSS 视图过渡 API 是一种直接构建到 Web 平台中的机制,允许开发人员在不同的 DOM(文档对象模型)状态之间创建动画过渡。在其核心,它提供了一种简单的方法来管理从一个视图到另一个视图的视觉变化,无论该变化发生在同一页面(在 SPA 中)还是在两个不同的文档之间(在 MPA 中)。
这个过程非常巧妙。当触发过渡时,浏览器:
- 拍摄当前页面状态(旧视图)的“屏幕截图”。
- 允许您将 DOM 更新到新状态。
- 拍摄新页面状态(新视图)的“屏幕截图”。
- 将旧视图的屏幕截图放在新的实时视图之上。
- 在两者之间进行动画过渡,默认情况下通常使用平滑的交叉淡入淡出。
整个过程由浏览器协调,使其具有很高的性能。更重要的是,它使开发人员可以使用标准 CSS 完全控制动画,从而将曾经复杂的 JavaScript 任务转变为声明性和可访问的样式挑战。
为什么这是 Web 开发的颠覆者
此 API 的引入不仅仅是另一个增量更新;它代表了对 Web 平台的根本改进。以下是它对全球开发人员和用户如此重要的原因:
- 显着增强的用户体验 (UX):流畅的过渡不仅仅是装饰性的。它们提供视觉连续性,帮助用户理解不同视图之间的关系。一个元素从缩略图无缝增长到全尺寸图像,提供上下文并引导用户的注意力,使界面感觉更直观和响应更快。
- 大大简化的开发:在此 API 之前,实现类似效果需要繁重的 JavaScript 库(如 Framer Motion 或 GSAP)或复杂的 CSS-in-JS 解决方案。视图过渡 API 用一个简单的函数调用和几行 CSS 取代了这种复杂性,降低了创建美观的应用程序式体验的入门门槛。
- 卓越的性能:通过将动画逻辑卸载到浏览器的渲染引擎,视图过渡可以比 JavaScript 驱动的对应物更具性能和电池效率。浏览器可以以难以手动复制的方式优化该过程。
- 弥合 SPA-MPA 鸿沟:也许最令人兴奋的方面是它对跨文档过渡的支持。这允许传统的服务器渲染网站 (MPA) 采用长期以来被认为是 SPA 独有的流畅导航。企业现在可以使用现代 UX 模式增强其现有网站,而无需进行昂贵且复杂的架构迁移到完整的 SPA 框架。
核心概念:理解视图过渡背后的魔力
要掌握 API,您首先需要了解它的两个主要组成部分:JavaScript 触发器和启用自定义的 CSS 伪元素树。
JavaScript 入口点:`document.startViewTransition()`
一切都始于一个 JavaScript 函数:`document.startViewTransition()`。此函数接受一个回调作为参数。在此回调中,您可以执行从旧状态到新状态所需的所有 DOM 操作。
一个典型的调用如下所示:
// 首先,检查浏览器是否支持该 API
if (!document.startViewTransition) {
// 如果不支持,则直接更新 DOM
updateTheDOM();
} else {
// 如果支持,则将 DOM 更新包装在过渡函数中
document.startViewTransition(() => {
updateTheDOM();
});
}
当您调用 `startViewTransition` 时,浏览器会启动前面描述的捕获-更新-动画序列。该函数返回一个 `ViewTransition` 对象,该对象包含允许您挂接到过渡生命周期的不同阶段以进行更高级控制的 Promise。
CSS 伪元素树
自定义的真正力量在于浏览器在过渡期间创建的一组特殊的 CSS 伪元素。这个临时树允许您独立地设置旧视图和新视图的样式。
::view-transition:树的根,覆盖整个视口。您可以使用它来设置过渡的背景颜色或持续时间。::view-transition-group(name):表示单个过渡元素。它负责动画期间元素的位置和大小。::view-transition-image-pair(name):旧元素和新元素的容器。它被设置为隔离的 `mix-blend-mode` 样式。::view-transition-old(name):元素在其旧状态下的屏幕截图(例如,缩略图)。::view-transition-new(name):元素在其新状态下的实时表示(例如,全尺寸图像)。
默认情况下,此树中唯一的元素是 `root`,它代表整个页面。要对状态之间的特定元素进行动画处理,您必须为它们提供一致的 `view-transition-name`。
实际实现:您的第一个视图过渡(SPA 示例)
让我们构建一个常见的 UI 模式:一个卡片列表,当点击时,过渡到同一页面上的详细视图。关键是拥有一个共享元素,例如图像,可以在两种状态之间平滑变形。
步骤 1:HTML 结构
我们需要一个用于列表的容器和一个用于详细视图的容器。我们将在父元素上切换一个类来显示一个并隐藏另一个。
<div id="app-container">
<div class="list-view">
<!-- 卡片 1 -->
<div class="card" data-id="item-1">
<img src="thumbnail-1.jpg" alt="Item 1">
<h3>产品一</h3>
</div>
<!-- 更多卡片... -->
</div>
<div class="detail-view" hidden>
<img src="large-1.jpg" alt="Item 1">
<h1>产品一</h1>
<p>此处为详细描述...</p>
<button id="back-button">返回</button>
</div>
</div>
步骤 2:分配一个 `view-transition-name`
为了让浏览器理解缩略图图像和详细视图图像是*相同的概念元素*,我们必须在 CSS 中为它们提供相同的 `view-transition-name`。此名称对于页面上任何给定时间内的每个过渡元素必须是唯一的。
.card.active img {
view-transition-name: product-image;
}
.detail-view.active img {
view-transition-name: product-image;
}
我们使用一个 `.active` 类,我们将用 JavaScript 添加它,以确保只有可见元素被分配名称,从而避免冲突。
步骤 3:JavaScript 逻辑
现在,我们将编写处理 DOM 更新的函数,并将其包装在 `document.startViewTransition()` 中。
function showDetailView(itemId) {
const updateDOM = () => {
// 将 'active' 类添加到正确的卡片和详细视图
// 这也会通过 CSS 分配 view-transition-name
document.querySelector(`.card[data-id='${itemId}']`).classList.add('active');
document.querySelector('.detail-view').classList.add('active');
// 隐藏列表并显示详细视图
document.querySelector('.list-view').hidden = true;
document.querySelector('.detail-view').hidden = false;
};
if (!document.startViewTransition) {
updateDOM();
return;
}
document.startViewTransition(() => updateDOM());
}
仅凭这一点,点击卡片将触发图像的平滑变形动画和页面其余部分的交叉淡入淡出。不需要复杂的动画时间线或库。
下一个前沿:MPA 的跨文档视图过渡
这就是 API 真正具有变革性的地方。以前,如果不将这些流畅的过渡应用于传统的多页应用程序 (MPA),是不可能的。现在,这是一个简单的选择加入。
启用跨文档过渡
要为不同页面之间的导航启用过渡,请将一个简单的 CSS @ 规则添加到源页面和目标页面的 CSS 中:
@view-transition {
navigation: auto;
}
就是这样。一旦存在此规则,浏览器将自动为所有同源导航使用视图过渡(默认的交叉淡入淡出)。
关键:一致的 `view-transition-name`
就像在 SPA 示例中一样,跨两个单独的页面连接元素的魔力依赖于共享的、唯一的 `view-transition-name`。让我们想象一个产品列表页面 (`/products`) 和一个产品详细信息页面 (`/products/item-1`)。
在 `products.html` 上:
<a href="/products/item-1">
<img src="thumbnail-1.jpg" style="view-transition-name: product-image-1;">
</a>
在 `product-detail.html` 上:
<div class="hero">
<img src="large-1.jpg" style="view-transition-name: product-image-1;">
</div>
当用户单击第一个页面上的链接时,浏览器会看到一个带有 `view-transition-name: product-image-1` 的元素离开页面。然后,它等待新页面加载。当第二个页面呈现时,它会找到一个具有相同 `view-transition-name` 的元素,并自动在两者之间创建一个平滑的变形动画。页面内容的其余部分默认为微妙的交叉淡入淡出。这创造了一种速度和连续性的感知,这对于 MPA 来说以前是不可想象的。
高级技术和自定义
默认的交叉淡入淡出很优雅,但 API 通过 CSS 动画提供了深入的自定义挂钩。
使用 CSS 自定义动画
您可以通过使用标准 CSS `@keyframes` 和 `animation` 属性定位伪元素来覆盖默认动画。
例如,要为新页面内容创建“从右侧滑入”效果:
@keyframes slide-from-right {
from { transform: translateX(100%); }
}
::view-transition-new(root) {
animation: slide-from-right 0.5s ease-out;
}
您可以将不同的动画应用于 `::view-transition-old` 和 `::view-transition-new` 以用于不同的元素,从而创建高度编排和复杂的过渡。
使用类控制过渡类型
一个常见的需求是为前进和后退导航提供不同的动画。例如,前进导航可能会从右侧滑入新页面,而后退导航可能会从左侧滑入新页面。这可以通过在触发过渡之前将一个类添加到文档元素 (`<html>`) 来实现。
“后退”按钮的 JavaScript:
backButton.addEventListener('click', (event) => {
event.preventDefault();
document.documentElement.classList.add('is-going-back');
document.startViewTransition(() => {
// 返回导航的逻辑
Promise.resolve().then(() => {
document.documentElement.classList.remove('is-going-back');
});
});
});
用于定义不同动画的 CSS:
/* 默认前进动画 */
::view-transition-new(root) {
animation: slide-from-right 0.5s;
}
/* 后退动画 */
.is-going-back::view-transition-new(root) {
animation: slide-from-left 0.5s;
}
这种强大的模式提供了对用户导航体验的精细控制。
可访问性考虑因素
如果没有强大的内置可访问性,现代 Web API 将是不完整的,而视图过渡 API 提供了这一点。
- 尊重用户偏好:API 会自动尊重 `prefers-reduced-motion` 媒体查询。如果用户已指示他们更喜欢操作系统设置中的较少运动,则跳过过渡,并且 DOM 更新会立即发生。默认情况下会发生这种情况,而无需开发人员进行额外的工作。
- 保持焦点:过渡纯粹是视觉上的。它们不会干扰标准焦点管理。开发人员仍然有责任确保在过渡之后,键盘焦点移动到新视图中的逻辑元素,例如主要标题或第一个交互元素。
- 语义 HTML:API 是一个增强层。您的底层 HTML 应保持语义化和可访问性。使用屏幕阅读器或不支持的浏览器的用户将在没有过渡的情况下体验内容,因此结构本身必须有意义。
浏览器支持和渐进增强
截至 2023 年末,基于 Chromium 的浏览器(Chrome、Edge、Opera)支持用于 SPA 的视图过渡 API。用于 MPA 的跨文档过渡在功能标志后面可用,并且正在积极开发中。
该 API 从头开始设计用于 渐进增强 。我们之前使用的守卫模式是关键:
if (!document.startViewTransition) { ... }
此简单检查可确保您的代码仅尝试在支持它的浏览器中创建过渡。在旧浏览器中,DOM 更新会立即发生,就像一直以来一样。这意味着您可以立即开始使用 API 来增强现代浏览器上的用户体验,而对旧浏览器上的用户没有负面影响。这是一个双赢的局面。
Web 导航的未来
视图过渡 API 不仅仅是一个用于引人注目的动画的工具。这是一个根本性的转变,使开发人员能够制作更直观、更具凝聚力和吸引力的用户旅程。通过标准化页面过渡,Web 平台正在缩小与本机应用程序的差距,从而为所有类型的网站启用新的质量和润色水平。
随着浏览器支持的扩展,我们可以预期在 Web 设计中看到新的创意浪潮,其中页面之间的旅程变得与页面本身一样经过深思熟虑的设计。SPA 和 MPA 之间的界限将继续模糊,从而使团队能够选择最适合其项目的架构,而不会牺牲用户体验。
结论:立即开始构建更流畅的体验
CSS 视图过渡 API 提供了一个罕见的强大功能和卓越简单性的结合。它提供了一种高性能、可访问且渐进增强的方式,可以将您网站的用户体验从功能性提升到令人愉悦的程度。
无论您是构建复杂的 SPA 还是传统的服务器渲染网站,现在都可以使用这些工具来消除令人不快的页面加载,并通过流畅、有意义的动画引导您的用户浏览您的界面。理解其力量的最好方法是尝试一下。采用您应用程序的一小部分——画廊、设置页面或产品流程——并进行实验。您会惊讶于几行代码如何从根本上改变您网站的感觉。
白色闪烁的时代即将结束。Web 导航的未来是无缝的,有了视图过渡 API,您就可以拥有今天开始构建它所需的一切。