CSSScroll-Driven Animations動畫前端開發2026

告別 JS 動畫庫:CSS Scroll-Driven Animations 實戰

CSS Scroll-Driven Animations 完整教學!scroll() 與 view()、animation-range 控制、GSAP 比較攻略。2026 年工程師必看的 CSS 動畫指南!

· 5 分鐘閱讀

過去要實現「滾動觸發動畫」(scroll-triggered animations),你需要 JavaScript 動畫庫——GSAP、Framer Motion、Locomotive Scroll。這些庫很強大,但它們帶來的相依性和效能開銷,在某些場景下是不必要的。CSS Scroll-Driven Animations 是瀏覽器原生支援的功能,讓你用純 CSS 實現同樣的效果,而且效能更好。2026 年 Safari 18+ 正式支援後,覆蓋率超過 80%,是時候認真對待這項技術了。


前端工程師為什麼要關心 CSS 滾動動畫

多數前端工程師已經習慣用 JavaScript 處理滾動動畫。當你在一個專案裡加入 GSAP 的 ScrollTrigger 時,你獲得了一個完整的動畫解決方案,但同時也帶來了:

  • bundle 體積增加:GSAP 約 60KB(壓縮後)
  • 學習曲線:ScrollTrigger 的 API 文件雖然完整,但有門檻
  • 效能考慮:JavaScript 驅動的動畫在主執行緒上運行

CSS Scroll-Driven Animations 的價值主張:如果你的需求在 CSS 能做到的範圍內,你就不需要 JS 庫


瀏覽器支援

瀏覽器支援版本支援度
Chrome115+✅ 全面支援
Edge115+✅ 全面支援
Safari18+✅ 全面支援
Firefox開發中

覆蓋率約 80%+(以全球瀏覽器市場計)。如果你的用戶多數是 Safari 使用者,現在已經可以使用。如果需要支援 Firefox,可以考慮 GSAP fallback。


兩個核心語法:scroll() 和 view()

scroll():滾動容器內的動畫

scroll() 讓元素的動畫與特定滾動容器的進度掛鈎:

/* 當 #container 滾動時,.progress-bar 的寬度隨之變化 */
.progress-bar {
  width: 100%;
  animation: grow linear;
  animation-timeline: scroll(#container);  /* 綁定到 #container 的滾動 */
  animation-range: 0% 100%;  /* 從頭到尾全範圍 */
}

@keyframes grow {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
<div id="container">
  <div class="progress-bar"></div>
</div>

view():元素進入視口的動畫

view() 監聽元素本身進入/離開視口(viewport)的狀態:

/* 當元素進入視口時,淡入 */
.fade-in-element {
  animation: fade-in linear both;
  animation-timeline: view();  /* 監聽元素自身 */
  animation-range: entry 0% cover 50%;  /* 從進場 0% 到覆蓋 50% */
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

animation-range:精確控制動畫時機

animation-range 是 Scroll-Driven Animations 最關鍵的功能,讓你控制動畫在哪個區間播放:

進場與退場

/* 進場(entry):元素從下方進入視口 */
.fade-in {
  animation: fade linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;  /* 元素完全進入視口 */
}

/* 退場(exit):元素離開視口 */
.fade-out {
  animation: fade linear both;
  animation-timeline: view();
  animation-range: exit 0% exit 100%;  /* 元素完全離開視口 */
}

/* 進場 + 退場 */
.both {
  animation-range:
    entry 0% entry 50%,   /* 進來時 */
    exit 50% exit 100%;    /* 出去時 */
}

cover 的應用

cover N% 讓你根據元素覆蓋視口的程度來控制動畫:

/* 元素覆蓋視口 0% 到 100% 時,執行動畫 */
.zoom-effect {
  animation: zoom linear both;
  animation-timeline: view();
  animation-range: cover 0% cover 100%;
}

@keyframes zoom {
  from { transform: scale(0.8); }
  to { transform: scale(1.2); }
}

實際應用場景

1. 進度條指示器

/* 頁面頂部的閱讀進度條 */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 4px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  width: 100%;
  transform-origin: left;
  animation: grow linear both;
  animation-timeline: scroll(root block);  /* 整個頁面的滾動 */
  animation-range: 0% 100%;
}

@keyframes grow {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

2. Scrollytelling:元素逐個進場

/* 每個 .step 在進入視口時淡入並上移 */
.step {
  min-height: 80vh;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  animation: step-enter linear both;
  animation-timeline: view();
  animation-range: entry 10% entry 60%;  /* 10%-60% 視口覆蓋時 */
}

@keyframes step-enter {
  from {
    opacity: 0;
    transform: translateY(60px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

3. 視差效果(Parallax)

/* 背景圖片比前景元素移動得慢,產生深度感 */
.parallax-bg {
  position: absolute;
  inset: -20%;
  background-image: url('mountains.jpg');
  background-size: cover;
  animation: parallax linear both;
  animation-timeline: scroll(root);  /* 頁面整體滾動 */
  animation-range: cover cover;  /* 覆蓋整個視口 */
}

@keyframes parallax {
  from { transform: translateY(0); }
  to { transform: translateY(20%); }  /* 20% 的視差偏移 */
}

4. 數字滾動效果

/* 數字隨著元素進入視口而「計數」 */
.stat-number {
  font-size: 4rem;
  font-weight: bold;
  animation: count-up linear both;
  animation-timeline: view();
  animation-range: entry 0% cover 30%;
}

@keyframes count-up {
  from { --count: 0; }
  to { --count: 10000; }
}

與 GSAP 的實用比較

維度CSS Scroll-DrivenGSAP ScrollTrigger
bundle 體積0KB~60KB
主執行緒外(瀏覽器paint)主執行緒(JavaScript)
瀏覽器支援~80%100%
自訂彈性有限極高
複雜時間軸
學習成本

CSS 勝出的場景

  • 簡單的進場/退場動畫
  • 閱讀進度條
  • 視差背景(不複雜的)
  • 需要效能優先的長頁面

GSAP 仍然必要的場景

  • 複雜的時間軸編排(多個動畫順序播放)
  • 需要在特定時間點暫停/控制
  • 滾動速度不是線性的(如加速/減速)
  • 需要豐富的插件生態(如 DrawSVGPlugin)

Fallback 策略

Progressive Enhancement

/* 如果瀏覽器不支援,就用一般的 animation */
@supports (animation-timeline: scroll()) {
  .progress-bar {
    animation: grow linear both;
    animation-timeline: scroll(root block);
    animation-range: 0% 100%;
  }
}

檢測支援

// JavaScript 檢測支援
const supportsScrollTimeline = CSS.supports('animation-timeline', 'scroll()');

if (!supportsScrollTimeline) {
  // 使用 GSAP 或 Locomotive Scroll 作為 fallback
  gsap.registerPlugin(ScrollTrigger);
}

總結:現在是開始使用的時機

CSS Scroll-Driven Animations 在 2026 年已經覆蓋了 80%+ 的瀏覽器。對於 Safari 用戶為主的產品,這已經不是「可以考慮」的技術,而是「可以開始用」的技術。

對於需要支援 Firefox 的產品,可以考慮 Progressive Enhancement 的策略:在支援的瀏覽器上用 CSS,不支援的用 JS fallback。

過去用 GSAP 處理的很多場景,現在 CSS 都能做到。當然,GSAP 不會消失——它的 API 豐富度、生態系、和跨瀏覽器一致性,仍然是 CSS Scroll-Driven Animations 短期內無法完全取代的。但對於簡單的滾動觸發動畫,現在沒有理由不用原生 CSS。


延伸閱讀

本文是「2026 CSS 實用技術」系列文章之一。