進場和退場效果是指元素進入或離開可視區域時觸發的動畫。這項功能可用於打造引人入勝的動態使用者體驗。舉例來說,您可以使用進入效果,讓元素在捲動進入檢視畫面時淡入,或使用退出效果,讓元素在捲動離開檢視畫面時縮小。
導入方式
如要為元素新增進入和退出效果,您需要結合多個 CSS 屬性。逐步指南如下:
為進場和退場動畫建立不同的
@keyframes。元素進入可視區域時會套用進場動畫,離開時則會套用退場動畫。@keyframes slide-in { from { transform: translateX(-100%); } } @keyframes slide-out { to { transform: translateX(100%); } }將進入和離開關鍵影格附加至元素。方法是在
animation屬性中定義多個動畫。- 將進場動畫的
animation-fill-mode設為backwards,這樣動畫就會在開始前套用初始狀態。 - 將結束動畫的
animation-fill-mode設為forwards,讓動畫在完成後維持最終狀態。
.animated-element { animation: slide-in 1s linear backwards, slide-out 1s linear forwards; }- 將進場動畫的
建立 View Timeline 並連結至動畫。檢視區間時間軸是一種時間軸,與可視區域中元素的顯示設定連結。您可以使用
view()函式建立一個,然後使用animation-timeline屬性將其套用至動畫。.animated-element { animation-timeline: view(); }根據預設,
view()會追蹤block軸上的元素。如需在inline軸上追蹤,可以使用view(inline)。將動畫限制在
entry和exit範圍內。animation-range屬性可讓您指定動畫應在時間軸的哪個部分執行。entry範圍涵蓋元素首次進入可視區域到完全顯示的時間。exit範圍涵蓋元素開始離開可視區域到完全隱藏的時間。
.animated-element { animation-range: entry, exit; }
範例程式碼
這段程式碼會使用匿名檢視畫面時間軸,在捲動時為捲動器的直接子項加上動畫效果:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: view(inline);
animation-range: entry, exit;
}
}
}
當元素進入捲動區時,系統會播放 grow 動畫,離開捲動區時則會播放 shrink 動畫。
下列程式碼會產生相同的視覺效果,但會使用具名檢視畫面時間軸,在捲動時為捲動器的直接子項建立動畫:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
view-timeline: --tl inline;
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: --tl;
animation-range: entry, exit;
}
}
}
最佳做法
使用捲動驅動動畫時,請務必遵循幾項最佳做法,確保體驗流暢且無障礙:
- 務必加入功能偵測:並非所有瀏覽器都支援捲動驅動動畫。使用
@supports ((animation-timeline: view()) and (animation-range: entry))檢查支援情形,並為不支援的瀏覽器提供備用方案。- 這裡必須加入
(animation-range: entry)檢查,篩除僅部分支援的瀏覽器。 - 請勿使用
scroll-timeline-polyfill套件做為備用策略,因為該套件的功能不完整,且有許多已知問題。 - 如果動畫僅用於裝飾,請選擇漸進增強,且「不要」提供備用方案。
- 這裡必須加入
- 務必尊重使用者偏好:部分使用者偏好網頁上較少動態效果。使用
prefers-reduced-motion媒體查詢,為這些使用者停用或減少動畫。 - 建議只為高效能 CSS 屬性製作動畫:如要讓動畫最流暢,請只為瀏覽器合成器執行緒可處理的屬性製作動畫,例如
transform和opacity。為width或height等其他屬性建立動畫,可能會導致效能問題。 - 建議使用正確的宣告順序:使用
animation簡寫屬性時,請在該屬性「之後」宣告animation-timeline,以免簡寫重設時間軸。
使用 view() 函式建立捲動驅動動畫時:
- 選用:明確指定要追蹤的軸:如果不是指定預設的
block軸 (例如在水平捲軸中),請明確指定要追蹤的軸,使用view(block)或view(inline)。 - 如果動畫未套用至追蹤的主體本身,請使用具名檢視區塊時間軸。
使用 view-timeline 屬性建立捲動驅動動畫時:
- 建議使用 CSS
<dashed-ident>做為名稱。 - 選用:明確指定要追蹤的軸。如果不是指定預設的
block軸 (例如在水平捲動器中),請使用view-timeline-axis明確指定要追蹤的軸。 - 務必確保查詢範圍有效:如果宣告
view-timeline的元素不是動畫元素的平面樹狀結構祖系,請在共用祖系上使用timeline-scope,提高view-timeline名稱的瀏覽權限。
如果追蹤主體的多個元素或子項需要動畫,建議使用具名 view-timeline。
瀏覽器支援和備用策略
因此,通常需要備用策略。
如果瀏覽器不支援捲動驅動動畫,可以使用備用方案重新建立視覺效果。備用方案通常是使用捲動事件監聽器 (用於 ScrollTimeline 效果) 或 IntersectionObserver API (用於 ViewTimeline 效果) 建構。
如果瀏覽器內建支援捲動式動畫,請一律使用原生 CSS 實作,因為這類實作的效能較佳。
請注意,並非所有效果都能使用備用方法重新建立。
針對這個用途,下列指令碼會為不支援捲動驅動動畫的瀏覽器套用備用方案。這個函式會使用 IntersectionObserver 追蹤 .wrapper 元素的可見度,並根據捲動位置更新圖層的 transform 屬性。
<script>
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
// This matches the effect as defined in the CSS example above.
// Customize this further if needed.
entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
}
},
{
threshold: Array.from({ length: 101 }, (_, i) => i / 100),
}
);
document.querySelectorAll('.scroller > *').forEach((el) => {
observer.observe(el);
});
}
</script>