スクロールでふわっと表示するUIの作り方【Scroll Reveal Animation】

Scroll Reveal Animationのアイキャッチ画像

ページをスクロールしたときに、
要素が「ふわっ」と現れるUIを見たことはありませんか?

これは Scroll Reveal Animation と呼ばれ、
視線誘導や没入感を高めるのに非常に効果的です。

Scroll Revealは、要素の見せ方をコントロールするUIです。
基本的なアニメーションについては、まずはHover Animationの記事も参考になります。

この記事では、

  • IntersectionObserverを使った実装
  • CSSアニメーションとの組み合わせ
  • 軽量で実用的な設計

を、完全コピペで使える形で解説します。

1.完成イメージ

  • 下からフェードイン
  • 少し遅れて順番に表示(stagger風)
  • スクロール位置で自動発火

2.実装コード(完全コピペ)

要素を順番に表示する表現と組み合わせると、より自然なUIになります。
Stagger Animationの記事もあわせて見るのがおすすめです。

HTML

<section class="container">
  <h2>Scroll Reveal</h2>

  <div class="card reveal">Item 1</div>
  <div class="card reveal">Item 2</div>
  <div class="card reveal">Item 3</div>
  <div class="card reveal">Item 4</div>
  <div class="card reveal">Item 5</div>
</section>

CSS

body {
  margin: 0;
  font-family: sans-serif;
  background: #111;
  color: #fff;
}

.container {
  padding: 100px 20px;
  max-width: 600px;
  margin: auto;
}

.card {
  margin: 40px 0;
  padding: 40px;
  background: #222;
  border-radius: 12px;
  text-align: center;
  font-size: 20px;

  /* 初期状態 */
  opacity: 0;
  transform: translateY(40px);
  transition: all 0.6s ease;
}

/* 表示状態 */
.card.show {
  opacity: 1;
  transform: translateY(0);
}

JavaScript

const targets = document.querySelectorAll('.reveal');

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add('show');
    }
  });
}, {
  threshold: 0.2
});

targets.forEach((el) => observer.observe(el));

3.IntersectionObserverとは?

IntersectionObserverは、
「要素が画面内に入ったかどうか」を検知するAPIです。

今回のコードでは

if (entry.isIntersecting)

これが「画面に入った瞬間」を判定しています。

つまり

  • スクロール位置を自分で計算しなくていい
  • 高速・軽量に実装できる

スクロールに応じたUIは、Progress Barのような応用にもつながります。

4.thresholdの意味

threshold: 0.2

これは

👉 要素が20%見えたら発火する

という意味です。

体感の違い

  • 0 → 触れた瞬間に発火(早すぎる)
  • 0.2 → 自然(おすすめ)
  • 0.8 → かなり遅い

👉 UXに直結するポイント

5.なぜscrollイベントじゃないのか?

昔の実装

window.addEventListener('scroll', ...)

これだと

  • 毎フレーム処理が走る
  • パフォーマンスが悪い
  • 実装が複雑

6.IntersectionObserverのメリット

  • 必要なときだけ発火
  • ブラウザ最適化済み
  • コードがシンプル

👉 現代のベストプラクティス

7.CSS側の役割(意外と重要)

今回の設計

  • JS → トリガー(showを付けるだけ)
  • CSS → アニメーション
transition: all 0.6s ease;

👉 ロジックと見た目を分離している

8.よくある勘違い(追加すると良い)

「JSでアニメーションしてる」と思いがち

👉 実際はCSSが動いている

UIアニメーションは「実際に動かして理解する」のが一番です。
Ripple Animationの記事とあわせて体験してみてください。

9.実験:スクロール位置と発火タイミングを観察する

Scroll Revealは「どこで発火するか」によって体験が大きく変わります。
thresholdやoffsetを変えながら挙動を観察してみましょう。

観察ポイント

  • thresholdを0.1 → 0.5にするとどう変わる?
  • translateYの距離を増やすとどう感じる?
  • transitionを0.3sにすると軽くなる?

応用パターン

① Stagger風(少しずつ遅延)

targets.forEach((el, index) => {
  el.style.transitionDelay = `${index * 0.1}s`;
  observer.observe(el);
});

② 一度だけ表示(再発火しない)

if (entry.isIntersecting) {
  entry.target.classList.add('show');
  observer.unobserve(entry.target);
}

③ 上方向・横方向にも対応

transform: translateX(-40px);

設計ポイント

  • scrollイベントより軽い(IntersectionObserver)
  • CSSでアニメーション、JSはトリガーだけ
  • 「見せる順番」がUXに直結する

よくあるミス

  • thresholdが高すぎて発火しない
  • 初期状態のopacityを忘れる
  • transition未指定でパッと表示になる

10.まとめ

Scroll Revealは、

  • 軽量
  • 実装がシンプル
  • UIの質が一気に上がる

という、コスパ最強の演出です。

まずは今回のコードをそのまま使って、
「どのタイミングで出すと気持ちいいか」を試してみてください。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA