Documentation CSS

この記事で学べること

  • scroll-timelineプロパティの概念と目的
  • scroll-timeline-nameとscroll-timeline-axisとの関係
  • 名前付きスクロールタイムラインの作成方法
  • 実践的なスクロール駆動アニメーションの実装
  • ブラウザ対応状況と注意点

概要

scroll-timelineプロパティは、CSSのスクロール駆動アニメーション(Scroll-driven Animations)機能の一部で、スクロールコンテナにスクロールタイムラインを定義するためのショートハンドプロパティです。このプロパティを使用することで、ユーザーのスクロール位置に基づいてアニメーションを制御できます。

スクロール駆動アニメーションとは、従来の時間ベースのアニメーションとは異なり、スクロール位置をアニメーションの進行度として使用する仕組みです。ページをスクロールすると、それに連動してアニメーションが進行・後退します。

scroll-timelineは以下の2つのプロパティをまとめて指定できるショートハンドです。

  • scroll-timeline-name: タイムラインに名前を付ける
  • scroll-timeline-axis: スクロールの軸方向を指定する

scroll-timelineプロパティの基本構文

scroll-timelineプロパティは以下の構文で使用します。

/* タイムライン名のみ指定(軸はデフォルトのblock) */
scroll-timeline: --my-timeline;

/* タイムライン名と軸を指定 */
scroll-timeline: --my-timeline block;
scroll-timeline: --my-timeline inline;
scroll-timeline: --my-timeline x;
scroll-timeline: --my-timeline y;

/* 複数のタイムラインを定義 */
scroll-timeline: --timeline-a, --timeline-b inline;

各値の説明

説明
--timeline-nameタイムラインの名前(--で始まるカスタム識別子)
blockブロック方向(通常は垂直)のスクロールに連動(デフォルト)
inlineインライン方向(通常は水平)のスクロールに連動
x水平方向のスクロールに連動(物理的な軸)
y垂直方向のスクロールに連動(物理的な軸)

個別プロパティとの対応

/* ショートハンドで指定 */
.container {
  scroll-timeline: --main-scroll block;
}

/* 上記は以下と同等 */
.container {
  scroll-timeline-name: --main-scroll;
  scroll-timeline-axis: block;
}

使用例

基本的な使用例:スクロールプログレスバー

ページのスクロール量に応じて、画面上部のプログレスバーが進行する例です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>scroll-timelineの基本例</title>
<style>
/* スクロールコンテナにタイムラインを定義 */
html {
  scroll-timeline: --page-scroll block;
}

/* プログレスバーのスタイル */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  transform-origin: left;
  /* 初期状態は幅0 */
  transform: scaleX(0);
}

/* スクロールに連動するアニメーション */
@keyframes grow-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

.progress-bar {
  animation: grow-progress linear;
  /* 定義したタイムラインを使用 */
  animation-timeline: --page-scroll;
}

/* ページコンテンツ */
body {
  margin: 0;
  padding: 20px;
  min-height: 300vh; /* スクロール可能な高さ */
  background: linear-gradient(180deg, #f0f9ff, #e0f2fe);
}

h1 {
  margin-top: 60px;
}
</style>
</head>
<body>
  <div class="progress-bar"></div>
  <h1>スクロールしてください</h1>
  <p>ページをスクロールすると、上部のプログレスバーが進行します。</p>
  <p>scroll-timelineプロパティを使用して、スクロール量とアニメーションを連動させています。</p>
</body>
</html>

この例では、html要素にscroll-timeline: --page-scroll blockを指定してタイムラインを定義し、.progress-bar要素でそのタイムラインを参照しています。

水平スクロールギャラリー

水平スクロールに連動して要素がフェードインする例です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>水平スクロールギャラリー</title>
<style>
/* 水平スクロールコンテナ */
.gallery {
  /* 水平方向のスクロールタイムラインを定義 */
  scroll-timeline: --gallery-scroll inline;
  display: flex;
  gap: 20px;
  padding: 40px;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
}

/* ギャラリーアイテム */
.gallery-item {
  flex: 0 0 300px;
  height: 400px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 48px;
  font-weight: bold;
  scroll-snap-align: center;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

.gallery-item:nth-child(2n) {
  background: linear-gradient(135deg, #f093fb, #f5576c);
}

.gallery-item:nth-child(3n) {
  background: linear-gradient(135deg, #4facfe, #00f2fe);
}

/* インジケーターのアニメーション */
@keyframes indicator-progress {
  from {
    width: 0%;
  }
  to {
    width: 100%;
  }
}

.indicator {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  height: 4px;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 2px;
  overflow: hidden;
}

.indicator-fill {
  height: 100%;
  background: #667eea;
  animation: indicator-progress linear;
  animation-timeline: --gallery-scroll;
}

body {
  margin: 0;
  background: #f5f5f5;
}
</style>
</head>
<body>
<div class="gallery">
  <div class="gallery-item">1</div>
  <div class="gallery-item">2</div>
  <div class="gallery-item">3</div>
  <div class="gallery-item">4</div>
  <div class="gallery-item">5</div>
  <div class="gallery-item">6</div>
</div>
<div class="indicator">
  <div class="indicator-fill"></div>
</div>
</body>
</html>

この例では、scroll-timeline: --gallery-scroll inlineで水平スクロールのタイムラインを定義し、下部のインジケーターがスクロール位置を表示します。

複数のアニメーションを同期させる

同じタイムラインを複数の要素で共有する例です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>複数アニメーションの同期</title>
<style>
/* スクロールタイムラインを定義 */
.scroll-container {
  scroll-timeline: --content-scroll;
  height: 100vh;
  overflow-y: scroll;
}

.content {
  height: 400vh;
  padding: 20px;
  background: linear-gradient(180deg, #1a1a2e, #16213e, #0f3460, #e94560);
}

/* 回転するアニメーション */
@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* スケールするアニメーション */
@keyframes scale {
  0% { transform: scale(0.5); }
  50% { transform: scale(1.5); }
  100% { transform: scale(0.5); }
}

/* 色が変化するアニメーション */
@keyframes color-change {
  0% { background: #3b82f6; }
  33% { background: #8b5cf6; }
  66% { background: #ec4899; }
  100% { background: #3b82f6; }
}

/* 共通スタイル */
.animated-element {
  position: fixed;
  width: 80px;
  height: 80px;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

/* 各要素に異なるアニメーションを適用 */
.element-1 {
  top: 50%;
  left: 100px;
  background: #3b82f6;
  animation: rotate linear;
  animation-timeline: --content-scroll;
}

.element-2 {
  top: 50%;
  left: 200px;
  background: #8b5cf6;
  animation: scale linear;
  animation-timeline: --content-scroll;
}

.element-3 {
  top: 50%;
  left: 300px;
  animation: color-change linear;
  animation-timeline: --content-scroll;
}

body {
  margin: 0;
}
</style>
</head>
<body>
<div class="scroll-container">
  <div class="animated-element element-1">1</div>
  <div class="animated-element element-2">2</div>
  <div class="animated-element element-3">3</div>
  <div class="content">
    <h1 style="color: white;">スクロールしてください</h1>
    <p style="color: white;">3つの要素が同じタイムラインに同期してアニメーションします。</p>
  </div>
</div>
</body>
</html>

この例では、1つのタイムライン --content-scroll を3つの異なる要素で共有し、それぞれ異なるアニメーション(回転、スケール、色変化)を実行しています。

scroll()関数との使い分け

scroll-timelineプロパティとscroll()関数は、どちらもスクロールタイムラインを作成しますが、用途が異なります。

/* scroll-timelineを使用する場合(名前付きタイムライン) */
.container {
  scroll-timeline: --my-scroll;
}

.animated {
  animation: fade-in linear;
  animation-timeline: --my-scroll;
}

/* scroll()関数を使用する場合(匿名タイムライン) */
.animated-direct {
  animation: fade-in linear;
  /* 直接scroll()関数を使用 */
  animation-timeline: scroll(root block);
}

使い分けのポイント

方法用途
scroll-timeline複数の要素で同じタイムラインを共有したい場合
scroll()単一の要素で簡単にスクロールアニメーションを適用したい場合

実践的な例:パララックス効果

スクロールに応じて異なる速度で要素が移動するパララックス効果の例です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>パララックス効果</title>
<style>
html {
  scroll-timeline: --parallax block;
}

body {
  margin: 0;
  min-height: 400vh;
  background: #0f172a;
  overflow-x: hidden;
}

/* 背景レイヤー(遅い動き) */
@keyframes parallax-slow {
  from { transform: translateY(0); }
  to { transform: translateY(-100px); }
}

/* 中間レイヤー(中程度の動き) */
@keyframes parallax-medium {
  from { transform: translateY(0); }
  to { transform: translateY(-200px); }
}

/* 前景レイヤー(速い動き) */
@keyframes parallax-fast {
  from { transform: translateY(0); }
  to { transform: translateY(-400px); }
}

.layer {
  position: fixed;
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 48px;
  font-weight: bold;
  color: white;
}

.layer-back {
  background: linear-gradient(135deg, #1e3a8a, #3730a3);
  animation: parallax-slow linear;
  animation-timeline: --parallax;
  z-index: 1;
}

.layer-mid {
  background: transparent;
  animation: parallax-medium linear;
  animation-timeline: --parallax;
  z-index: 2;
}

.layer-front {
  background: transparent;
  animation: parallax-fast linear;
  animation-timeline: --parallax;
  z-index: 3;
}

.layer-back::before {
  content: "背景";
  opacity: 0.5;
}

.layer-mid::before {
  content: "中間";
  opacity: 0.7;
}

.layer-front::before {
  content: "前景";
}

.scroll-hint {
  position: fixed;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  color: white;
  font-size: 18px;
  z-index: 10;
}
</style>
</head>
<body>
<div class="layer layer-back"></div>
<div class="layer layer-mid"></div>
<div class="layer layer-front"></div>
<p class="scroll-hint">スクロールしてパララックス効果を確認</p>
</body>
</html>

この例では、3つのレイヤーがそれぞれ異なる速度で移動し、奥行き感のあるパララックス効果を実現しています。

scroll-timelineと関連プロパティ

scroll-timelineは、スクロール駆動アニメーションの一連のプロパティと組み合わせて使用します。

プロパティ説明
scroll-timelineタイムライン名と軸を定義するショートハンド
scroll-timeline-nameタイムラインの名前を定義
scroll-timeline-axisタイムラインの軸方向を指定
animation-timelineアニメーションに適用するタイムラインを指定
animation-rangeアニメーションが適用されるスクロール範囲を指定

注意点

ブラウザ対応状況

scroll-timelineプロパティは、CSS Scroll-driven Animations仕様の一部であり、比較的新しい機能です。

  • Chrome/Edge: バージョン115以降でサポート
  • Firefox: バージョン110以降でフラグ付きでサポート(layout.css.scroll-driven-animations.enabled
  • Safari: 執筆時点では未サポート

本番環境で使用する場合は、@supportsを使用してフォールバックを実装することを推奨します。

/* フォールバック処理の例 */
.progress-bar {
  /* デフォルトのスタイル(アニメーションなし) */
  transform: scaleX(0);
  transition: transform 0.3s ease;
}

/* スクロール駆動アニメーションをサポートするブラウザ向け */
@supports (animation-timeline: scroll()) {
  .progress-bar {
    animation: grow-progress linear;
    animation-timeline: --page-scroll;
  }
}

JavaScriptによるポリフィル

サポートしていないブラウザ向けに、JavaScriptでスクロール位置を監視してアニメーションを制御する方法もあります。

// ポリフィルの簡易例
if (!CSS.supports('animation-timeline', 'scroll()')) {
  const progressBar = document.querySelector('.progress-bar');

  window.addEventListener('scroll', () => {
    // スクロール進行度を計算(0から1)
    const scrollTop = window.scrollY;
    const docHeight = document.documentElement.scrollHeight - window.innerHeight;
    const progress = scrollTop / docHeight;

    // プログレスバーを更新
    progressBar.style.transform = `scaleX(${progress})`;
  });
}

パフォーマンスに関する考慮事項

  • スクロール駆動アニメーションは、GPUで処理されるtransformopacityプロパティと組み合わせることで、滑らかな動作が期待できます
  • レイアウトに影響を与えるプロパティ(widthheightmarginなど)のアニメーションは避けてください
  • 複雑なアニメーションを多用する場合は、will-changeプロパティの使用を検討してください
.animated-element {
  /* パフォーマンス最適化 */
  will-change: transform, opacity;
}

論理的な軸と物理的な軸

  • 論理的な軸(block、inline): 国際化対応が必要なサイトで推奨。書字方向に応じて自動的に適切な方向が選択されます
  • 物理的な軸(x、y): 書字方向に関係なく一貫した動作が必要な場合に使用

まとめ

scroll-timelineプロパティは、スクロール駆動アニメーションを実装するための強力なショートハンドプロパティです。従来JavaScriptで実装していたスクロール連動アニメーションを、CSSだけで簡潔に記述できます。

ポイントの振り返り

構文説明
--nameタイムライン名の定義scroll-timeline: --my-scroll
--name block垂直スクロール連動scroll-timeline: --main block
--name inline水平スクロール連動scroll-timeline: --gallery inline
--name y物理的な垂直軸scroll-timeline: --scroll-y y

スクロール駆動アニメーションを活用することで、ユーザーのスクロール操作に応じた直感的でインタラクティブな体験を提供できます。scroll-timelineを適切に設定し、魅力的なWebページを作成しましょう。

参考文献

円