WordPress5.5からNative Lazylodに対応しました。同時に、Wordpressの機能を使って追加された画像には自動的にwidthとheightが追加されるようになりました。これはNative Lazyload実行時にimgタグにwidth/heightを追加することでCLSを悪化させないための対策になっています。
ところがCocoonの吹き出しブロックのアイコンにはwidthとheightの指定がありません。その影響でLazyload有効時にレイアウトシフトが発生してCLSが悪化する場合があります。
この記事では、Wordpress 5.5以上になってもimgタグにwidthとheightが追加されない要素に対して独自にwidthとheightを追加するカスタマイズをご紹介します。
Cocoonの吹き出しブロックのアイコンにwidthとheightが設定されない理由
WordPress5.5以降でimgタグにwidth/heightが自動的に追加される条件は?
WordPressの該当部分のソースコードを確認します。
条件:imgタグのclassにwp-image-{画像ID}が追加されているかどうか
imgタグのclassにwp-image-{画像ID}が追加されている場合に、widthとheightが自動的に追加されます。
WordPressでは、画像のwidthとheightを取得する時に画像IDを使用します。HTML内に画像IDがわかる情報としてwp-image-{画像ID}を使用しているので、それが無いものは対象外としているようです。
なので、wp-image-{画像ID}のclassが追加されていないimgタグはwidth/heightの追加対象外になっています。
ブロックエディタで画像を追加している場合は、wp-image-{画像ID}が自動的に追加されますので問題ありませんが、テーマやプラグインの独自機能などで挿入される画像にwp-image-{画像ID} classが無いものがあるとwidth/heightが追加されません。
Cocoonの吹き出しブロックのHTML
WordPress5.5以降のimgタグへwidth/heightを自動追加する条件(wp-image-{画像ID}がclassにある)に合致していません。
<div class="speech-wrap sb-id-9 sbs-stn sbp-l sbis-cb cf">
<div class="speech-person">
<figure class="speech-icon"><img loading="lazy" class="speech-icon-image" src="https://xxxx.com/wp-content/uploads/2019/02/man.png" alt="" data-ll-status="loaded"></figure>
</div>
<div class="speech-balloon">
<p>吹き出しの内容</p>
</div>
</div>
これは吹き出しブロックで画像を参照するときにDBの画像IDを見ていないので、classが追加されないためです。
WordPressの仕組みでwidth/heightを追加するならwp-image-{画像ID} classを追加することになります。
そうでない場合は、widthとheightを自分で追加することになります。
カスタマイズコード
WordPressの仕組みと同じようにフックを使ってimgタグのwidth/heightを追加するカスタマイズを行います。
考え方はシンプルで、wp-image-{画像ID}の代わりに、speech-icon-imageを検索して、widthとheightは決め打ちで100にしているだけです。
add_filter( 'the_content', '_image_dimensioning_filter_content_tags' );
add_filter( 'the_excerpt', '_image_dimensioning_filter_content_tags' );
add_filter( 'the_category_content', '_image_dimensioning_filter_content_tags' );
add_filter( 'the_category_tag_content', '_image_dimensioning_filter_content_tags' );
//add_filter( 'widget_text_content', '_image_dimensioning_filter_content_tags' );
/**
* Filters specific tags in post content and modifies their markup.
*
* @param string $content The HTML content to be filtered.
* @param string $context Optional. Additional context to pass to the filters. Defaults to `current_filter()` when not set.
* @return string Converted content with images modified.
*/
function _image_dimensioning_filter_content_tags( $content, $context = null ) {
if ( null === $context ) {
$context = current_filter();
}
if ( false === strpos( $content, '<img' ) ) {
return $content;
}
if ( ! preg_match_all( '/<img\s[^>]+>/', $content, $matches ) ) {
return $content;
}
$images = array();
foreach ( $matches[0] as $image ) {
if ( preg_match( '/speech-icon-image/i', $image) ) {
$images[ $image ] = 1;
continue;
}
$images[ $image ] = 0;
}
foreach ( $images as $image => $attachment_id ) {
if ( $attachment_id ) {
$size = array();
$filtered_image = $image;
if ( false === strpos( $filtered_image, ' width=' ) && false === strpos( $filtered_image, ' height=' ) ) {
if ( preg_match( '/src\s*=\s*[\"|\'].*?-([0-9]{2,4})x([0-9]{2,4})\.(jpe?g|png|gif)[\"|\']/i', $image, $s ) ) {
$size = array( $s[1], $s[2] );
} else {
$size = array( 100, 100 );
}
if ( $size ) {
$filtered_image = str_replace( '<img', '<img width="' . $size[0] . '" height="' . $size[1] . '"', $filtered_image );
$content = str_replace( $image, $filtered_image, $content );
}
}
}
}
return $content;
}
width:100%が指定してある場合、width/heightはアスペクト比があっているのであれば重要ではありませんので、100じゃなくても何でも大丈夫です。
まとめ
Cocoon公式サイトでは吹き出しブロックはLazyload対象外になっていて今回の様なwidth/heightの問題は出ていません。Lazyload対象にしたい人は、width/heightは必須なのでご自分で追加しましょう、というカスタマイズでした。