WEB NOTE
WEB関連の備忘録

「IntersectionObserver」で作る、スクロールすると要素を表示させる方法

Javascript

特性の要素が可視範囲に入ったタイミングでクラスを付けるスクリプトを実装し、CSSで動きを付ける方法を紹介します。

よく「スクロールアニメーション」などで検索すると出てくる 、 紹介されている記事を見ていると、あまりサイトのパフォーマンスに良くないコードやJQuery製のプラグインが紹介されています。
パフォーマンスに良くない原因は、スクロールするたびに処理を行っているからです。

今回紹介するのは、Javascriptの「IntersectionObserver」を使い、ターゲット要素を監視し、ビューポートと交差するを発火する処理を行います。
これまでの処理に比べ、圧倒的にパフォーマンスがよくなります。
一つデメリットとして、IEに対応していないため、ポリフィルを読み込む必要があります。

DEMO

See the Pen MWwRpBN by sakuya (@sakuyanet) on CodePen.

実装コード

JavaScript

function scan(hoge, setting) {
	const target = hoge === undefined ? '.animation-box' : hoge;
	const add = setting === undefined ? 'active' : setting;

	const targets = [].slice.call(document.querySelectorAll(target));
	const options = {
		root: null,
		rootMargin: "0px 0px -50%",
		threshold: 0
	};

	const observer = new IntersectionObserver(callback, options);

	targets.forEach(function(target) {
		observer.observe(target);
	});

	function callback(entries, object) {
		entries.forEach(function(entry, i){
			if(!entry.isIntersecting) return;
			const item = entry.target;
			animation(item);
			object.unobserve(item);
		})
	}

	function animation(target) {
		if (!target.classList.contains(add)) {
			target.classList.add(add);
		}
	}
}

HTML

<!-- 表示させたい要素 -->
<div class="fadeIn-bottom animation-box"></div>

<!-- スクリプトを呼び出し -->
<script src="script.js"></script>
<script>
		scan();
</script>

CSS

.animation-box {
	&.fadeIn-bottom {
		opacity: 0;
		&.active {
			animation: fade-in-bottom 0.6s cubic-bezier(0.175, 0.885, 0.320, 1.275) both;
		}
	}
}
@keyframes fade-in-bottom {
	0% {
		transform: translateY(50px);
		opacity: 0;
	}
	100% {
		transform: translateY(0);
		opacity: 1;
	}
}

アニメーションはこちらから拝借しました。

https://animista.net/

使い方

使い方は、クラスを付けたい要素に .animation-box のクラスを振ります。
CSSで要素を非表示にします。そして、 .active クラスが付いたときに表示するアニメーションを設定します。
今回は animation で表示する処理を紹介しましたが、 transition でも問題ないです。

表示させたい要素につけるクラス、追加するクラスを変更する場合は、以下のようにスクリプトを呼び出せば大丈夫です。

<div class="fadeIn-bottom anime"></div>

<!-- 表示させたい要素につけるクラス名 anime 、追加するクラス名を start とする場合 -->
<script>
		scan('.anime','start');
</script>

IEへの対応方法

Can I use : IntersectionObserver

IEは「IntersectionObserver」が対応していないため、別途でポリフィルを読み込む必要があります。
こちらからダウンロードし、読み込んでください。