動態效果是所有數位體驗中不可或缺的一環,可引導使用者從一次互動到下個互動。但網路平台上的流暢動畫有些許差異。這類元件包括輕鬆為進入和離開動畫建立動畫效果,並針對可關閉的元素 (例如對話方塊和彈出式視窗),流暢地來回動畫。
為彌補不足之處,Chrome 116 和 117 版加入了四項全新的網路平台功能,可讓個別屬性產生流暢的動畫和轉換效果。
這四項新功能包括:
- 支援在主要畫面格時間軸上建立
display
和content-visibility
動畫 (從 Chrome 116 開始)。 transition-behavior
屬性搭配allow-discrete
關鍵字,可啟用display
等不連續屬性的轉換 (從 Chrome 117 開始)。@starting-style
規則可針對display: none
和頂層 (從 Chrome 117 版本) 新增進入效果。overlay
屬性可在動畫播放期間控制頂層圖層行為 (自 Chrome 117 起)。
在主要畫面格中顯示動畫
在 Chrome 116 中,您可以在主要畫面格規則中使用 display
和 content-visibility
。如此一來,主要畫面格就會在主要畫面格發生時互換。不需要其他新值即可支援這類功能:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
上述範例將 0.5 秒內不透明度的動畫效果設為 0,然後將顯示設為無。此外,forwards
關鍵字會確保動畫維持結束狀態,因此套用該動畫的元素仍維持 display: none
和 opacity: 0
。
這個簡單的範例模擬了您可以對轉換執行的操作 (請參閱轉換部分中的示範)。但轉場效果無法建立更複雜的動畫,例如下列範例:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
spin-and-delete
動畫是退出動畫。首先,資訊卡會在 Y 軸上旋轉,繞過色調旋轉,然後在 80%
到時間軸時,將不透明度從 1 轉換為 0。最後,資訊卡會從 display: block
切換為 display: none
。
你可以為動畫設定觸發條件,而不必直接將動畫套用至元素。舉例來說,將事件監聽器附加至按鈕,藉此觸發類別套用動畫,如下所示:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
上述範例的結尾狀態是 display:none
。在許多情況下,您可能會想要繼續進行,然後移除設有逾時的 DOM 節點,讓動畫先播完。
轉換離散動畫
與使用主要畫面格建立離散屬性動畫的情況不同,您必須使用 allow-discrete
轉換行為模式,才能轉換不同的屬性。
transition-behavior
屬性
allow-discrete
模式是可進行離散轉換,值為 transition-behavior
屬性的值。transition-behavior
可接受兩個值:normal
和 allow-discrete
。
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
transition
簡寫也可以設定這個值,因此您可以省略屬性,在每次轉換時,在 transition
簡寫結尾使用 allow-discrete
關鍵字。
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
如果您要為多個獨立屬性建立動畫效果,您必須在要建立動畫的每個屬性後加入 allow-discrete
。例如:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
項目動畫的 @starting-style
規則
目前這篇文章已介紹離開動畫,您必須使用 @starting-style
規則建立進入動畫。
請使用 @starting-style
套用樣式,讓瀏覽器在開啟該元素前可先查詢樣式。這就是「開啟前」狀態 (表示動畫出入位置)。
/* 0. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 1. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
現在,您同時擁有這些 TODO 清單項目的進入與結束狀態:
為頂層和頂層元素建立動畫
如要為頂層圖層和頂層元素建立動畫,請在「開啟」狀態指定 @starting-style
,讓瀏覽器知道應該從何處加入動畫。如果是對話方塊,系統會使用 [open]
屬性定義開啟狀態。如果是彈出式視窗,請使用 :popover-open
虛擬類別。
簡易的對話方塊範例如下:
/* 0. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 1. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
在下一個範例中,進入和離開效果不同。透過動畫從可視區域底部向上移動,讓效果回到可視區域頂端。並使用巢狀 CSS 編寫,以增加視覺封裝。
為彈出效果加上動畫效果時,請使用 :popover-open
虛擬類別,而不是先前使用的 open
屬性。
.settings-popover {
&:popover-open {
/* 0. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
overlay
資源
最後,如要從頂層淡出 popover
或 dialog
,請將 overlay
屬性新增至轉場效果清單。popover
和 dialog
會逸出祖系片段和轉換,並將內容置於頂層。如未轉換 overlay
,您的元素會立即回到裁剪、轉換及覆蓋範圍,因此您將無法看到轉場效果。
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
請改為在轉場效果或動畫中加入 overlay
,為 overlay
與其他地圖項目加上動畫效果,並確保動畫呈現在頂層圖層中。這樣看起來會更順暢。
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
此外,當頂層圖層開啟多個元素時,疊加元素可協助您控制頂層和外層的流暢轉場效果。你可以前往這個簡單的範例瞭解差異。轉出時,如果不將 overlay
套用至第二個彈出式視窗,它會先從頂層跳出,從另一個彈出式視窗後跳轉,再開始轉場效果。這並非平滑的效果。
檢視畫面轉場注意事項
如果您要進行 DOM 變更 (例如在 DOM 中新增及移除元素),另一個可以流暢播放動畫的方法是檢視畫面轉場。上方有兩個透過檢視區塊轉場效果建構的範例。
在第一個示範中,您不必設定 @starting-style
和其他 CSS 轉換,而是會處理檢視畫面轉場效果。檢視畫面轉換的設定如下:
首先,請在 CSS 中為每張資訊卡提供個別的 view-transition-name
。
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
接著,在 JavaScript 中,在檢視畫面轉場中納入 DOM 變異 (在本例中為移除資訊卡)。
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
現在,瀏覽器可以處理每張卡片的淡出和變形。
另一個非常實用的例子,就是新增/移除清單項目示範。在這種情況下,請務必為建立的每張卡片新增專屬的 view-transition-name
。
結論
透過這些新的平台功能,我們更接近在網路平台上流暢進入及結束動畫。如要瞭解詳情,請點選下列連結: