サイトに画像の遅延読み込みをGoogle推奨のIntersection Observerで実装しよう 結城永人 - 2019年4月11日 (木) ブログの表示速度をPageSpeed Insightsで調査すると改善できる項目として「オフスクリーン画像の遅延読み込み」が出て来て取り入れると0.1秒くらい短縮できると分かる。 オフスクリーンの非表示の画像は、クリティカルなリソースをすべて読み込んだ後に遅れて読み込むようにして、インタラクティブになるまでの時間を短縮することをご検討ください。 改善できる項目|PageSpeed Insights|Google Developers 真っ先に心配なのはSEO(検索エンジン最適化)対策で、専らGoogle検索でのサイト評価が下がるとしたら辛い。必要な画像が的確に表示されないとサイトを巡回するクローラーに読み込まれず、コンテンツの品質が低いと判断されて検索結果で不利になってしまうのではないか。個人的に検索エンジンからのアクセスダウンは何としても避けなくてはならないと感じる。 サイトの表示速度もGoogle検索でのサイト評価の要因なので、可能なかぎりは是非とも取り入れておきたい画像の遅延読み込みでもある。 昨年、パソコンと同様にスマホでもサイトの表示速度がサイト評価に重視されるスピードアップデート(ページの読み込み速度をモバイル検索のランキング要素に使用します)が導入されてそれ自体は物凄く遅いサイトでなければ不利にはならない検索アルゴリズムらしいけど、とにかく訪問者の利便性が低い状態が有利ではないはずだから少しでもサイトの表示速度を上げる取り組みはSEO対策で欠かせない。 追記:サイトの画像の遅延読み込みはHTMLのloading属性で簡単に行えるようになった。JavaScriptのIntersection observerも同じように使えるけど、サイトのプログラムで望み通りに動作させる以外の目的ではHTMLよりもコードを増やしてしまうので、むしろ画像以外のコンテンツの遅延読み込みやその他の無限スクロールなどの動作に使う方が向いているだろう。 目次Google推奨でSEO対策にも向くIntersection Observerの利点JavaScriptのIntersection Observerでの画像の遅延読み込みの設置法IntersectionObserverのプログラムのアウトラインIntersectionObserverEntityの七つのプロパティIntersection Observerの三つのオプションスクロールで画像を赤から青へ切り替えるサンプルサイトの画像の遅延読み込みに無料で使える二つのプログラムJeremy Wagnerのスクリプト(Google Developers)lozad.js:Apoorv Saxenaのライブラリー(GitHub) Google推奨でSEO対策にも向くIntersection Observerの利点 PageSpeed InsightsはGoogleが提供しているWebサービスだからサイトの表示速度を高めるための様々なアドバイスはSEO対策を踏まえて行われているかも知れない。 気になる「オフスクリーン画像の遅延読み込み」を改善できる項目のLearn more(もっと学ぶ)を確認するとOffscreen Images(オフスクリーン画像)でJavaScriptのIntersection Observer APIを使ったサイト作成が推奨されていた。 オフスクリーン画像の遅延読み込みにはIntersection Observerの使用を賢い決断と考えて下さい。例えばとても長いページの下段に画像があると推測されるような場合です。Intersection Observerによって利用者はスクロールで下がる正に途中から画像を読み込めるのです。 原文 Consider using an IntersectionObserver to intelligently determine when to lazy-load offscreen images. For example, suppose you have some images at the bottom of a very long page. With an IntersectionObserver, you can load the images only when the user has scrolled halfway down the page. See Intersect all the things! for more on this approach. オフスクリーン画像|Tool for Web Developers(訳出)|Google Developers なぜかの詳細はさらにIntersectionObserver's Coming into View(Intersection Observerが視野に入れる)で、示されている。 従来、JavaScriptでもスクロールイベントの引き上げか周期タイマーを使うか、あるいはgetBoundingClientRect()を呼んで座標系(要素の寸法やビューポートへの位置取り)から処理していて何れもブラウザがページを再配置するために無駄を出してしまって画像の遅延読み込みを改善する方法にせよ、結果は悲劇的に遅かったといわれる。 この可視性テストのもっと効果的な遂行がIntersection Observerの企図された目的で、Chrome 51(この記事の時点ではβリリースです)が開始しました。Intersection Observerはいつ監視された要素がブラウザのビューポートへ出入りするかを教えてくれます。 原文 Making this visibility test more efficient is what IntersectionObserver was designed for, and it’s landed in Chrome 51 (which is, as of this writing, the beta release). IntersectionObservers let you know when an observed element enters or exits the browser’s viewport. IntersectionObserver's coming into view|web.dev(訳出)|Google Developers JavaScriptのIntersection Observerは新しい。Chrome51で開始されたのはCan I use…によると2016年5月25日だから三年近く経っているにせよ、従来の方法で避けられなかったブラウザの動作上の無駄を削ぎ落としてそれこそ画像の遅延読み込みに特化したプログラムを単純明快にも実現しているわけだった。聞くやサイト作成に取り入れたいと願う。 ただし検索エンジンのクローラーが一時的でも表示されない像を読み取ってサイト評価に好影響を与えるかどうかは良く分からないので、さらに調べてみるとGoogleが公式の発言を行って画像の遅延読み込みにJavaScriptのIntersection Observerを使用するサイト作成を推奨する情報を掴んだから大分と安心できた。 サイトのページ上のコンテンツがすべて確実に Googlebot で認識されるようにするには、遅延読み込みを実装する際、IntersectionObserver API と Polyfill を使うことにより、どの関連コンテンツも、ビューポートに表示できる場合に必ず読み込まれるようにします。 遅延読み込みコンテンツを Google が認識できるようにする|Google Developers 画像の遅延読み込みはサイトの表示速度を高めるから便利で良いと思うし、アクセスアップに繋がるはずなのに検索エンジンに把握できないためにサイト評価を上げられず、SEO対策に不利では反対にアクセスダウンに陥り兼ねないのでは手が出せない。 Googleが推奨するかぎり、もはや心置きなく取り入れるかぎりだ。 追記:2019年5月からGoogleのクローラーがChromeブラウザと同等のレンダリングエンジンを搭載してサイトのIntersection Observerの読み取りが可能になった(Googlebot が常に最新のレンダリング エンジンをサポートするようになります)からサイト評価への好影響を明らかに期待できる。 JavaScriptのIntersection Observerでの画像の遅延読み込みの設置法 intersectionRatio by Google Developers / CC BY ブラウザのビューポートへの要素の出入り、すなわちデバイスの画面の中にコンテンツがあるかないかを判定するために使われるのがIntersection Observer APIで、何等かの仕方でJavaScriptのプログラムに組み込めばサイトのまだ表示されない画像を初めて表示される時点から普通よりも遅延して読み込ませるようにできる。 IntersectionObserverのプログラムのアウトライン var io = new IntersectionObserver( entries => { console.log(entries); }, { /* デフォルトのオプションを使用。詳細は以下 */ } ); // 要素の監視を開始する io.observe(element); // 要素の監視を停止する // io.unobserve(element); // IntersectionObserverを完全に停止する // io.disconnect(); 原文var io = new IntersectionObserver( entries => { console.log(entries); }, { /* Using default options. Details below */ } ); // Start observing an element io.observe(element); // Stop observing an element // io.unobserve(element); // Disable entire IntersectionObserver // io.disconnect(); 出典:IntersectionObserver's coming into view|Google Developer(訳出) オプションが記載されないデフォルトの場合の要素はブラウザのビューポートと少しでも交差するときと完全に離れるときにコールバックを行う。 もしも必要ならば複数の要素でもobserve()で呼んで同一のIntersectionObserverのインスタンスに何回でも使い回せるだろう。 コールバックに渡されるentriesの項目はIntersectionObserverEntityのオブジェクトを配列で有する。 IntersectionObserverEntityの七つのプロパティ var calledback = function(entries, observer) { entries.forEach(entry => { // 各entryは監視された一つの交差の変化を示す // 対象となる要素: // entry.boundingClientRect // entry.intersectionRatio // entry.intersectionRect // entry.isIntersecting // entry.rootBounds // entry.target // entry.time }); }; 原文var calledback = function(entries, observer) { entries.forEach(entry => { // Each entry describes an intersection change for one observed // target element: // entry.boundingClientRect // entry.intersectionRatio // entry.intersectionRect // entry.isIntersecting // entry.rootBounds // entry.target // entry.time }); }; 出典:Intersection Observer|MDN(訳出) IntersectionObserverEntityはIntersectionObserverのコールバックへの入力かIntersectionObserver.takeRecords()を呼び出すかで得られる。 Intersection Observerは交差の変化を非同期に捉えるけれどもコールバックはメインスレッドで為される。なるべ早く動作する必要があって時間を要する処理が求められるならばrequestIdleCallbackメソッドを使うと良いらしい。コールバックの呼び出しの優先度が下がり、ブラウザの待機時間に処理が行われるようになる。 boundingClientRect監視された要素の矩形/getBoundClientRect()による寸法やビューポートへの位置取りintersectionRatio可視化された要素の内部的な割合intersectionRectrootと要素の二つの矩形が交差したところの矩形isIntersecting可視化された要素があるかないかの真偽値rootBoundsrootの矩形/初期値はブラウザのビューポート自体のgetBoundClientRect()による寸法やビューポートへの位置取りtargetrootと交差して可視化する要素を指すtimeファイルの読み込みから交差するまでのDOMHighResTimeStamp型の時間 Intersection Observerの三つのオプション JavaScriptのIntersection Observerにはオプションが三つ付いていて固有の範囲と対象が交差する判定の仕方を調節できる。 root: null/例_document.query.selector("name") 判定の領域を指定する:サイトに別窓のコンテンツをスクロール付きで配置するような場合に役立つ/デフォルトはブラウザのビューポートだ。 rootMargin: "0px"/例_"0 0 64px 0" 判定の範囲を指定する:要素の上下左右を交差するrootの端よりも大小とずらして発動させられる/デフォルトは「0px」だ。単位はpxか%を使って常に省略しない。%はrootの割合なので、オプションからrootを指定して親ボックスの大きさが確定しない場合は動作しない。値の入力の仕方は一つで上下左右、二つで上下と右左、三つで上下と右と左、四つで上と右と下と左になる。追記:値は「0」でもpxや%の単位なしでは動作し難いかも知れない。又、複数の入力は上手く反映しない場合がある。 threshold: 0/例_[0, 0.5, 1.0] 判定の割合を指定する:要素がrootの端とどのくらい交差したら発動するかを0から1まで分割して決められる/デフォルトは「0」だ。値は要素の内部的な割合で、最大の1で全体が閾値(rootと交差済みの状態)として扱われる。 ※全体は半角波括弧({})に入れて一つ以上を設定する際は半角コンマ(,)で区切って記載する。 スクロールで画像を赤から青へ切り替えるサンプル 半分以上が見えると赤から青に変わる 半分以上が見えると赤から青に変わる HTML <figure id="ioa"> <p>半分以上が見えると赤から青に変わる</p> <img class="iom" src="画像URL(赤)" data-src="画像URL(青)"> <p>半分以上が見えると赤から青に変わる</p> </figure> CSS #ioa {margin:0 auto;text-align:center;overflow:scroll;border:2px #c0c0c0 solid;height:min((100vw - 24px) * 9 / 16, 360px);width:min(100vw - 24px, 640px)} #ioa p {margin:3em 0} JavaScript var elm = document.querySelector("img.iom"); var dim = elm.src; var io = new IntersectionObserver( entries => {entries.forEach(function(entry) { if (entry.isIntersecting) { entry.target.src = entry.target.dataset.src; } else { entry.target.src = dim; }}); }, { root: document.querySelector("figure#ioa"), rootMargin: "0px", threshold: 0.5 } ); io.observe(elm); サイトの可視化を監視したいコンテンツをdocument.querySelectorメソッドなどで取り込んでおいてobserveメソッドの引数としてIntersectionObserverへ放り込んでインスタンスを与えると仕込まれた任意のプログラムの実行結果が一つの戻値として得られる。 サイトの画像の遅延読み込みに無料で使える二つのプログラム JavascriptのIntersection Observerの方法でサイトに画像の遅延読み込みを実装するには監視する要素についてHTMLの画像のimgタグの画像URLを記載するsrc属性を予め空にしておいて通常はブラウザに表示されないdata-src属性に代わりに記載しておいたのを後から移動させるようにするのが一般的な方法なんだ。 entry.target.src = entry.target.dataset.src; JavaScriptでなくては画像が表示されなくなってしまうので、どんな場合でも表示するためにはHTMLのnoscriptタグで代替画像も一緒に載せるべきだ。 サイトで画像の遅延読み込みを取り入れるにはもっとパフォーマンスを高めたり、他の便利な機能を付けたりできるのが良いと思う。巷に無料で使える優れたプログラムが提供されているので、簡単な使い方を含めて紹介しておきたい。 Jeremy Wagnerのスクリプト(Google Developers) 簡潔なソースコードで、しかも要素の取得や監視の切り替えやフォールバック(Intersection Observer APIが使えないブラウザのための設定が可能だ)など、サイトで画像の遅延読み込みを的確に行えるプログラムなので、非常に洗練されているというか、気に入って僕も使っている。 document.addEventListener("DOMContentLoaded", function() { var lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); if ("IntersectionObserver" in window) { let lazyImageObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { let lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.srcset = lazyImage.dataset.srcset; lazyImage.classList.remove("lazy"); lazyImageObserver.unobserve(lazyImage); } }); }); lazyImages.forEach(function(lazyImage) { lazyImageObserver.observe(lazyImage); }); } else { // Possibly fall back to event handlers here } }); 出典:Lazy-loading images|web.dev プログラムはApache 2.0 Licenseで提供されていて著作権はJeremy Wagnerにあるけれどもこの場合は作者名とライセンスの表記と共にどんなサイトでも改変可能で無料で使用して構わない。 /* Copyright Jeremy Wagner and Rachel Andrew 2020 | Apache 2.0 License | https://web.dev/lazy-loading-images/ */ 他人がホームページやブログに取り入れる場合はソースコードの冒頭に作者名とライセンスのコメントを付けておくのが適法だ。 使い方は遅延読み込みを求める画像のimgタグに「.lazy」のclassを付ける。そしてimgタグの画像URLのsrc属性をdata-src属性、あればsrcset属性もdata-srcset属性へ書き換える。さらにスクリプトのソースコードの全体をscriptタグの<script></script>で囲ってサイトのbodyの閉じタグの</body>の上の近くなどに記載する。すると当該の画像の遅延読み込みがプログラムに従って動作する。 カスタマイズはIntersection Observerのオプションが使える。 let lazyImageObserver = new IntersectionObserver(function(entries, observer) { // Lazy loading image code goes here }, { rootMargin:"0px 0px 256px 0px" }); 出典:イメージと動画の遅延読み込み|Web Fundamentals 全体のスクリプトでは終わり頃の「lazyImages.forEach」の前の「);」の前がIntersection Observerのオプションのスペースになっている。直前に新しく半角コンマ(,)を打たなくてはからないからプログラムを挿入するだけでは上手く行かない。スペースの前の「}」の次に半角コンマを打って区切ってからオプションのプログラムを配置すると大丈夫だ。 他にフォールバックを設定できるのが有り難い。現在は大半のブラウザが対応済みとはいえ、もしもIntersection Observerが新しくてまだ動作しなければ画像が表示されないので、代替用のプログラムを記載しておくのが望ましい。フォールバックは一行コメントの「// Possibly fall back to event handlers here」(あるいはイベント処理へのフォールバックはここ)の部分に記載する。必要なければelse { // Possibly fall back to event handlers here }を削除して構わないけれども波括弧にプログラムを配置する。 lazyImages.forEach(function(lazyImage) { lazyImage.src = lazyImage.dataset.src; lazyImage.srcset = lazyImage.dataset.srcset;}); JavaScriptで画像URLを非表示のdata付きの属性から表示のdataなしの属性へ切り替えてサイトのソースコードを画像の遅延読み込みを取り入れない状態へ戻している。 公開元のweb.devのイメージと動画の遅延読み込みにはIntersection Observer APIが使えないブラウザとの互換性や背景画像や動画の遅延読み込みやプレースホルダー画像(非表示用)の使い方やJavaScriptがない場合の対処法なども取り上げられている。 追記:元のページが移動されてIntersection ObserverについてはLazy-load images and videoに様々な遅延読み込みの方法と共に再構成された。 lozad.js:Apoorv Saxenaのライブラリー(GitHub) JavaScriptだけの軽量なライブラリーで――バージョン1.9.0は2.33KB/gzip圧縮で1.04KBしかない――Intersection Observer APIを使ったスムーズな画像の遅延読み込みを実現している。 GitHubで公開されていてライブラリーはサイト作成がNode.jsならばlazad -npmでインストールするか、その他はlazy.jsやlazad CDN by jsDelivrでscriptタグを貰ってHTMLのheadの閉じタグの</head>>の上の近くなどに記載する。 プログラムはThe MIT Licenseで提供されていて著作権はApoorv SaxenaJeremy Wagnerにあるけれどもこの場合は作者名とライセンスの表記と共にどんなサイトでも改変可能で無料で使用してかまわない。 loyad.jsはライブラリーに全て記載されているので、サイトに取り入れながら特に何もする必要はないと思う。 使い方は遅延読み込みを求める画像のimgタグに「.lozad」のclassを付ける。そしてimgタグの画像URLのsrc属性をdata-src属性、あればsrcset属性もdata-srcset属性へ書き換える。さらに「.lozad」のインスタンス化のためのプログラムをscriptタグの<script></script>で囲ってサイトのbodyの閉じタグの</body>の上の近くなどに記載する。 デフォルトのソースコード const observer = lozad(); observer.observe(); DOMの要素を参照する場合 const el = document.querySelector('img'); const observer = lozad(el); observer.observe(); ※HTMLの「img」で監視対象のインスタンス化を行う。他のDOMの要素の「div」などへの書き換えや追加が可能になる。 オプション付きのバージョン const observer = lozad('.lozad', { rootMargin: '0px', threshold: 0 }); observer.observe(); 三つの仕方のどれかでobserveメソッドを発動すると当該の画像の遅延読み込みがプログラムに従って動作する。 カスタマイズはlozad.jskに必須の要素のインスタンス化のスクリプトの例えばlozad()の部分などに他のプログラムを追加して行う。 交差中の関数定義の変更 const observer = lozad('.lozad', { load: function(el) { console.log('loading element'); el.src = el.getAttribute('data-src'); } }); observer.observe(); ※デフォルトの画像の切り替えも解除される。 監視する要素を拡張する const observer = lozad('.lozad', { loaded: function(el) { el.classList.add('loaded'); } }); observer.observe(); ※デフォルトの画像の切り替えは解除されない。 先読みの画像を指定する const observer = lozad(); observer.observe(); const coolImage = document.querySelector('.image-to-load-first'); observer.triggerLoad(coolImage); ※表示されなくてもブラウザが読み込んで交差したら直ぐに表示できるようにする。HTMLのimgタグに「.image-to-load-first」のclassが付いた画像一枚が対象になる。 公開元のGitHubのApoorvSaxena/lozad.jsには画像全般のpictureタグや他のページから取り込むiframeタグでのコンテンツの遅延読み込みなども取り上げられている。 参考サイトIntersectionObserverこれなら簡単で便利!要素がビューポートに表示されているかを判定できる -Intersection ObserverIntersectionObserverで要素が画面内に入ってきたかを判定するIntersection Observerで要素が画面内に入ったときにアニメーションや自動スクロールをスタートするIntersection Observer を用いた要素出現検出の最適化 コメント 新しい投稿 前の投稿
細川慎二のどうにも泣けて来てしまうストリートライヴのアルトサックス サックス奏者の 細川慎二 のYouTubeチャンネルの Sax in the Night City で出ているサックスのストリートライヴの動画が美しい音色と相俟った街角の雰囲気の良さで心底と泣けて来るほどの感動を催させる。 細川慎二のアルトサックスの美しい音色が響き渡る街角の...
宜保愛子は本物の霊能力者だと考えられる三つの真実 昭和から平成にかけてテレビや雑誌で何度も大きく取り上げられて物凄く活躍した霊能力者の 宜保愛子 がいた。何気なく昔のテレビ番組を観ていたら霊視は嘘だったと思えない内容で、本当にびっくりした。昔、そんなに引き付けられて観ていたわけではないし、改めて霊能力が本当かどうかを確かめようと...
平田監督の白井球審の誤審への抗議はパワハラへの強力な対処法に他ならない 日本プロ野球で 佐々木朗希が完全試合を実現して 次の試合も八回まで無安打と無失点の状況で、次の試合はどうかと注目した4月24日の対オリックスバファローズ戦は初回の先頭打者の初球にヒットを打たれて五回に二失点を喫して連続の無安打と無失点が両方とも途絶えてしまった。 しかし予想外...
アドセンスのGDPRに日本でも対応しなくてはならない場合がある アドセンスの個人情報のCookieなどの使用に関してサイトの訪問者に同意を得なくてはならない法律としてEU(European Union/欧州連合)の GDPR (General Data Protection Regulation/EU一般データ保護規則)がある。外国の個人情報...
伊良部秀輝が自殺した原因はミッドライフクライシスによる鬱と飲酒だと考える プロ野球選手の 伊良部秀輝 が自殺したと知ってショックを受けたことがあった。もう十年以上前になる。2011年の夏、享年四十二と早過ぎたのに加えて大好きな投手の一人だったので、とても残念に感じた。 目次 伊良部秀輝が大好きだった記憶 負けても自分のスタイルを貫き通した 野球への...
玉置浩二のメロディーは涙腺緩んで総毛立つ名曲中の名曲だ 玉置浩二 のYouTubeの公式チャンネルで、最も気に入りの メロディー のライブ版が追加されていた。曲自体をちゃんと聴いたのは約二十五年振りかも知れないけど、しかし初めての内容から以前にも況して大変な感動を覚えることになった。 玉置浩二 『メロディー』Live at Tok...
日本人がジャニーズ事務所で行われた性加害よりも恐れていること イギリスの公共放送のBBC(British Broadcasting Corporation/英国放送協会)が日本のジャニーズ事務所の創業者の ジャニー喜多川 の性加害について取り上げたドキュメンタリーの J-POPの捕食者:秘められたスキャンダル に衝撃を受けた。 目次 ジ...
Imgurで画像URLと埋め込みコードを取得する方法 Imgur は自分でアップロードした画像については画像URL/直リンクを取得して他のサイトにHTMLのimgタグで表示させられる。 そして自分と他の人たちも含めて画像の埋め込みコードを取得して他のサイトのHTMLに、そのまま、記載して表示させられもする。 目次 Img...
沖雅也の涅槃への自殺と双極性障害 かつて俳優の 沖雅也 の自殺が伝えられたとき、遺書の言葉とされた「おやじ、涅槃でまっている」と共に何なのかと疑問を感じたのを良く覚えている。聞き慣れない「涅槃」という言葉が入っても何十年も過ぎた今振り返っても自殺者の遺書として本当に珍しい表現だったと改めて驚く。 沖雅也が書い...
生島浩の5:55の心の目に光り輝く尊さ 日本の ホキ美術館 は日本人の画家の写真のように細密に描かれた写実絵画を中心的に所蔵している。その中で、絵を印刷したポストカードの売り上げがホキ美術館の設立当初から一位で、常に最高の人気を誇るのが生島浩の 5:55 (五時五十五分)といわれる。僕も一見して忽ち引き付けられる物凄い...
コメント