
【JavaScript】IntersectionObserverって何?スクロール連動の仕掛けがカンタンに!
目次
そもそもIntersectionObserverって?
簡単に言うと、「ある要素が、画面(または特定の親要素)の中に入ったかどうかを教えてくれる仕組み」です。
たとえばこんな場面、よくありませんか?
• 特定のセクションが画面に入ったらアニメーションを始めたい
• 無限スクロール(下にスクロールしたらコンテンツを自動で追加したい)
• ヘッダーの表示/非表示をスクロールに合わせて切り替えたい
そんなとき、昔はスクロールイベントを使って位置をゴリゴリ計算してましたが、今はIntersectionObserverでスマートになります!
使い方はとってもシンプル
まずは基本の構文から。
- const observer = new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- console.log('見えてるよ!', entry.target);
- }
- });
- });
- const target = document.querySelector('.watch-me');
- observer.observe(target);
このコードでやってることは:
1. IntersectionObserverを作成
2. .watch-meというクラスの要素を監視開始
3. 画面内にその要素が入ったタイミングでコールバックが発火!
オプションも指定できる
- const observer = new IntersectionObserver(callback, {
- root: null, // 画面全体(デフォルト)
- threshold: 0.5 // 50%表示されたら反応
- });
他にも、rootを指定すれば「この特定のスクロールエリア内で表示されたら反応」なんてこともできます。
ちょっとした例:スクロールでフェードイン
See the Pen
Untitled by ryotom (@ryotam-smoke)
on CodePen.
これだけで、スクロールして表示されたらふわっと表示する仕掛けが完成です!
このコード、何をしているの?
ざっくり言うと、「.fade-inクラスが付いている要素を監視して、画面に入ったら.showクラスを追加する」という動きです。
IntersectionObserverで監視
- const observer = new IntersectionObserver((entries) => {
- ...
- });
ここでは「画面に入ってきた要素を検出するためのオブザーバー(監視者)」を作っています。
• entriesは、監視している要素たちの状態(見えているかどうかなど)を配列で返してくれるものです。
• entry.isIntersecting は「今、要素が画面内に見えているかどうか」を true/false で教えてくれます。
要素が見えたら .show クラスを追加
- if (entry.isIntersecting) {
- entry.target.classList.add('show');
- }
この部分で、「もし画面内に入ってきたら、show というクラスを追加してね」と命令しています。
つまり、CSS側で .show にアニメーションを設定しておけば、「画面に入った瞬間にアニメーションが始まる」というわけです!
.fade-inの要素たちを監視!
- document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
この一文で、
• .fade-in というクラスが付いているすべての要素を取得し、
• それぞれに対して observer.observe(el) を呼び出して、
• 一つずつ監視対象に登録しています。
※ el は 「element(エレメント)」の省略形で、HTMLの要素(=DOM要素)を指す変数名です。
この el という名前は実は何でもOKなんですが、element の略であることが多く、わかりやすいのでよく使われています。
スクロールで「見えてる?見えてない?」を表示してみよう!
以下のようなUIを作ります:
• スクロールしていくと出てくる要素(ここでは大きな #box)。
• それが画面に表示されたら、左上に「見えてます!」と表示。
• 画面から外れたら「見えません!」と切り替わる。
See the Pen
Untitled by ryotom (@ryotam-smoke)
on CodePen.
「threshold」を用いてアニメ開始のタイミングを操ろう!
threshold(スレッショルド)は、IntersectionObserverの動作条件を決める「設定値(オプションプロパティ)」の一つです。
「どれくらい見えたら反応するか」を設定することが出来ます。
ざっくり言うと、対象の要素が画面(ビューポート)に何割見えたら処理を実行するかを決めるものです。
- { threshold: 0.3 }
と書いてある場合、「その要素が 30% 見えた時点で反応する」という意味になります。
0の場合1pxでも入ったら反応。0.5の場合は50%以上見えたら、
1.0は全体が完全に見えたら反応するというように、
「どのくらい出たら」の基準を数字で細かく決められるのが threshold なんです。
実際の使用例
- const observer = new IntersectionObserver((entries) => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- entry.target.classList.add('active');
- } else {
- entry.target.classList.remove('active');
- }
- });
- }, { threshold: 0.5 });
- document.querySelectorAll('.card').forEach(card => {
- observer.observe(card);
- });
See the Pen
Untitled by ryotom (@ryotam-smoke)
on CodePen.
このコードでは、監視している要素が半分以上表示されたらクラスが付与されます。
複数の閾値を配列で指定もできる!
- threshold: [0, 0.25, 0.5, 0.75, 1]
こうすると、それぞれの割合を通過するたびにイベントが発火します。
細かいアニメーションや、プログレスバーの実装などに使えます。
rootを使ってスクロール可能なdivの中で監視対象を設定
rootを指定することで、カスタムスクロール領域の中だけを監視対象にできます。
モーダル、タブ切り替え、横スクロールのギャラリーなどでも有用です。
See the Pen
Untitled by ryotom (@ryotam-smoke)
on CodePen.
まとめ
IntersectionObserver を使えば、スクロールに合わせたインタラクションがとても簡単に実装できます。
パフォーマンスにも優しく、スクロールイベントよりスマートな選択肢です。
Webサイトやブログにちょっとしたリアクションを加えるとき、ぜひ活用してみてください!