キャッチ画像

前置き

画像をそのまま読み込む時代は終わりました。デバイスごとに最適なサイズを配信したり、画面に入ってきたら読み込ませるなど、より高いパフォーマンスを意識したサイト開発が求められています。

5G規格の導入によって大容量のデータを高速でやりとりできるようになっていく一方で、我々技術者は、余計なトラフィックを増やさないようにすることを目指す必要が出てきました。

サイトパフォーマンスの向上は、一昔前まではコアな技術者たちの趣味(尊敬しています)だったかもしれませんが、現在はメディアサイトをはじめとしたさまざまなサービスで取り組みが広がりつつあります。GoogleもSEO界隈で積極的に取り組んでいることから、今後デファクト・スタンダードとなっていくでしょう。

画像の遅延読み込みを実装する手段

2020年5月現在、画像の遅延読み込みを実装するソリューションとして、以下の3つが挙げられます。弊社が対応するブラウザでの使用可否を表でまとめました。

ソリューション 実装方法 IE11 Edge Firefox Chrome Safari iOS Safari Chrome for Android
loading="lazy" HTML × × ×
Intersection Observer API JS ×
getBoundingClientRect() JS

loading="lazy" はもっとも新しいソリューションです。ブラウザがネイティブで遅延読み込みをサポートしますので、JavaScriptを書く必要がなく、img要素にloading属性を付与するだけで対応できます。一方で、対応ブラウザが限られていること、ブラウザ任せの読み込みタイミングであることが課題とされています。

Intersection Observer API は、対象要素とビューポートの交差を非同期的に検出する方法を提供します。これを利用することで、対象のimg要素がページのスクロールで画面内に入るタイミングで画像を読み込むことができます。Internet Explorer 11を除いたほとんどのブラウザに対応しています。

getBoundingClientRect() は、Internet Explorer 11(またはそれ以下)を含んだほぼすべてのブラウザで実行できます。しかし、常に画像の絶対位置とスクロール位置を計算しなければならないため、リソースを大量に消費しサイトのパフォーマンスが非常に悪化します。

対応ブラウザについて詳しく知りたい方はこちらを参照してください:
https://caniuse.com/#feat=loading-lazy-attr
https://caniuse.com/#feat=intersectionobserver
https://caniuse.com/#feat=getboundingclientrect

Polyfillで古いブラウザをカバーする

Polyfillの概要図

最新の画像の遅延読み込み機能を使うために、いくつかのブラウザを見限ることは非現実的です。とくにBtoB案件では、Internet Explorer 11対応もいまだに需要がありますから、古いブラウザを考慮した実装方法を検討しなければなりません。

そこで、Polyfill(ポリフィル)と呼ばれる仕組みを使った対応方法があります。Polyfillは、新しい技術を取り入れながら、サポートしていない古いブラウザでも動作させるための仕組みです。Polyfillを使えば、古いブラウザでも擬似的に遅延読み込みが対応できるようになります。たとえば、モダンブラウザでは Intersection Observer API を利用し、対応していないブラウザは getBoundingClientRect() を使うといった具合です。有名なJavaScriptプラグインは、Polyfill対応されているものがいくつかあります。

Polyfillの語源について: https://remysharp.com/2010/10/08/what-is-a-polyfill

いろいろな遅延読み込みプラグイン

上記の内容を踏まえて、いくつかの遅延読み込みプラグインを紹介します。ファイルサイズの基準はdist/*.min.jsとして、ない場合はdist/*.jsとしています。

プラグイン名 GitHubスター ファイルサイズ 手段 Polyfill
loading-attribute-polyfill 184 2.88 KB loading="lazy"
lazysizes 13,300 7.07 KB getBoundingClientRect()
Lozad.js 6,200 2.72 KB Intersection Observer API
Layzr.js 5,600 2.75 KB getBoundingClientRect()
LazyLoad 5,300 7.63 KB Intersection Observer API
yall.js 1,100 2.00 KB Intersection Observer API

* 2020年5月10日時点の情報

loading-attribute-polyfill は、最新の遅延読み込みに対応していないブラウザのためにフォールバックするためのPolyfillです。SEOフレンドリーでInternet Explorer 9まで対応しています。noscriptタグを常用しなければならないので、開発の時点で導入をしておくべきでしょう。

lazysizes は、GitHubで一番人気の遅延読み込みプラグインです。多機能で拡張機能なども豊富に用意されています。なお、標準ではgetBoundingClientRect()を利用していますが、src/lazysizes-intersection.jsを使うことでIntersection Observer APIを利用した遅延読み込みが使えます。ただし、ドキュメントに一切記述がないため、現時点では参考程度にとどめておいたほおうが良さそうです。

Lozad.js はIntersection Observer APIを用いた軽量なプラグインです。さまざまなWebサービスで利用されているようで、npmパッケージとしても公開されているため、webpackなどのモジュールバンドラーでも気軽に利用できます。Polyfillもnpmで公開されています。

Layzr.js は、getBoundingClientRect()を利用したプラグインです。dataset属性をサポートしていないブラウザでも高解像度画像が使用できるように、data-retina属性が用意されています。

LazyLoad は、lazysizesに次ぐ老舗プラグインです。35のContributionsがあり、定期的にメンテナンスがされているプラグインです。絵文字が可愛いです。Intersection Observer APIを使用しており、Polyfillの追加方法もいくつかのパターンが用意されています。

yall.js は、Web Fundamentals | Google Developersに数多く記事を寄稿しているJeremy Wagner氏が作成したプラグインで、Intersection Observer APIを使用したプラグインの中ではかなり軽量です。そのぶん必要最小限の構成となっており、気軽に導入できます。

どれを使うかはプロジェクトに合わせて

どのプラグインも基本的には以下のようなHTMLを書くだけで実装できます。

<img class="lazyload" data-src="awesome-photo.jpg" alt="alternate text">

この書き方に慣れておけばどれも難しくないでしょう。プラグインによって色々な機能やAPIが用意されていますので、それぞれのプロジェクトに合うプラグインを選びましょう。次に、選ぶときのポイントをいくつか示します:

選ぶポイント

  • ファイルサイズの軽さ
  • レスポンシブイメージへの対応
  • iframeへの対応
  • クラス名などの柔軟さ
  • SEO対策されているか
  • EventやMethodの豊富さ
  • Internet Explorer対応など

yall.jsで遅延読み込みを実装する

前置きがとても長くなりましたが、これらを踏まえて実際に遅延読み込みを実装していきましょう。今回はファイルサイズが軽く、必要最小限の機能が機能しかないyall.jsを使って実装します。

このJavaScriptプラグインは、Intersection Observer APIを利用して遅延読み込みを行います。そのため、Webサイトのパフォーマンスを下げることなく遅延読み込みを実装できます。Intersection Observer APIが使用できないブラウザは、プラグイン指定のPolyfillを利用することでフォールバックされますので、Internet Explorer 11をはじめとした古いブラウザでも使用できます。

使用方法

プラグインの読み込み

GitHubのリポジトリをダウンロードし、distディレククトリにあるyall.min.jsをHTMLで読み込みます。

+ <script src="/PATH/TO/yall.min.js"></script>

Internet Explorer 11対応をする場合は、Polyfillをプラグインより上で読み込みます。

+ <script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
  <script src="/PATH/TO/yall.min.js"></script>

次に、JavaScriptをイニシャライズします。

+ document.addEventListener("DOMContentLoaded", yall);

これでプラグインの準備は完了です。

マークアップ

プラグインの実行トリガーとなるクラスは初期値でlazyです。src属性には初期表示の画像を指定します。これは無くても問題ありません。そしてdata-src属性で遅延読み込みの画像を指定します。

+ <img class="lazy" src="placeholder.png" data-src="lazy-load-image.jpg" alt="alternate text" height="400" width="600">

height/width属性は無くても問題ありませんが、未指定ですと読み込み前後でスクロール位置が変わるため、指定していたほうが安心です。静的HTMLでは指定が面倒ですが、CMSではheight/width値がデータベースに登録されていることが多いと思いますので、簡単に指定できるかと思われます。

いかがでしょうか。たった数行書くだけで、簡単に実装できました。

実装のサンプル動画

もしJSが実行されない環境だったら

上記の内容でじゅうぶん完成形ですが、JavaScriptを実行できない環境でも画像が正しく表示されるようにしてみましょう。これも簡単な実装で済みます。

まず、html要素にno-jsクラスを付与します。

- <html>
+ <html class="no-js">

次に、JavaScriptでno-jsクラスを削除する文を記述します。

+ document.documentElement.classList.remove("no-js");
  document.addEventListener("DOMContentLoaded", yall);

これによって、JavaScriptが実行されればno-jsクラスが削除され、実行されない場合はクラスが残るというわけですね!

img要素の部分は次のようにnoscript要素を追加しましょう。

  <img class="lazy" src="placeholder.png" data-src="lazy-load-image.jpg" alt="alternate text" height="400" width="600">
+ <noscript>
+   <img src="lazy-load-image.jpg" alt="alternate text" height="400" width="600">
+ <noscript>

最後に、no-jsクラスとlazyクラスを使ってCSSを調整します。

+ .no-js .lazy {
+   display: none;
+ }

さいごに

遅延読み込みはプラグインを使えば簡単に実装できます。冒頭にもお話したように、遅延読み込みは今後もっと身近な技術になっていくでしょうから、今のうちに試しておくと良いかもしれません。(フルスクラッチでもできますが、プラグインを使ったほうが圧倒的に多機能で楽ですね!)今回を機に実装方法を覚えて、快適な遅延読み込みライフを満喫しましょう!

参考文献

佐々木

佐々木 Webデザイナー

2014年入社。安定感や清潔感のあるデザインが得意。CMSに導⼊しやすい効率的かつ保守性の⾼いマークアップができ、デザイナーながらフロントエンドの技術も有する。
旅と写真が好きだが、地図を眺めていて1日が終わることがよくある。