レスポンシブ対応時にも画像の表示場所をあらかじめ確保することで、画像の遅延読み込み時 (Lazy loading) に再レンダリングされるのを防止して画面がチラつくのを回避する方法をまとめました。
目次
レスポンシブ画像の遅延読み込みで高さが指定されていない場合再レンダリングされてしまう原因
去年画像の lazySizes というライブラリを使って遅延読み込み (Lazy loading) に対応しました。
レスポンシブ対応の画像を遅延読み込みすると、スクロールなどで後から読み込んだ画像を表示するとき、ページ全体が再レンダリングされてチラついてみっともないです。また記事に目次を作っているとリンクをクリックしたとき、ページ内を移動するのだけれど、まだ読み込んでない画像がある場合、ジャンプ後の位置が画像を読み込むと変わるため、意図した所にジャンプしてくれないなどの問題点がありました。イメージとしては下記のアニメーションのような感じです。
なぜそうなるかというと画像をレスポンシブデザインに対応させるには以下のような CSS を指定して、画面サイズに合わせて画像の大きさを変化させます。
このとき height が auto になっているため、画像が読み込まれていない状態ではブラウザは高さがわからないため、高さを 0 として一度レンダリングします。そして画像が遅延読み込みされたときに画像の高さが初めてわかるので、それを元に再度レンダリングを行うので画面がチラつくのです。
そこで以下のサイトを参考にして記事内にどんな大きさの画像が配置されても、レスポンシブデザインにおいても画像が表示される場所を確保することにしました。
→ Davide Calignano : Lazy loading with responsive images and unknown height
施策後のイメージは以下のアニメーションのような感じです。
画像遅延読み込み時に画像の表示スペースを確保する基本的な考え方
基本的な考え方は次のとおりです。
img タグのひとつ外側の a 要素に height を 0 にして padding-bottom を画像の縦横比(アスペクト比)で設定して余白を確保します。
padding-bottom = ( 高さ ÷ 横幅 ) × 100 (%);
padding-bottom は % で指定した場合、親要素の横幅を基準にするので、 a タグをさらに div で囲みこれに幅を指定します。囲った div タグの幅がすべて同じなら CSS ファイルで width を指定すればいいですが、横幅が画像によって変わる可能性があるので style 要素でタグ内に埋め込むことにしました。 width で指定した値よりこの div 要素の表示領域の横幅が狭い場合に備えて max-width: 100%; もつけ加えます。
そして a タグの左上を基準にして画像を絶対位置にて表示させます。このとき width と height は 100% と指定して、親要素である a タグいっぱいに広がるようにします。
これなら画面サイズによって画像の大きさを変化させても、画像のスペースがきちんと確保されており、かつ画像は絶対位置で表示されるので再レンダリングされません。
HTML コード
HTML コードはこんな感じになります。(見やすいように改行を入れました。)
CSS コード
CSS はこんな感じです。
WordPress で対応する場合の関数
WordPress でメディアライブラリから画像を貼りつけるときにコードを自動的に改変する関数を作りました。
WordPress では wp_make_content_images_responsive() という関数を the_content にフィルターフックすることで、 srcset 属性や sizes 属性をつけ加えてレスポンシブ対応の img タグに書き換えています。
それにならって必要な style 属性を追加する関数を作成しました。コンテンツの中から <a><img></a> という部分の HTML タグの配列を作って、それぞれの width と height の値を正規表現で検索し、コールバック関数でタグ書き換えています。
image_send_to_editor のフックを使って、編集画面に挿入するときに書き換えようかと思ったのですが、前の記事にも対応できるように the_content を使いました。
このコードを function.php に書き足すと上に書いた HTML コードが出力されます。クラスに lazyload を追加する関数に組み込んだ方が効率的かもしれません。わたしは画像を Google Photos に置いているのでこのコードは使ってはいませんが参考までに。






