view-transition-name

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

view-transition-name CSS 屬性指定所選元素將參與的檢視過渡快照。這使你可以將這些元素與頁面的其餘部分分開進行動畫處理,而頁面的其餘部分在檢視過渡期間使用預設的交叉淡入淡出動畫。然後,你可以為這些元素定義自定義動畫樣式。

語法

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> 不能是 automatch-elementnoneCSS 全域性關鍵字值。

match-element

瀏覽器會自動為所選元素分配一個唯一的名稱。此名稱用於將該元素與頁面上所有其他元素分開進行快照。(此名稱是內部的,無法從 DOM 讀取。)

none

所選元素不會參與單獨的快照,除非其父元素設定了 view-transition-name,在這種情況下,它將作為該元素的一部分進行快照。

描述

預設情況下,當檢視過渡應用於 Web 應用時,在該過渡期間發生的所有 UI 更改都會被快照並一起進行動畫處理。這是預設的——或稱root)——快照(參見檢視過渡偽元素樹)。預設情況下,此動畫是平滑的交叉淡入淡出,可以在檢視過渡 SPA 演示中看到實際效果。

如果你希望某些元素在檢視過渡期間與快照的動畫方式不同,你可以透過為它們指定一個不同的 view-transition-name 來實現,例如

css
figcaption {
  view-transition-name: figure-caption;
}

然後,你可以使用相關的檢視過渡偽元素——::view-transition-old()::view-transition-new()——來為舊快照和新快照指定你想要的動畫。例如

css
::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

css
.dont-animate-me {
  view-transition-name: none;
}

對於參與檢視過渡的每個渲染元素,view-transition-name<custom-ident> 必須是唯一的。如果兩個渲染元素在同一時間具有相同的 view-transition-nameViewTransition.ready Promise 將會拒絕,並且過渡將被跳過。

自動指定 view-transition-name

有時,你希望在檢視過渡中為多個 UI 元素分別設定動畫。當頁面上有一個元素列表並且希望以某種方式重新排列它們時,通常就是這種情況

html
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>

  <!-- ... -->

  <li>Item 99</li>
</ul>

為每個元素指定一個唯一的名稱可能很不方便,尤其是在元素數量增多時

css
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

css
li {
  view-transition-name: match-element;
}

由於 match-element 會根據元素標識自動分配 view-transition-name 值,因此它只能用於同文檔檢視過渡。自動生成的內部識別符號無法在不同元素或文件之間傳遞。

正式定義

初始值none
應用於所有元素
繼承性
計算值同指定值
動畫型別離散

正式語法

view-transition-name = 
none |
<custom-ident>

示例

view-transition-name 的基本用法

此示例來自檢視過渡 SPA 演示,這是一個基本的圖片庫。基本 SPA 檢視過渡更詳細地解釋了此演示的工作原理。

大部分 UI 更改都使用過渡快照進行動畫處理。然而,<figcaption> 被賦予了 figure-captionview-transition-name,以使其可以與頁面的其餘部分以不同的方式進行動畫處理

css
figcaption {
  view-transition-name: figure-caption;
}

以下程式碼僅對 <figcaption> 應用自定義動畫

css
@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> 元素。

html
<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> 則填充剩餘的可用水平空間。

css
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 將此類應用於列表項,這將啟動一個檢視過渡。

css
.active-item {
  position: absolute;
  z-index: 1;
  translate: 37cqw;
  width: calc(100% - 37cqw);
  height: 100%;
}

預設情況下,檢視過渡中的所有元素都會在一個交叉淡入淡出中一起進行動畫處理。然而,在此示例中,我們不希望這樣——我們希望每個列表項都有自己的移動動畫。我們可以透過對每個列表項應用 view-transition-name: match-element 來實現這一點

css
.match-element-applied li {
  view-transition-name: match-element;
}

match-element-applied 類預設應用於 <main> 元素,這就是為什麼“結果”框架中的複選框最初是選中的。如果取消選中它,該類將被移除,預設的交叉淡入淡出動畫將生效。你可以切換複選框來比較預設動畫和使用 view-transition-name: match-element 時應用的動畫。

接下來,我們透過使用 ::view-transition-group() 偽元素為所有檢視過渡組(由 * 識別符號表示)應用 animation-duration,併為所有舊快照和新快照設定 height100%,來自定義動畫。這可以解決舊快照和新快照寬高比差異的問題,並使動畫看起來更平滑

css
::view-transition-group(*) {
  animation-duration: 0.5s;
}

html::view-transition-old(*),
html::view-transition-new(*) {
  height: 100%;
}

JavaScript

在此示例中,當列表項的連結被點選時,active-item 類會應用於這些列表項;這是透過 updateActiveItem() 函式實現的

js
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

瀏覽器相容性

另見