intersecton observer APIの解説記事

intersecton observer APIの解説記事

スクロール監視の新定番 intersecton observer API

#181 スクロール監視

WEB制作

スクロールに応じて何を変更させたりするときに便利なintersecton Observer APIの解説記事です。 初めて聞くメソッドが多く、APIという名称が敷居を高く感じさせますが、使ってみると意外とシンプルで使い勝手のよい仕組みです。

公開日:
最終更新日:

商品リンクにアフィリエイト広告を利用しています

サイトマップサイトマップ

スクロール検知をもっと便利に Intersection Observer API

一定の位置までスクロールされたら、クラスを付与(または削除)する、という挙動を実装するには、従来の方法であれば、JavaScriptで位置の取得が必要でした。

JSでスクロールを取得するには、常に位置情報を監視し続ける必要があるので、負荷が気になるんですよね。

そんなときに便利なのがIntersection Observer API(交差セクションオブザーバーAPI)です。

Intersection Observer APIの概要

技術的な解説は以下のページが参考になります。
使い方の解説なども記載がありますので、一度目を通しておくと良いです。

読み込み中

Intersection Observer APIの役割は明確でわかりやすいんですが、コードは結構わかりづらいんですよね。

Intersection Observer APIを使う

このIntersection Observer APIを何に使うか。

私は仕事でLPを作るのですが、LPの下部に固定のCTA(コールトゥーアクション:申し込みボタンとか)を設置することを依頼されます。

その時にFV(ファーストビュー)を超えてから、固定ボタンを表示してほしい、と依頼を受けます。

ということで、それを想定してサンプルを作りたいと思います。
ちなみに似たようなものをこのページでも使用しています。

FVを超えたら固定CTAを表示する設計

必要な物が、CTAボタン、FV要素。

FVがページ上部に到達したら、固定CTAを表示するという仕様で作ります。

サンプルの挙動解説

FVと書かれた画像が、ウィンドウの上部に全部到達すると、CTAというボタンが表示されます。
Intersection Observer APIの「intersectionRatio」というプロパティを使うと、交差している量を計測できるのでそれを使っています。

このintersectionRatioの値が「0」になったらCTAボタンが表示されます。
intersectionRatioの値を「ページサンプル」という画像の下に表示するようにしています。

挙動サンプル

ファーストビュー
ページ要素

IntersectionRatio:

CTA

HTMLのサンプルコード

上記サンプルのHTMLコードです。

<div id="sample">
	<div id="fv">
		<img src="img/fv.png" width="640" height="960" loading="lazy">
	</div>
	<img src="img/page.png" width="640" height="250" loading="lazy">
	<p class="mt_20">IntersectionRatio:<span id="ir_value"></span></p>
	<div id="sample_cta">
		<img src="img/cta.png" width="640" height="117" loading="lazy">
	</div>
</div>		

サンプルのJavaScriptコード

上記サンプルのJavaScriptのコードを表示します。
ベースは先ほど紹介しているMDNをカスタマイズしたものです。

let target_item = document.querySelector("#fv");
let cta = 	document.querySelector("#sample_cta");
window.addEventListener("load", (event) => {
	sample_createObserver();	
}, false);

function sample_createObserver() {
	let sample_observer;
	let options = {
		root: null,
		rootMargin: "-70px",
		threshold: 0
	};
	sample_observer = new IntersectionObserver(cta_disp, options);
	sample_observer.observe(target_item);
}	

function cta_disp(entries){	
	entries.forEach(entry => {
		if (entry.intersectionRatio <= 0) {
			cta.classList.add("sample_on");
		}else{
			cta.classList.remove("sample_on");
		}				
	});
}	

サンプルコードの解説

実際に表示しているサンプルは、intersectionRatioの表示などもしているのですが、そこは省いて紹介します。

1.変数の定義

最初にFVとCTAの定義をしています。

let target_item = document.querySelector("#fv");
let cta = 	document.querySelector("#sample_cta");

2.実行関数の呼び出し

次にページが読み込まれたら、window.addEventListenerで、sample_createObserver()という関数を呼び出します。

window.addEventListener("load", (event) => {
	sample_createObserver();	
}, false);

3.sample_createObserverの定義

IntersectionObserverの呼び出しと、そのオプションの設定をしています。

function sample_createObserver() {
	let sample_observer;
	let options = {
		root: null,
		rootMargin: "-70px",
		threshold: 0
	};
	sample_observer = new IntersectionObserver(cta_disp, options);
	sample_observer.observe(target_item);
}	

let sample_observer;で定義した変数に、
new IntersectionObserver(cta_disp, options);を代入して、IntersectionObserverを呼び出す。

new IntersectionObserverの引数に入っている「cta_disp」は閾値を超えたら実行する関数が入っています。

4.optionsの内容

細かい設定はMDNの解説を一読することをオススメします。
が、わかりづらいので、私なりの解釈で説明入れておきます。

let options = {
	root: null,
	rootMargin: "-70px",
	threshold: 0
};

root: nullについて

これはスクロールする要素を指定します。
今回はnullを指定しているので、既定のブラウザのビューポートになります。

root
ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素です。指定されなかった場合、または null の場合は既定でブラウザーのビューポートが使用されます。

MDNより引用

rootオプションを指定した場合、監視対象はrootの子要素でなければ動作しません。

null以外の指定方法

nullではなく、要素を指定する場合は、

root: document.querySelector("#fv"),

のように指定します。

rootMargin: "-70px",について

これは、交差地点のマージンを指定しています。
私のサイト(今見ているページ)には、ページ上部に固定のナビが入っているので、その分を抜いて計算させています。

-(マイナス)の値を入れると交差地点が下に下がります。

threshold: 0 について

対象の要素がどの程度表示されたらコールバックをさせるか、を指定する値になります。

もしかしたら間違っているかもですが、IntersectionRatioの値と同じと考えてよいかと思います。

「intersectionRatio」は前述しましたが、交差地点と監視対象がどの程度、交差しているかを測るプロパティです。

「intersectionRatio」が「0」になったら、「cta_disp」関数が呼び出されるという仕組みです。

サンプルでは、intersectionRatioの値を表示しているので参考にしてください。
交差が開始すると「1」以下の数値になり、交差し終わると「0」になります。

threshold:は複数指定できる

thresholdは複数個の値を指定できます。
複数個を指定する場合は、配列の書式で記述します。

threshold: [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]

このページで実際に表示しているサンプルは、0~1までを0.1で区切ってコールバックしています。

intersectionRatioを細かく表示するために、このようにしていると。

threshold:0 は完全にスクロールしたら発動

この「threshold」の値が「0」というのは、言い換えると「見えなくなったら発動」ということになります。

0の場合、完全にスクロールして見なくなったらコールバックが発動する、という意味です。

逆に「1」を指定すると、対象要素が完全に表示されている(1pxもスクロールエリアにかかっていない)状態で発動となります。

サンプルの場合、FVがスクロールし終わったらCTAを表示する、という目的なので「0」を指定しているというわけですね。

5.sample_observerの定義

解説が長くなったのでコードを再掲します。
8行目の「sample_observer = new IntersectionObserver(cta_disp, options);」の解説です。

function sample_createObserver() {
	let sample_observer;
	let options = {
		root: null,
		rootMargin: "-70px",
		threshold: 0
	};
	sample_observer = new IntersectionObserver(cta_disp, options);
	sample_observer.observe(target_item);
}	

new IntersectionObserver(cta_disp, options);で、「IntersectionObserver」を呼び出し、その引数で「cta_disp」関数と、「options」を指定します。

コールバックで呼び出す関数を指定する、と、オプションを指定する、と覚えればOK。

6.監視対象の指定

9行目の、sample_observer.observe(target_item); は、スクロールを監視する対象を指定します。

target_itemは以下のものを指定しています。

let target_item = document.querySelector("#fv");

「#fv」がスクロールの監視対象になっています。

7.コールバックする関数の解説

いよいよ最後の関数です。
コールバックされたときに実行する関数です。

function cta_disp(entries){	
	entries.forEach(entry => {
		if (entry.intersectionRatio <= 0) {
			cta.classList.add("sample_on");
		}else{
			cta.classList.remove("sample_on");
		}				
	});
}

function cta_disp(entries)の引数の「entries」の中身は「IntersectionObserverEntry」のオブジェクトの配列が入ります。

この内容を知りたい場合はconsole.logで表示させると確認できます。
色々な値が入っております。

entries配列の中身の一部

以下が実際に「entries」をconsole.logで表示させた配列の内容の一部です。

[IntersectionObserverEntry]
0: IntersectionObserverEntry
boundingClientRect: DOMRectReadOnly {x: 111.5, y: -1262.0625, width: 840, height: 990, top: -1262.0625, …}
intersectionRatio: 0
intersectionRect: DOMRectReadOnly {x: 0, y: 0, width: 0, height: 0, top: 0, …}
isIntersecting: false
isVisible: false
rootBounds: DOMRectReadOnly {x: 70, y: 70, width: 1283, height: 1424, top: 70, …}
target: div#fv
time: 280.2000000178814
[[Prototype]]: IntersectionObserverEntry
length: 1
[[Prototype]]: Array(0)

entries配列をforEachで展開して条件指定

entriesが配列なので、forEachで展開し、その配列の中にある「entry.intersectionRatio」の値に対してif文を指定。

if (entry.intersectionRatio <= 0) {
	cta.classList.add("sample_on");
}else{
	cta.classList.remove("sample_on");
}			

intersectionRatioの値が「0」以下の場合「sample_on」というCSSのクラスを付与し、0より大きい場合はそのクラスを削除しています。

▼指定しているCSSの内容はこちら。

#sample_cta{
	visibility: hidden;
}

#sample_cta.sample_on{
	visibility: visible;
}

サンプルはCLSの発生が嫌だったので、visibilityで非表示化しています。

intersectionRatioの値が「0」以下なので、FV要素がページ内から完全にスクロールし終わったら、CTAが表示される、という仕組みですね。

Intersection Observer APIまとめ

ちゃんと理解して使おうとするとなかなかややこしいのですが、コード自体は短めで構造はシンプルなので使いやすいと思います。

私もちゃんとは理解してないのですが、この記事を書いて少し理解が深まりました。

常に監視し続けなくて良いのがメリットで、ユーザーの環境に負荷がかからず良いとおもいます。

使い方次第でいろいろと使い道がありそうなので、ぜひ使ってみてください。

主にrootMarginについて追記しました

rootMarginの考え方を中心に、スクロールに応じて画像が大きくなるサンプルを使った解説記事を追加しました。

WEBデザイナー・プログラミング学習にオススメ

記事内で紹介している商品リスト
(価格はAmazon参考価格)

独習JavaScript 新版

1,639円(税込)

独習JavaScript 新版

JavaScript 第7版

5,060円(税込)

JavaScript 第7版

いちばんやさしいJavaScriptの教本 第2版 ECMAScript 2017(ES8)対応 人気講師が教えるWebプログラミング入門 「いちばんやさしい教本」シリーズ

2,178円(税込)

いちばんやさしいJavaScriptの教本 第2版 ECMAScript 2017(ES8)対応 人気講師が教えるWebプログラミング入門 「いちばんやさしい教本」シリーズ

図解! JavaScriptのツボとコツがゼッタイにわかる本 “超”入門編

1,188円(税込)

図解! JavaScriptのツボとコツがゼッタイにわかる本 “超”入門編

JavaScript コードレシピ集

3,114円(税込)

JavaScript コードレシピ集

JavaScript[完全]入門

2,653円(税込)

JavaScript[完全]入門

ステップアップJavaScript フロントエンド開発の初級から中級へ進むために

2,376円(税込)

ステップアップJavaScript フロントエンド開発の初級から中級へ進むために

スクロール監視の関連ページ

SNSでこの記事をシェアできます

ブログ デイリーアクセスランキング

車用スマホホルダー
1位

車用スマホホルダー

スマホをカーナビとして使うと熱さで充電ができなくなるので、熱対策と1年間使って外れることがなかったスマホホルダーの紹介。

PHPで作るカレンダー
2位

PHPで作るカレンダー

forとifとforeachがメインのPHPによるカレンダーの作り方です。 祝日設定がちょっとめんどくさいんですよね。

ノートPCスタンド
3位

ノートPCスタンド

ノートパソコンを横にしまうと結構な専有面積があるのですが、立てて収納できればわずか数cmで使えるので本当に快適です!

MusicBeeのレイアウト変更方法
4位

MusicBeeのレイアウト変更方法

MusicBee 3.1のレイアウトをデフォルトの状態から、自分好みのレイアウト設定に変更する方法を写真付きで紹介しています。

PHPを使って作るCMS
5位

PHPを使って作るCMS

PHPを覚えたらデータベース回りも一緒に覚えるのがオススメです、 制作できるものの幅が広がって色々な仕組みを理解できます

PHPで作るカレンダーの作り方2
6位

PHPで作るカレンダーの作り方2

PHPで作るカレンダーの作り方の第二弾です。 今回はクリックした日付を取得してformに代入するところも解説してます。

机上台
7位

机上台

机上台という机の上に設置し、モニターを置きデッドスペースになるモニターの下に空間を生み出す悪魔的発想の商品を使ってみました。

Bluetoothイヤホンの使い方
8位

Bluetoothイヤホンの使い方

Bluetoothイヤホンのペアリング方法やリモコンの操作方法、リダイヤルの防止策を画像入りで解説します。

108cmの机上台
9位

108cmの机上台

FENGEの108cm 2段式の机上台レビュー! 横幅が広く収納力抜群でデザイン性もいいので非常に満足しています!

ホワイトボード
10位

ホワイトボード

100均で買えるつっぱり棒とネットを使ってホワイトボードを窓枠に設置してみました。 ホーロー製のホワイトボードがオススメ!

カテゴリ一覧

オススメ商品レビュー

オススメ商品レビュー

世の中にある比較サイトや、いかがでしたか系サイトが嫌いなんです。使ってないのにえらそうなこと言うなと。なので体験談です。

WEB制作

WEB制作

WEBサイトを作れますと一言に言っても色々な技術があるわけですよ。アウトプットの形は一緒でもいろいろこだわりがあるんです。

カメラ

カメラ

2018年4月に購入したソニーのミラーレス一眼「α7Ⅲ」に関連する記事一覧ページです。 作例集やカメラグッズレビューなど。

美味しいもの

美味しいもの

食に関してはあまりこだわりがないんですけどね、こだわりがない分美味しいと思ったものは本当においしいと思ったものなんですよ

Amazonプライム動画

Amazonプライム動画

Amazonプライム会員なら無料で利用できるAmazonプライム動画から、いろいろな動画をみたレビュー記事のまとめページ

旅LOG

旅LOG

家族旅行やおでかけした際の旅ブログです。夏休みの家族旅行(4人家族)で訪れた観光名所の感想などを記しています。

プロフィール

プロフィール

Start-Point.netの管理人のプロフィール紹介を兼ねた、自分の中のルールや決め事やエピソードなでお書いていきます

日記

日記

日記と言っても色々な日記があるわけで、記録的な日記や心理描写を色濃く描いた日記などをまとめたページです。

thanks

thanks

自分を表現することって意外と難しいんですよね。照れがあったり、間違ったこといってないかとよくわからない何かと戦ったりして。

記事内で紹介している商品

独習JavaScript 新版

1,639
(税込)