スクロールアニメーション

IntersectionObserver scrollY scroll-driven animations

スクロールに連動したアニメーションを実装します。ページ上部の赤いバーがスクロールプログレスの例です。

🔗 このページはIntersectionObserver APIを使ったスクロールアニメーションの実装です。React / Framer Motion を使った実装はスクロール連動ページを参照してください。

デモ①:スクロールプログレスバー

ページ上部に赤いプログレスバーが表示されています。

現在のスクロール進行率: 0%

デモ②:スクロールで要素をフェードイン(IntersectionObserver)

最初のカード(IntersectionObserverで表示検知)
2番目のカード(IntersectionObserverで表示検知)
3番目のカード(IntersectionObserverで表示検知)
4番目のカード(IntersectionObserverで表示検知)

コード例:IntersectionObserver

js
// IntersectionObserver でスクロール入場を検知
const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add('visible');
        observer.unobserve(entry.target); // 一度だけ
      }
    });
  },
  {
    threshold: 0.3,    // 30%見えたら発火
    rootMargin: '0px 0px -50px 0px', // 下50pxのオフセット
  }
);

// 全ての .fade-in 要素を監視
document.querySelectorAll('.fade-in').forEach(el => {
  observer.observe(el);
});

/* CSS */
.fade-in {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.fade-in.visible {
  opacity: 1;
  transform: translateY(0);
}

// スクロールプログレスバー
window.addEventListener('scroll', () => {
  const scrolled = window.scrollY;
  const total = document.documentElement.scrollHeight - window.innerHeight;
  const progress = (scrolled / total) * 100;
  progressBar.style.width = `${progress}%`;
}, { passive: true });

比較:IntersectionObserver vs scroll イベント

観点IntersectionObserver(推奨)scroll イベント
パフォーマンス✅ メインスレッド外で動作❌ 毎フレーム実行・重い
getBoundingClientRect不要(自動)毎回呼び出し必要
用途要素の表示検知、遅延読み込みプログレスバー、視差効果
ブラウザ対応✅ 全モダンブラウザ✅ 全ブラウザ

NEWCSS Scroll-Driven Animations(Chrome 115+)

JavaScriptなしでスクロール連動アニメーションをCSSだけで実現できる新機能です。パフォーマンスも最良です。

js
/* スクロールプログレスバーをCSSだけで実装 */
@keyframes progress {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.progress-bar {
  transform-origin: left;
  animation: progress linear;
  /* スクロールタイムラインに紐付け */
  animation-timeline: scroll(root);
}

/* 要素がビューポートに入るときのアニメーション */
@keyframes fade-in {
  from { opacity: 0; translate: 0 30px; }
  to   { opacity: 1; translate: 0 0; }
}

.card {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 50%;
}

/* ブラウザ対応: Chrome 115+, Edge 115+(Firefox・Safariは未対応) */

🤖 AIプロンプトテンプレート

以下のようなIntersectionObserverを使ったスクロールアニメーションのサンプルコードを生成してください:
- IntersectionObserverでスクロール入場を検知してfadeInアニメーションを実行
- threshold / rootMarginオプションで発火タイミングを調整する方法
- scrollYとdocumentHeightを使ったスクロールプログレスバーの実装
- unobserve()を使って一度だけアニメーションを実行するパターン
- CSS Scroll-Driven Animations(animation-timeline: scroll())の実装例

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。