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

どの実装方法を選んでも、流れは共通して次の3ステップです。この型さえ理解すれば、フェードイン以外の動きにも応用できます。
- HTMLで、動かしたい要素に目印のクラス(例:
js-fadein)を付ける - JavaScriptで、その要素が画面内に入ったかを判定し、
is-showなどのクラスを付与する - 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-delayやanimation-delayで時間差をつけると自然な印象になります。
スクロール量で判定する方法(従来型)

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-delayやanimation-delayで要素ごとに時間差をつけると、順番に現れる演出になります。

