CSS 视图过渡的入门级指南

阅读时间 5 分钟

想象一下,您的网站可以在页面之间流畅地进行动画,将您从index.html导航到about.html,而无需令人不适的页面重新加载。现在,这已经成为可能,这得益于现代浏览器对视图转换 API的支持。

视图转换曾经是单页应用程序(SPA)独有的功能。在这篇文章中,我们将探讨视图转换如何为多页应用程序(MPA)带来流畅、动画化的导航。

MPA 与 SPA 快速回顾

多页应用程序(MPA)和单页应用程序(SPA)是两种常见的 Web 开发方法,它们各有优缺点。

  • MPA 在每次导航时都会从服务器加载一个新页面,导致整个页面重新加载。对于包含许多不同页面的大型应用程序,MPA 更易于构建。
  • 另一方面,SPA 加载单个 HTML 页面,并通过 JavaScript 动态更新其内容,提供更快的交互和更流畅的用户体验,但通常需要更复杂的客户端路由和状态管理。

长期以来,流畅的动画过渡只能在 SPA 中实现。现在,借助视图转换 API——以及 CSS 的 @view-transition at-rule——MPA 也可以实现类似的效果。CSS 视图转换的设计理念是渐进增强。因此,如果浏览器不支持它们,网站仍然可以正常工作,因为 CSS 被视为一个提示,并且只在支持时应用。

浏览器对视图转换的支持

在深入探讨此功能的具体用法之前,值得注意的是视图转换目前的支持情况。CSS 视图转换规范有两个级别:

  • Level 1 使用 视图转换 API 在单个页面内实现转换。这在 Chrome、Edge 和 Safari 中已经得到支持。Firefox 版本 144(目前处于 Beta 版)也支持该功能。
  • Level 2 允许通过 @view-transition at-rule 实现跨多页面的转换。它目前在 Chrome 126+、Edge 126+ 和 Safari 18.2+ 中得到支持。在撰写本文时,Level 2 在 Firefox 中仍处于开发过程中,但预计将来会获得支持。

在不支持视图转换的浏览器中,网站将继续正常运行,使用标准的页面导航,因为这些转换被视为渐进增强,不会破坏您的网站。

Baseline banner showing multi-page view transition limited availability in browsers: Chrome, Edge (yes), Firefox (no), Safari (yes).

创建您的第一个视图转换

让我们深入了解一下,看看视图转换的实际应用。

作为最简单的例子,您只需在代码中添加几行 CSS 即可启用转换。

css
@view-transition {
  navigation: auto;
}

就是这样!基本版本只需要几行 CSS,如果问我的话,这简直太棒了。

为了看到这行代码的效果,让我们构建两个演示页面。您也可以尝试将此代码添加到任何现有的多页应用程序中。

第一个页面index.html,只包含一个标题、一些段落和一个指向第二个页面的链接。

html
<h1>🏡 Homepage</h1>
<p>Hello, my name is Mrs. Whiskers. Welcome to my personal website!</p>
<p>
  Everyone needs a place on the web, even a cat. If you're curious, you can find
  out more about my <a href="hobbies.html">hobbies</a>.
</p>

准备好我们的第二个页面hobbies.html。这也是一个简单的页面,包含一个标题、两个简短的段落以及一个返回第一个页面的链接。

html
<h1>🧶 My hobbies</h1>
<p>
  When I'm not busy napping, I love to play with yarn and chase laser pointers.
  I'm also an avid bird watcher.
</p>
<p>
  Thank you for your interest! You can return to the
  <a href="index.html">homepage</a> now.
</p>

最后,将以下样式添加到您的style.css文件中。

css
@view-transition {
  navigation: auto;
}

这就是创建视图转换所需的全部内容。仅凭这一行 CSS,您就会看到两个页面之间无缝的过渡。过去,这种流畅的过渡只能通过 JavaScript 在 SPA 中实现。借助 CSS @view-transition at-rule,浏览器现在可以原生处理多页应用程序之间的转换,而无需 JavaScript。

超越默认转换

现在让我们更进一步,自定义视图转换。在这里,我们将创建一个滑动进入和滑动出去的效果,这是一个简单的动画,用于理解视图转换的内部工作原理。

让我们为我们的两个 HTML 页面添加两个不同的样式表。将此添加到index.html

html
<link rel="stylesheet" href="index.css" />

……将此添加到hobbies.html

html
<link rel="stylesheet" href="hobbies.css" />

是时候熟悉一些控制视图转换的 CSS 选择器(伪元素)了。

css
::view-transition-old(root),
::view-transition-new(root) {
  /* Write some cool CSS here */
}

让我们了解一下这些伪元素是如何工作的:::view-transition-old::view-transition-new 伪元素分别引用旧页面和新页面,使我们能够为它们之间的过渡设置样式。当我们从index.html导航到hobbies.html时,旧页面是我们正在离开的页面(index.html),新页面是我们即将前往的页面(hobbies.html)。

让我们添加一个滑动动画,让hobbies.html以平滑的滑动效果进入。我们将此动画称为 slide-from-right。将以下代码添加到hobbies.css

css
@keyframes slide-from-right {
  from {
    /* Arrive from the right */
    transform: translateX(100vw);
  }
  to {
    /* Come into view */
    transform: translateX(0);
  }
}

::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
}

::view-transition-old(root) {
  animation: none;
}

::view-transition-new(root) {
  /* Apply animation to hobbies.html */
  animation: slide-from-right 0.3s;
}

请注意,mix-blend-mode 被设置为 normal,以避免默认的交叉淡入淡出效果。默认情况下,视图转换使用 plus-lighter 混合模式在旧页面和新页面之间创建交叉淡入淡出效果,但对于滑动动画,我们不需要这种交叉淡入淡出,因此我们用 normal 来覆盖它。

滑动进入效果如下所示。

现在,让我们通过添加另一个滑动动画来完成此效果,以确保hobbies.html页面以其进入的方式滑出。在这种情况下,我们将从hobbies.html导航到index.html;因此,hobbies.html现在是我们的旧页面,index.html是新页面。

我们将此动画称为 slide-to-right。将此代码添加到index.css

css
@keyframes slide-to-right {
  from {
    /* Start from screen view */
    transform: translateX(0);
  }

  to {
    /* Move to right */
    transform: translateX(100vw);
  }
}

::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
}

::view-transition-old(root) {
  /* Apply @keyframes to hobbies.html */
  animation: slide-to-right 0.3s;
  z-index: 2;
}

::view-transition-new(root) {
  animation: none;
}

请注意,我在两个方向上都只为hobbies.html添加了动画,而没有为index.html添加任何动画。如果您愿意,也可以为两者都添加动画。

最终的过渡效果如下,包括hobbies.html的滑动进入和滑动出去效果。

在您的浏览器中查看演示页面以查看效果。如果您想扩展此演示,请随时使用 mdn/dom-examples 存储库中的代码,并为index.html页面添加动画(在index.css文件中查找 animation: none)。

我很乐意看到您构思出的所有酷炫的视图转换。

总结

您可以在 MDN 的 Mastodon 上观看我关于此主题的演讲视频

祝您视图转换愉快!愿您的多页应用程序在页面之间流畅切换。