【JetTheme】LazyLoad時に縦長画像がぼやける問題を解決【Blogger】

本サイトには、広告あるいはアフィリエイトプログラムによるアソシエイトリンクが含まれる場合があります。

本ブログで使用しているBloggerテーマ「JetTheme」には遅延読み込み機能が組み込まれています。しかし、この遅延機能を使ってBlogger内の縦長画像を読み込むと実際の表示時に画像がぼやけてしまうことがあります。

この問題について意外と簡単に修正できたので紹介します。

症状

JetThemeの画像遅延読み込み機能(<noscript>で囲む方法やclass="lazyload"+data-src=を使う方法)[1]を使うと単純に画像を遅延読み込みするだけでなく、画像URLを書き換えてWebP形式に変換したり表示ディスプレイのデバイスピクセル比(DPR)に合わせて最適にリサイズしたりしてくれます(Blogger内画像のみ対象)。

しかし、縦長画像では表示領域より小さくリサイズされてしまい、引き延ばされぼやけてしまうことがあります。

以下は同じ縦長画像を並べて表示したスクリーンショットです(左はBloggerに挿入したそのままで表示した画像、右はJetThemeの遅延読み込み機能を使って表示し余計にぼやけてしまったもの)。

同じ縦長画像を通常表示したものと遅延読み込みしたものの比較スクリーンショット
通常表示した場合と遅延読み込みした場合の比較

原因

画像URLを書き換えるリサイズ機能にて、サイズを指定するURLパラメータとしてs#が使われており、これがぼやけの原因でした。

s#は画像のアスペクト比を維持しつつ長辺#pxでリサイズするパラメータです[2]。JetTheme内のスクリプトでは(おそらく)全て横幅基準で必要な画像サイズを計算しているのですが、縦長の画像ではs#によって意図せず高さ基準でリサイズされてしまい結果として横幅の解像度が足りずぼやけて表示されてしまうようです。

これを、横幅#pxを指定するパラメータw#[2]に変更することで問題を回避することができました。[3]

修正方法

以下ではテーマHTML(xml)を直接編集するので事前にバックアップを取ることをおすすめします。なお、以下に掲載するコードは素のJetTheme v2.9 (jettheme-v2.xml) のものです。既にカスタマイズ済みの場合、行番号は適宜読み替えてください。

外部スクリプト(jettheme/js@0.5.5/main.js)の編集

Bloggerの管理画面から「テーマ」→「HTMLを編集」を開き、以下のコードを探します(2515行目付近)。

<script src='https://cdn.jsdelivr.net/gh/jettheme/js@0.5.5/main.js'/>

このURL(https://cdn.jsdelivr.net/gh/jettheme/js@0.5.5/main.js)にブラウザでアクセスし、表示されたコードを全てコピーします。

コピーしたコードをテキストエディタ(メモ帳など)に貼り付け、検索機能(Ctrl+F)で"s"を検索し、"w"で置換します(一カ所のみ)。

"s"置換前後の周辺のコードは以下のようになっているはずです。

↓置換前
... ?"w"+cN+"-h"+i+"-c"+au:"s"+(cH=cN<30?cL<30?cM:cL:cN)+au, ...
↓置換後
... ?"w"+cN+"-h"+i+"-c"+au:"w"+(cH=cN<30?cL<30?cM:cL:cN)+au, ...

スクリプトのインライン化

BloggerのテーマHTML編集画面にて、先ほどの<script src='...'/>の部分を削除し、代わりに先ほど置換・修正したコードを以下の形式で貼り付けます。

<script>/*<![CDATA[*/
置換・修正したコード全体をここに貼り付ける
/*]]>*/</script>

これで保存すれば完了です。実際の表示で遅延読み込みさせた画像URLのパラメータ部分がw#-rwに書き換わるか、画像がぼやけていないか、表示領域より解像度の低い画像になっていないか確認してみてください。

以下は、上述したスクリーンショットと同じ記事・画像部分にて、スクリプト修正後にページをリロードし撮ったスクリーンショットです。

同じ縦長画像を通常表示したものと修正したスクリプトで遅延読み込みしたものの比較スクリーンショット
通常表示と遅延読み込み(修正版)との比較

DPRに応じて表示領域に対し適切なサイズの画像に書き換えられるため、遅延読み込みした右側の画像の方がより鮮明に表示されています。

おまけ(defer.jsのアップデートと圧縮パラメータ)

JetThemeの遅延読み込みはdefer.jsというライブラリに依存していますが、オリジナルのJetThemeの更新は何年も止まっておりdefer.jsは古いバージョン(v.2.5.0)のままになっています。

そこで本ブログでは以下の記事を参考にdefer.jsをバージョンアップして使っています。

最新のDefer.jsをJetThemeで使用する方法 - after work lab

参考記事の方法でjettheme/js@0.5.5/main.jsを既にインライン化している場合でも同様に"s""w"で置換すればOKです。

さらに参考記事でインライン化したスクリプトでは画像URLパラメータに-e365を2カ所追加しブラウザーのキャッシュ有効期間を延長していますが、本ブログではさらに圧縮に関するパラメータl#loを追加し以下のようにしています。

... ?"w"+cN+"-h"+i+"-n"+au+"-lo-l80-e365":"w"+(cH=cN<30?cL<30?cM:cL:cN)+au+"-l60-e365", ...

2カ所のうち前方はトップページ記事カードや関連記事などのサムネイル用、後方は記事本文内画像用です。

l#は画像品質を#の値1~100で指定します。出力先がロスレス方式になる場合(PNGや元PNGをURLパラメータrwでWebP化したもの)は無視されます。loを付けると非可逆(ロッシー)圧縮を強制できますが、視覚的劣化が大きくなるため品質値に注意が必要です。画像によりますが、元が非可逆圧縮の出力(JPEGや元JPEGのWebP)ではl60程度まで品質を落としても劣化が目立ちにくい一方、元がロスレスの画像にloを使うとl80付近から劣化を感じやすくなります。※JetThemeの遅延読み込みではパラメータrwでWebP画像に書き換えられるため、出力先のロスレス/ロッシーは元画像の形式に依存します。[2]

これらをふまえ、以下のような意図でパラメータを決めています。

  • サムネイル用:見た目の劣化を許容し、全ての画像を非可逆圧縮し容量削減。
  • 記事本文用:劣化が目立ちにくい画像(元JPEGなど)のみ圧縮。圧縮率はやや高め。
【AD】弓木奈於さんを応援しています
Previous
まだコメントはありません
コメントする
コメントの投稿者IDについて:匿名でもOKですが、名前/URLで何らかの名前を設定していただくと他の匿名さんと区別がつきありがたいです。URLは空欄で構いません。
comment url