Coding Memos

try {coding} catch {questions}

wordpressにおけるレスポンシブイメージに対するlazyload対策

wordpressアイキャッチを出すときに、lazyloadしたいっていう話。

<img src="hoge.jpg" alt="" >

は慣れ親しんだ記述だが、HTML5.1となると、レスポンシブイメージの書き方が、標準装備となる。

<img srcset="" sizes="" alt="">

srcsetでは、画像が複数リストとして記述される。sizesはどの範囲のviewportで、どのサイズの画像をつかうかということを示す。

まぁこの辺の解説は、普段からHTML CSSを書いている人にとっては、理解できることだろうから、詳細には立ち入らない。

今回はsrcsetも踏襲した上で、lazyloadつかおうということが主題である。

lazyloadによって、ユーザーの体感速度をあげる

ページ内の下の方の画像は、ユーザーがスクロールしたらロードされればいい。

lazyloadってのはそういうものだろうし。

つかってるlazyloadライブラリは、lazySizesというもの。

github.com

デモはこっち。

lazysizes - the ultimate lazyloader for responsive images, iframes and widget

Lazy load Plugin for jQueryじゃないの?

Lazy Load Plugin for jQuery

そう、これは前に使っていたが、lazysizesがさらにいいのは、jqueryを使わなくてもいいということ。

これによって、jQuery $ is not function Reference Error なんて依存関係の必要なものではなくなるし、軽いらしかった。

使いかた

簡単

  1. 外部ソースファイルをよみこむ
  2. lazyloadしたいimgにlazyloadというclassをつける。
  3. srcsetに入れたいurlリストをはじめはdata-srcsetにいれる
  4. sizesもdata-sizesとしてデータ持っておく

たったこれだけ。

jsを書かなくても使える。

もちろんオプションとか設定はある。jquery.lazyloadのときは、画像を出す演出がjqueryによってfadeInなどしていたが、こちらでは、cssによって、opacityとtransitionなどでふわっと画像を出したりすることができる。

Wordpressは4.4からすでにsrcset sizesを導入している

たぶん今後はこの書き方を要求されることが多くなりそう。今回は論を踏み入れないけど

<picture>
  <source 
    media="(min-width: 650px)"
    srcset="images/kitten-stretching.png">
  <source 
    media="(min-width: 465px)"
    srcset="images/kitten-sitting.png">
  <img 
    src="images/kitten-curled.png" 
    alt="a cute kitten">
</picture>

という書き方もある。

レスポンシブイメージのネイティブサポート - HTML5 Rocks

画像の対応の仕方は、Web屋はキャッチアップしておかないとまずそう。

前置きはさておき、今回は、アイキャッチを出すときに、lazyloadで画像読み込みをしたかった。 なので、Wordpressのフィルターフックを利用して以下のように記述した。

function thumbnailForLazyload($html, $post_id, $post_image_id)
{
    $html = '<a href="' . get_permalink( $post_id )  . '" title="' . esc_attr( get_the_title( $post_id ) ) . '" >';
    $html .= '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" data-srcset="' .wp_get_attachment_image_srcset($post_image_id).'"';
    $html .= 'data-sizes="'.wp_get_attachment_image_sizes($post_image_id) . '" class="lazyload wp-post-image">';
    return $html;
}

add_filter('post_thumbnail_html', 'thumbnailForLazyload', 3, 10);

post_thumbnail_html はテンプレートタグのthe_post_thumbnail()を使うときのフィルターフック。

ここに、lazyloadというクラスや、data-srcset, data-sizeを書き入れて、利用する感じにした。

はじめから、srcsetに画像URLがはいってしまうと、lazyloadにならないため、data-srcsetにしてある。(この使い方自体は、lazysizesのもともとの使いかた)

srcが書き入れてあるのは、1px x 1pxの透過イメージ。ここにlow qualityな画像を入れて、レガシーブラウザ(srcsetに対応していないブラウザ)に対してはsrcの画像を読み込ませるということもできる。

その他関数など

thumbnailForLazyload($html, $post_id, $post_image_id)は三つの引数をとる。$html,$post_id ,$post_image_idはもともと、post_thumbnail_htmlで用意された引数なので、フィルターフックで使う場合は、そのまま引数を渡せばいいだけ。

post_thumbnail_html | Hook | WordPress Developer Resources

wp_get_attachment_image_sizes(), wp_get_attachment_image_srcset()は引数に、$post_image_idつまり画像のidを渡すことで、srcsetとsizesを吐き出してくれるテンプレートタグになっている。

wp_get_attachment_image_sizes() | Function | WordPress Developer Resources

wp_get_attachment_image_srcset() | Function | WordPress Developer Resources

the_post_thumbnail()のlazyload対応

上記までで、アイキャッチを吐き出す際のlazyload対応ができたはず。

ほかにも、記事内の画像をlazyloadさせるときは、

function contentImgLazyload(引数何個か) {
    //処理
}

add_filter('the_content', 'contentImgLazyload', n(引数の個数), m(この処理の優先度));

という感じで書けば行けそう。

懸念点

the_post_thumbnail()アイキャッチを吐き出させるときには、第一選択といってもいいテンプレートタグなので、このやり方がいつでも正しいかは微妙なところ。

というのも、srcsetなど使いたくないアイキャッチ(ってどんな状況かおもいつかないけど)を呼び出すときなど、柔軟性に欠ける書き方をしているわけなので、もしかしたら、もう少しいい方法があるかもしれない。

もっといい方法をご存知でしたら教えてください〜。