【CSS+JS】背景画像の視差効果(パララックス)を実装する方法

はじめに

JavaScriptプラグインを使わずに、背景画像の視差効果(パララックス)をVanilla JS(ピュアなJavaScript)だけで実装する方法について説明します。

サンプル

まず、背景画像の視差効果(パララックス)とはどういうものなのか確認するために、下記のサンプルをご覧ください。

画面をスクロールすると背景画像を設定したコンテナーが現れますが、スクロールに合わせて少しずつ動いているのがわかるかと思います。完全にスクロールと連動しているわけでもなく、また、完全に固定されているわけでもありません。

このように、スクロールに合わせて少しだけ背景画像を動かすことを「背景画像の視差効果(パララックス)」と言います。現実世界では、遠くにある物ほど実際よりもゆっくり動くように見えるため、その視覚効果を擬似的に再現したのが視差効果(パララックス)です。

実装

では、実際に実装していきましょう。

HTML

HTMLは背景画像を設定するコンテナーのみです。

<div class="container"></div>

CSS

コンテナーに背景画像を設定します。

.container {
  background-image: url(../path/to/background-image.jpg);
  background-size: cover;
  background-position: center top;
  background-attachment: fixed;
}

background-attachment: fixed;を設定して背景画像を固定させます。

背景画像の横位置に決まりはありませんが、縦位置はtopにする必要があります。後述のJavaScriptで、topからのオフセット値を設定することにより背景画像を動かしています。もし、topからではなくcenterからのオフセット値を設定したい場合、centerからのオフセット値は設定できないため、代わりにcalcキーワードを使う方法があります。

.container {
  background-position: center calc(50% - 10px);
}

この方法を使う場合、後述のJavaScriptの処理もcalcキーワードを使うようにしてください。

JavaScript

JavaScriptは少し長いですが、順番に解説していきます。

class ParallaxEffectBackground {
  constructor() {
    this.devided = 5;
    this.target = '.container';
    this.setBackgroundPosition();
  }

  getScrollTop() {
    return Math.max(
      window.pageYOffset,
      document.documentElement.scrollTop,
      document.body.scrollTop,
      window.scrollY
    );
  }

  setBackgroundPosition() {
    document.addEventListener('scroll', e => {
      const scrollTop = this.getScrollTop();
      const position = scrollTop / this.devided;
      if (position) {
        document.querySelectorAll(this.target).forEach(element => {
          element.style.backgroundPosition = 'center top -' + position + 'px';
        });
      }
    });
  }
}

document.addEventListener('DOMContentLoaded', event => {
  new ParallaxEffectBackground();
});

まずはコンストラクターからです。

  constructor() {
    this.devided = 5;
    this.target = '.container';
    this.setBackgroundPosition();
  }

コンストラクターでは、以下の処理を行っています。

  • 背景画像の縦位置のオフセット値(スクロール位置に対する係数として使用)
  • 背景画像の視差効果(パララックス)を適用するターゲット(セレクター)
  • 背景画像の縦位置を設定する処理の呼び出し

1つ目に関してですが、背景画像のオフセット値はスクロール位置から係数を除算して算出しているため、係数の値を大きくすればするほど背景画像が遅く動くようになります。例えば、スクロール位置が500の場合、係数が5だとオフセット値は500/5=100になり、係数が10だとオフセット値は500/10=50になります。

getScrollTopメソッドでは、現在のスクロール位置を取得しています。

  getScrollTop() {
    return Math.max(
      window.pageYOffset,
      document.documentElement.scrollTop,
      document.body.scrollTop,
      window.scrollY
    );
  }

setBackgroundPositionメソッドでは、現在のスクロール位置から背景画像の縦位置のオフセット値を取得し、ターゲットの縦位置を設定しています。

  setBackgroundPosition() {
    document.addEventListener('scroll', e => {
      const scrollTop = this.getScrollTop();
      const offset = scrollTop / this.devided;
      if (offset) {
        document.querySelectorAll(this.target).forEach(element => {
          element.style.backgroundPosition = 'center top -' + offset + 'px';
        });
      }
    });
  }

topからではなくcenterからのオフセット値を設定したい場合、calcキーワードを使います。

          element.style.backgroundPosition = 'center calc(50% - ' + offset + 'px)';

まとめ

視差効果(パララックス)は、文字や画像を実際のスクロールよりも早く動かして、それらの要素がより近くにあることを表現する方法などもあります。いろいろな視差効果(パララックス)を試したいという場合は、便利なJavaScriptプラグインが用意されているので導入してみることをおすすめします。

背景画像の視差効果(パララックス)だけならVanilla JS(ピュアなJavaScript)だけでも簡単に実装できるので、本記事を参考にしていただければと思います。

関連記事

【CSS+JS】メニューアイコンの一種、ベントーメニューの実装方法(アニメーション付き)
# はじめに メニューアイコンの中ではハンバーガーメニューが有名だと思いますが、その他にもいろいろな種類があって、それぞれに名前もつけられています。 <a class="gallery" data-group="gallery" href= [...]
2021年10月18日 14:26
【CSS+JS】メインコンテンツの裏から現れるフッターの実装方法
# はじめに オシャレなサイトなどでたまに見かける「メインコンテンツの裏から現れるフッター」の実装方法について説明します。 # サンプル <iframe height="392" style="width: 100%;" scrollin [...]
2021年10月18日 13:26
【CSS+JS】ウィンドウ内全体にファイルをドラッグ&ドロップしてアップロード
# はじめに ユーザーが選択したファイルをアップロードする必要がある場合、ファイル選択フィールドを設置することはもちろんですが、ファイルをドラッグ&ドロップしてアップロードできるようにもなっていると使い勝手のいいサービスだと言えます。しかし、ドラ [...]
2021年6月2日 15:15
【CSS+JS】モーダルウィンドウを表示しその中にYouTube動画を動的に埋め込む
# はじめに 動画のサムネイル画像をクリックしてモーダルウィンドウを表示し、その中にYouTube動画を動的に埋め込む方法について説明します。なお、本記事ではYouTube動画を動的に埋め込むまでを範囲とし、埋め込んだ動画の再生制御などは範囲外と [...]
2021年5月20日 23:23
【CSS+JS】テキストを1文字ずつ表示するアニメーションの実装方法
# はじめに モダンなサイトでよく見かける「テキストを1文字ずつ表示するアニメーション」の実装方法を解説します。 # 実装 ## サンプル 繰り返し動作を確認したい場合は右下の「Rerun」ボタンをクリックしてください。 <i [...]
2021年5月20日 13:26
【CSS】CSSだけでMarkdownのコードにファイル名をつける
# はじめに Markdownのコードに、そのコードがどのファイルのものなのかを示すためにファイル名が書いてあるとわかりやすいです。以下はQiitaの記事でコードを書いたときの一例です。 <img data-src="https://i.i [...]
2021年4月6日 14:39
【CSS】カーソルを乗せると流れるようなアニメーションのハンバーガーメニューを作る
# はじめに 今回はハンバーガーメニューにカーソルを乗せると川のように流れるアニメーションを作りたいと思います。 今回の記事は以下の記事をベースにしていますので、まだご覧になっていない方は先にこちらをご覧ください。 <div clas [...]
2020年8月31日 8:54
【CSS】JavaScriptを使わずにハンバーガーメニューを作る
# はじめに 当初はスペースの限られるスマートフォンなどの低解像度デバイス向けサイトにおいてスペースを有効活用するために登場したハンバーガーメニューですが、最近はPCなどの高解像度デバイス向けサイトでも使われているのをよく見かけます。 何よ [...]
2020年8月31日 7:34