Blog

ブログ

Intersection Observerを使って要素と背景画像を連動させる方法

最終更新日:|公開日:

Intersection Observerを使って要素と背景画像を連動させる方法

こんにちは。

リースエンタープライズでSEOを担当している美土路です。

さて、みなさんは「Intersection Observer」というものをご存知でしょうか?

私自身、昨年までこの「Intersection Observer」の存在を全く知らず、以前務めていたフロントエンジニアの方に教えていただきました。

情報としてはちょっと古いものになってしまうのですが、もし知らない方がいらっしゃれば一度使ってみてください。

今まではJavaScriptのscrollイベントを駆使して色々と実装してきたものに変わる、革命的なAPIになっています。

「Intersection Observer」とは

Intersection Observerとは要素と要素の交差を検知してくれるAPIです。

「特定の位置までスクロールしたら~」など、scrollイベントと変わりないように見えますが、scrollイベント毎に処理が発生し、監視する要素が増える度に処理が重くなってしまうことがありました。
(スクロールすると詰まってしまったりなど…)

しかしIntersection Observerを使用することによって、ターゲット要素がどの程度見えているのかによって処理するコールバックを構成することが可能となっています。

ですので、スクロールするたびに呼ばれることもなくなり、サイトの表示速度も改善されることになります。

またIntersection Observerはgoogleも推奨しているということなので、SEOの表示速度や画像の遅延表示にも一役買ってくれそうですね。

「Intersection Observer」と背景画像を連動させてみる

まずはこちらのサンプルをご確認ください。

「Intersection Observer」と背景画像を連動

こちらは左の見出しの部分がブラウザの50%に当たる部分までスクロールされると右の画像が切り替わるという仕組みになっています。

あまり実用的ではないかもしれませんが、ちょっとやってみたかったというのと、Intersection Observerを使った画像の遅延などはネット上には溢れていますが、こういった別角度のものがなかったので、これを機会に作成してみました。

またコードなどは下記のようになっています。

See the Pen
test
by MID-LOW (@MID-LOW)
on CodePen.

上記のコードに関しては「ics.media」様の下記の記事から参考というか、ほぼ使用させていただいております(いつも有益な情報をありがとうございます。

JSでのスクロール連動エフェクトにはIntersection Observerが便利

実際にやってることは簡単なのです

html

    <div id="mainBox">
        <div class="left">
          <div class="box box1" id="intersect01">
            <div class="text">
              <div class="Heading">見出し1</div>
              <p>~中略~</p>
            </div>
          </div>
          <div class="box box2" id="intersect02">
            <div class="text">
              <div class="Heading">見出し2</div>
              <p>~中略~</p>
            </div>
          </div>
          <div class="box box3" id="intersect03">
            <div class="text">
              <div class="Heading">見出し3</div>
              <p>~中略~</p>
            </div>
          </div>
        </div>
        <div class="right" id="image">
          <div class="right__inner">
            <div class="image image01 intersect01">
            </div>
            <div class="image image02 intersect02">
            </div>
            <div class="image image03 intersect03">
            </div>
          </div>
        </div>
      </div>

htmlに関しては左にテキストのボックス、右に背景画像のボックスを設置しており、テキストの各ボックスにid=”intersect01″、画像の各ボックスにclass=”intersect01″を設置しています。

今回は名前を同じにしておかないと全く連動しないので、ここは注意が必要です。

CSS

* {
  margin: 0;
  padding: 0;
  line-height: 26px;
  box-sizing: border-box;
}

#mainBox {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
}

.left {
  width: 45%;
}
.left .box {
  display: flex;
  margin-bottom: 5em;
}
.left .box .text .Heading {
  font-weight: bold;
  font-size: 22px;
}
.left .box .text p {
  margin-bottom: 1em;
}

.right {
  position: relative;
  width: 50%;
}
.right .image {
  position: fixed;
  top: 0;
  width: 50%;
  height: 100%;
  background-size: cover;
  background-position: center;
}
.right .image.image01 {
  background-image: url("images/cat-image01.jpg");
  z-index: 1;
}
.right .image.image01.active {
  z-index: 4;
}
.right .image.image02 {
  background-image: url("images/cat-image02.jpg");
  z-index: 2;
}
.right .image.image02.active {
  z-index: 5;
}
.right .image.image03 {
  background-image: url("images/cat-image03.jpg");
  z-index: 3;
}
.right .image.image03.active {
  z-index: 6;
}

CSSもそこまで難しいことは書いていませんが、表示される順番をz-indexで指定しておかないと思った通りの動きにならないので注意してください。

またactiveが着いた要素に関しては、さらに前に表示されるようにそれぞれの要素のz-indexを調整してあげてください。

実際にローカル環境で色々とz-indexをいじって遊んでみると変な動きになるので、実際に試してみることをおすすめしますw

javascript

      const boxes = document.querySelectorAll(".box");

      const options = {
        root: null,
        rootMargin: "-50% 0px",
        threshold: 0
      };
      const observer = new IntersectionObserver(doWhenIntersect, options);
      boxes.forEach(box => {
        observer.observe(box);
      });
      function doWhenIntersect(entries) {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            activateIndex(entry.target);
          }
        });
      }
      function activateIndex(element) {
        const currentActiveIndex = document.querySelector("#image .active");
        if (currentActiveIndex !== null) {
          currentActiveIndex.classList.remove("active");
        }
        const newActiveIndex = document.querySelector(`.${element.id}`);
        newActiveIndex.classList.add("active");
      }

javascriptの解説に関しては「ics.media」様にて詳しく記されています。

本当にわかり易すぎて自分で説明するのが本当に無駄なくらいわかりやすいです。ですので、「ics.media」様にて解説を見ていただければと思います。

対応ブラウザ

Intersection Observerの対応ブラウザは下記のサイトから確認できます。

対応ブラウザはこちら。

IE11以外は問題なく動くので、みなさん使っちゃいましょう(暴論

はちょっと極端すぎるので対応策として、IE11はポリフィルを利用することでIntersection Observerを対応させることができます。

まとめ

従来のscrollイベントを使うよりも多くのメリットがIntersection Observerにはあります。

基本的には画像の遅延読み込みとかで多様されるかと思いますが、今回の記事をきっかけにスクロールで発火するものをIntersection Observerに私自身も切り替えていこうと思います。

普段はSEOやマーケティングが担当なのであまりこっちの勉強はしていないのですが、SEO目的で取り組む必要がありそうなものが増えていっているので、今後はさらに情報をアップデートしていきたいところです。

美土路 拓也
担当者:美土路 拓也
SEO、マーケティングなどを得意分野としています。最近ではコーディングからフロントエンジニア部分まで手を出す雑食な人間に進化しました。
見積り 見積り