view-transition-name
view-transition-name
CSS 属性指定所选元素将参与的视图过渡快照。这使你可以将这些元素与页面的其余部分分开进行动画处理,而页面的其余部分在视图过渡期间使用默认的交叉淡入淡出动画。然后,你可以为这些元素定义自定义动画样式。
语法
/* <custom-ident> value examples */
view-transition-name: header;
view-transition-name: figure-caption;
/* Keyword value */
view-transition-name: none;
view-transition-name: match-element;
/* Global values */
view-transition-name: inherit;
view-transition-name: initial;
view-transition-name: revert;
view-transition-name: revert-layer;
view-transition-name: unset;
值
<custom-ident>
-
一个标识名称,使所选元素参与与根快照分离的快照。
<custom-ident>
不能是auto
、match-element
、none
或CSS 全局关键字值。 match-element
-
浏览器会自动为所选元素分配一个唯一的名称。此名称用于将该元素与页面上所有其他元素分开进行快照。(此名称是内部的,无法从 DOM 读取。)
none
-
所选元素不会参与单独的快照,除非其父元素设置了
view-transition-name
,在这种情况下,它将作为该元素的一部分进行快照。
描述
默认情况下,当视图过渡应用于 Web 应用时,在该过渡期间发生的所有 UI 更改都会被快照并一起进行动画处理。这是默认的——或称根
(root
)——快照(参见视图过渡伪元素树)。默认情况下,此动画是平滑的交叉淡入淡出,可以在视图过渡 SPA 演示中看到实际效果。
如果你希望某些元素在视图过渡期间与根
快照的动画方式不同,你可以通过为它们指定一个不同的 view-transition-name
来实现,例如
figcaption {
view-transition-name: figure-caption;
}
然后,你可以使用相关的视图过渡伪元素——::view-transition-old()
和 ::view-transition-new()
——来为旧快照和新快照指定你想要的动画。例如
::view-transition-old(figure-caption) {
animation: 0.25s linear both shrink-x;
}
::view-transition-new(figure-caption) {
animation: 0.25s 0.25s linear both grow-x;
}
如果你不希望某个元素被单独快照,可以指定 view-transition-name
的值为 none
.dont-animate-me {
view-transition-name: none;
}
对于参与视图过渡的每个渲染元素,view-transition-name
的 <custom-ident>
必须是唯一的。如果两个渲染元素在同一时间具有相同的 view-transition-name
,ViewTransition.ready
Promise
将会拒绝,并且过渡将被跳过。
自动指定 view-transition-name
值
有时,你希望在视图过渡中为多个 UI 元素分别设置动画。当页面上有一个元素列表并且希望以某种方式重新排列它们时,通常就是这种情况
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<!-- ... -->
<li>Item 99</li>
</ul>
为每个元素指定一个唯一的名称可能很不方便,尤其是在元素数量增多时
li:nth-child(1) {
view-transition-name: item1;
}
li:nth-child(2) {
view-transition-name: item2;
}
li:nth-child(3) {
view-transition-name: item3;
}
li:nth-child(4) {
view-transition-name: item4;
}
/* ... */
li:nth-child(99) {
view-transition-name: item99;
}
为了解决这个问题,你可以使用 match-element
值,这会使浏览器为每个选定的元素指定一个唯一的内部 view-transition-name
li {
view-transition-name: match-element;
}
由于 match-element
会根据元素标识自动分配 view-transition-name
值,因此它只能用于同文档视图过渡。自动生成的内部标识符无法在不同元素或文档之间传递。
正式定义
正式语法
view-transition-name =
none |
<custom-ident>
示例
view-transition-name
的基本用法
此示例来自视图过渡 SPA 演示,这是一个基本的图片库。基本 SPA 视图过渡更详细地解释了此演示的工作原理。
大部分 UI 更改都使用根
过渡快照进行动画处理。然而,<figcaption>
被赋予了 figure-caption
的 view-transition-name
,以使其可以与页面的其余部分以不同的方式进行动画处理
figcaption {
view-transition-name: figure-caption;
}
以下代码仅对 <figcaption>
应用自定义动画
@keyframes grow-x {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
@keyframes shrink-x {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
::view-transition-group(figure-caption) {
height: auto;
right: 0;
left: auto;
transform-origin: right center;
}
::view-transition-old(figure-caption) {
animation: 0.25s linear both shrink-x;
}
::view-transition-new(figure-caption) {
animation: 0.25s 0.25s linear both grow-x;
}
我们创建了一个自定义 CSS 动画,并将其应用于 ::view-transition-old(figure-caption)
和 ::view-transition-new(figure-caption)
伪元素。我们还应用了其他样式以将它们保持在同一位置,并防止默认样式干扰我们的自定义动画。
使用 match-element
值
此示例包含一个技术列表——HTML、CSS、SVG 和 JS——它们显示在主内容区域旁边的侧边栏中,而主内容区域最初是空的。点击某个技术的标题会将其内容动画化到显示更多详细信息的相邻内容区域中。
HTML
<main>
元素包含一个无序列表和一个 <article>
元素。列表中的多个子 <li>
元素各自包含一个位于标题内的 <a>
元素。
<main class="match-element-applied">
<ul>
<li>
<h2><a href="#">HTML</a></h2>
<h3>HyperText Markup Language</h3>
<p>
HyperText Markup Language (HTML) is the most basic building block of the
web. It defines the meaning and structure of web content. HTML provides
the fundamental building blocks for structuring web documents and apps.
</p>
</li>
<li>
<h2><a href="#">CSS</a></h2>
<h3>Cascading Style Sheets</h3>
<p>
Cascading Style Sheets (CSS) is a stylesheet language used to describe
the presentation of a document written in HTML or XML (including XML
dialects such as SVG, MathML or XHTML). CSS describes how elements
should be rendered on screen, on paper, in speech, or on other media.
</p>
</li>
<li>
<h2><a href="#">SVG</a></h2>
<h3>Scalable Vector Graphics</h3>
<p>
Scalable Vector Graphics (SVG) is an XML-based markup language for
describing two-dimensional based vector graphics.
</p>
</li>
<li>
<h2><a href="#">JS</a></h2>
<h3>JavaScript</h3>
<p>
JavaScript (JS) is the web's native programming language. JavaScript is
a lightweight, interpreted (or just-in-time compiled) programming
language with first-class functions. While it is most well-known as the
scripting language for web pages, many non-browser environments, such as
Node.js, also use it.
</p>
</li>
</ul>
<article></article>
</main>
CSS
我们使用 Flexbox 来将 <li>
和 <article>
并排布局,并使列表项在第一列中共享相等的空间。列表占据容器宽度的 35%,而 <article>
则填充剩余的可用水平空间。
main {
container-type: inline-size;
width: 100%;
height: 100%;
display: flex;
gap: 2cqw;
position: relative;
}
ul {
width: 35cqw;
display: flex;
flex-direction: column;
gap: 1cqw;
}
article {
flex: 1;
}
li {
flex: 1;
}
我们还定义了一个规则,用于选择具有 active-item
类的元素。当此类别应用于某个元素时,该规则会使其精确定位在 <article>
元素的正上方。当列表项的链接被点击时,将通过 JavaScript 将此类应用于列表项,这将启动一个视图过渡。
.active-item {
position: absolute;
z-index: 1;
translate: 37cqw;
width: calc(100% - 37cqw);
height: 100%;
}
默认情况下,视图过渡中的所有元素都会在一个交叉淡入淡出中一起进行动画处理。然而,在此示例中,我们不希望这样——我们希望每个列表项都有自己的移动动画。我们可以通过对每个列表项应用 view-transition-name: match-element
来实现这一点
.match-element-applied li {
view-transition-name: match-element;
}
match-element-applied
类默认应用于 <main>
元素,这就是为什么“结果”框架中的复选框最初是选中的。如果取消选中它,该类将被移除,默认的交叉淡入淡出动画将生效。你可以切换复选框来比较默认动画和使用 view-transition-name: match-element
时应用的动画。
接下来,我们通过使用 ::view-transition-group()
伪元素为所有视图过渡组(由 *
标识符表示)应用 animation-duration
,并为所有旧快照和新快照设置 height
为 100%
,来自定义动画。这可以解决旧快照和新快照宽高比差异的问题,并使动画看起来更平滑
::view-transition-group(*) {
animation-duration: 0.5s;
}
html::view-transition-old(*),
html::view-transition-new(*) {
height: 100%;
}
JavaScript
在此示例中,当列表项的链接被点击时,active-item
类会应用于这些列表项;这是通过 updateActiveItem()
函数实现的
const mainElem = document.querySelector("main");
let prevElem;
let checkboxElem = document.querySelector("input");
// View transition code
function updateActiveItem(event) {
// Get the list item that contains the clicked link
const clickedElem = event.target.parentElement.parentElement;
// Set the active-item class on the list item
clickedElem.className = "active-item";
// Keep track of the previous item that was clicked, if any.
// Remove the active-item class from the previous item so that only
// one list item is placed over the <article> at any one time
if (prevElem === clickedElem) {
prevElem.className = "";
prevElem = undefined;
} else if (prevElem) {
prevElem.className = "";
prevElem = clickedElem;
} else {
prevElem = clickedElem;
}
}
mainElem.addEventListener("click", (event) => {
event.preventDefault(); // Prevent iframe from scrolling when clicked
// Do nothing unless a link is clicked inside the <main> element
if (event.target.tagName !== "A") {
return;
}
// Run updateActiveItem() on its own if view transitions are not supported
if (!document.startViewTransition) {
updateActiveItem(event);
} else {
// Run updateActiveItem() via startViewTransition()
const transition = document.startViewTransition(() =>
updateActiveItem(event),
);
}
});
// Toggle the class on <main> to control whether or not match-element is applied
checkboxElem.addEventListener("change", () => {
mainElem.classList.toggle("match-element-applied");
});
通过 startViewTransition()
函数运行 updateActiveItem()
函数可以平滑地动画化技术详情的显示。
结果
点击侧边栏中的一个技术标题,注意其内容进入主内容区域的动画效果。
还有一个复选框,默认是选中的,因此应用了 view-transition-name: match-element
。取消选中该复选框,然后再次点击一个标题,看看在没有 view-transition-name: match-element
的情况下视图过渡是如何工作的。
规范
规范 |
---|
CSS 视图过渡模块第 1 级 # view-transition-name-prop |
浏览器兼容性
加载中…