スクロールアニメーションの実装方法|JavaScriptとCSSでふわっと表示

スクロールアニメーションとは、ページをスクロールして要素が画面内に入ったタイミングで、フェードインなどの動きをつけて表示させる演出です。実装の考え方はシンプルで、「要素が画面に入ったらJavaScriptでクラスを付与し、そのクラスに対してCSSでアニメーションを指定する」だけです。本記事では、現在の主流であるIntersection Observerを使った書き方を中心に、従来のスクロール量判定やjQueryのinview.jsによる方法、フェードインのコード例、実装時の注意点までを解説します。

スクロールアニメーションの基本の仕組み

person using MacBook Pro
Photo by Glenn Carstens-Peters on Unsplash

どの実装方法を選んでも、流れは共通して次の3ステップです。この型さえ理解すれば、フェードイン以外の動きにも応用できます。

  1. HTMLで、動かしたい要素に目印のクラス(例:js-fadein)を付ける
  2. JavaScriptで、その要素が画面内に入ったかを判定し、is-showなどのクラスを付与する
  3. CSSで、クラスが付いたときの見た目(透明度や位置)を指定してアニメーションさせる

Intersection Observerを使う方法(推奨)

現在おすすめなのは、標準機能のIntersection Observerを使う方法です。スクロールのたびに計算する必要がなく、ブラウザ側が効率よく監視してくれるため、動作が軽いのが利点です。jQueryなどの外部ライブラリも不要です。

<div class="js-fadein fadeIn">ふわっと表示される要素</div>
const targets = document.querySelectorAll(".js-fadein");const observer = new IntersectionObserver(function (entries) {  for (const entry of entries) { if (entry.isIntersecting) {entry.target.classList.add("is-show");observer.unobserve(entry.target); // 1回だけ実行する場合 }  }}, {  threshold: 0.2 // 要素が20%見えたら発火});for (const target of targets) {  observer.observe(target);}

thresholdは「要素が何割見えたら発火するか」の設定です。0.2なら20%見えた時点で動き出します。unobserveを書くと一度きりの実行になり、消さなければスクロールのたびに繰り返し発火させることもできます。

CSSでフェードインを指定する

JavaScript側は「クラスを付ける」だけなので、実際の見た目はCSSで作ります。下からふわっと浮き上がる、定番のフェードインは次のように書きます。

.fadeIn {  opacity: 0;  transform: translateY(30px);  transition: opacity 0.8s, transform 0.8s;}.fadeIn.is-show {  opacity: 1;  transform: translateY(0);}

translateYの値を変えれば動く距離を、translateXにすれば左右からのスライドインを作れます。複数の要素を順番に表示したいときは、transition-delayanimation-delayで時間差をつけると自然な印象になります。

スクロール量で判定する方法(従来型)

lines of HTML codes
Photo by Florian Olivo on Unsplash

Intersection Observerを使わず、スクロール量と要素の位置を比較して判定する方法もあります。仕組みが分かりやすいため、動作を理解したい場合に向いています。

const targets = document.querySelectorAll(".js-fadein");window.addEventListener("scroll", function () {  const scroll = window.scrollY;  const windowHeight = window.innerHeight;  for (const target of targets) { const targetPos = target.getBoundingClientRect().top + scroll; if (scroll > targetPos - windowHeight + 100) {target.classList.add("is-show"); }  }});

ただしこの方法は、スクロールのたびに全要素の位置計算が走るため、要素数が多いとパフォーマンスに影響します。実務ではIntersection Observerを選ぶほうが安全です。

jQueryを使う方法(inview.js)

既存サイトで既にjQueryを使っている場合は、プラグインのinview.jsを使うと短い記述で実装できます。要素が表示領域に入るとinviewイベントが発火する仕組みです。

$(function () {  $(".inview").on("inview", function (event, isInView) { if (isInView) {$(this).stop().addClass("is-show"); }  });});

利用にはjQuery本体とinview.jsの読み込みが必要で、対象の要素にはinviewクラスを付けておきます。なお、これから新規で作るサイトであれば、外部ライブラリが不要なIntersection Observerを推奨します。

実装時の注意点

  • ファーストビューには使わない:最初から見えている要素に付けると、表示されないまま残るおそれがある
  • 動かしすぎない:すべての要素を動かすと読みづらく、かえって印象が悪くなる
  • 速度は0.5〜1秒程度に:長すぎるアニメーションはスクロールの妨げになる
  • JSが無効な場合に備えるopacity: 0のままだと内容が読めなくなるため、動作しない環境への配慮が必要
  • アクセシビリティ:動きが苦手なユーザー向けにprefers-reduced-motionでアニメーションを抑制する
  • スマホで確認する:画面が小さいと発火タイミングがずれやすいため、実機でチェックする

よくある質問(FAQ)

Q. jQueryは必要ですか?
A. 不要です。Intersection Observerは標準機能のため、素のJavaScriptだけで実装できます。既存サイトでjQueryを使っている場合のみ、inview.jsが選択肢になります。

Q. アニメーションを1回だけ実行したいです。
A. クラスを付与したあとにobserver.unobserve(entry.target)を実行すると、その要素の監視が終了し、再度発火しなくなります。

Q. 発火のタイミングを調整したいです。
A. Intersection Observerのthreshold(何割見えたら発火するか)やrootMargin(判定範囲の余白)で調整できます。

Q. 複数の要素を順番に表示させるには?
A. CSSのtransition-delayanimation-delayで要素ごとに時間差をつけると、順番に現れる演出になります。

最新情報をチェックしよう!