スクロール連動アニメーションを軽く実装するための 4 つのコツ

パララックスやフェードインを、重くならず、誰にとっても読みやすい形で実装するための考え方をまとめました。

Hiraoku1 分で読めます

緑色の丘と木が重なる紙の風景を、巻物で動かす黒ペン風イラスト

スクロールに合わせて要素がふわっと現れる演出は、うまく使えばページに奥行きを与えてくれます。一方で、やりすぎるとカクついたり、読みにくくなったりします。実装するときに意識しているコツを 4 つ紹介します。

1. scroll イベントで重い処理をしない

scroll イベントは非常に高い頻度で発火します。表示判定には IntersectionObserver を使い、スクロール量に応じた値が必要なときだけ requestAnimationFrame でまとめて計算します。

let ticking = false;
window.addEventListener(
  'scroll',
  () => {
    if (ticking) return;
    ticking = true;
    requestAnimationFrame(() => {
      ticking = false;
      update();
    });
  },
  { passive: true },
);

表示判定にはIntersectionObserver、スクロール量の計算にはrequestAnimationFrameを使い、読める状態を保つ設計

上の2つは用途に応じて選ぶ処理です。すべてのアニメーションが両方を通るわけではありません。

2. 動かすのは transform と opacity だけ

top や width を動かすとレイアウトの再計算が走ります。transform と opacity だけを使えば、ブラウザは合成レイヤーで処理できるので滑らかです。

3. JavaScript が無くても読めるようにする

初期状態で要素を opacity: 0 にしてしまうと、スクリプトが読み込まれなかったときに何も見えなくなります。<html> に .motion クラスが付いたときだけ隠すようにしておくと安心です。

.motion [data-reveal] {
  opacity: 0;
  transform: translateY(32px);
}

.motion [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

4. prefers-reduced-motion を尊重する

動きで気分が悪くなる人もいます。OS の設定を尊重して、アニメーションを止められるようにしましょう。

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

ほかの記事も読む