はじめに
担当しているサイトがIE非対応になったため、それとともにパフォーマンス改善処理を見直し画像遅延読み込みが改善の余地があったため今回loading属性+InterSectionObeserverで実装した。
loading属性
Chrome 75からサポート。
loading属性とはブラウザがネイティブで遅延ロードをサポートするもの(参照: https://coliss.com/articles/build-websites/operation/work/native-image-lazy-loading.html)
IntersectionObserver
Intersection Observer APIは直訳すると交差監視APIという名前です。これは要素と要素の交差を検知するAPIになります。(参照: https://ics.media/entry/190902/)
実装
本来、loading属性はHTMLのみで完結しますが、対応ブラウザはChrome 76
、Firefox 75
、Chromium 版 Edge
においては、デフォルトで利用可能になっていますがそれ以外が使用不可なので使用できない箇所はJavascriptで実装していきます。
HTML
<img class="hoge" src="/images/common/noimage.png" data-src="/images/hoge.png" alt="hoge" loading="lazy">
src="/images/common/noimage.png"
: 遅延読み込み前に読み込む1×1画像
data-src="/images/hoge.png"
:読み込む画像(今回はJavaScriptでも使用する可能性があるため、data-srcで指定)
loading="lazy"
: loading属性セット
JavaScript
const lazyLoad = function () {
const dataSrc = document.querySelectorAll("img[data-src]")
const sources = document.querySelectorAll("source[data-srcset]");
//対応ブラウザかチェック
if ("loading" in HTMLImageElement.prototype) {
//loading属性対応の場合 data-srcの値をsrcへセット
if (sources.length !== 0) {
sources.forEach(function (source) {
source.srcset = source.dataset.srcset;
});
}
dataSrc.forEach(function (img) {
img.src = img.dataset.src;
});
} else {
//loading属性非対応の場合 IntersectionObserverを行う。
const targets = Array.from(dataSrc);
const img_path = "data-src";
const options = {
// 上下100px手前で発火
rootMargin: "100px 0px"
};
// 初期化
const observer = new IntersectionObserver(callback, options);
targets.forEach(function (img) {
// 監視の開始
observer.observe(img);
});
// コールバック
function callback(entries, object) {
entries.forEach(function (entry) {
// 交差していない
if (!entry.isIntersecting) return;
// ターゲット要素
const img = entry.target;
// 遅延ロード実行
loading(img);
// 監視の解除
object.unobserve(img);
});
}
// 遅延ロード
const loading = (img) => {
// data-srcの値を取得
if (sources.length !== 0) {
sources.forEach(function (source) {
source.srcset = source.dataset.srcset;
});
}
const src_val = img.getAttribute(img_path);
if (src_val) {
// 画像パスを設定
img.src = src_val;
img.onload = function () {
// data-src属性を削除
this.removeAttribute(img_path);
};
}
};
}
}
const _lazyload = lazyLoad();
export default _lazyload;
"loading" in HTMLImageElement.prototypeで対応ブラウザだとtrueが返される。
IntersctionObserverの処理は別記事で紹介しているので割愛。
おわり
loading属性での遅延読み込みがとにかく記述が少なく、HTMLで完結してくれるから楽。
対応ブラウザが今後も増えてくれることを願います。
参照記事
ics.media JSでのスクロール連動エフェクトには
Chromeに実装される新機能『loading属性』について解説、ついにブラウザがネイティブで遅延ロードをサポート