CSS和佈局動畫無障礙性

捲動動畫:用 animation-timeline 取代 IntersectionObserver

捲動動畫:用 animation-timeline 取代 IntersectionObserver

Scroll-driven animations 從根本上解決問題。這是你已知的 CSS 動畫,只有一個替換:不是時間驅動進度,而是捲動容器的位置。瀏覽器可以在合成器上執行它。

四行進度條

css

.progress {
position: fixed;
inset: 0 0 auto 0;
height: 4px;
transform-origin: left;
animation: grow linear both;
animation-timeline: scroll(root block);
}
@keyframes grow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}

捲動時顯示:view() 時間軸

css

.reveal {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(32px); }
to { opacity: 1; transform: translateY(0); }
}

四個命名範圍:entry、exit、cover(預設)、contain。

耗費一小時的陷阱:animation 簡寫重置時間軸

css

/* 損壞:簡寫將 animation-timeline 重置為 auto */
.reveal {
animation-timeline: view();
animation-range: entry 0% entry 60%;
animation: fade-up linear both;
}

css

/* 正確:時間軸和範圍在簡寫之後 */
.reveal {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}

命名時間軸

css

.gallery {
overflow-x: auto;
scroll-timeline: --gallery inline;
}
.gallery-indicator {
animation: fill linear both;
animation-timeline: --gallery;
timeline-scope: --gallery;
}

漸進增強在這裡不是可選的

css

.reveal {
opacity: 1;
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.reveal {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
}
}

陷阱與最佳實踐

  • 只動畫化 transform 和 opacity。
  • 永遠不要隱藏只有動畫才能揭示的內容。
  • 「為什麼我的動畫靜止?」幾乎總是捲動容器的問題。
  • 使用 both 作為填充模式。
  • 減少動態效果是醫療設定,不是禮貌。
  • 不要刪除你仍然需要的 JavaScript。

總結

Scroll-driven animations 將關於主執行緒的相同想法應用於整個效果類別:需要捲動監聽器、觀察器和類別切換的東西變成了單一 CSS 屬性。