先日とあるサイトでGoogle Search Consoleの「ウェブに関する指標」を確認したところ、「CLSに関する問題」のレポートで不良が多数発生していることに気づきました。

CLS(Cumulative Layout Shift)とはUXのコアウェブバイタルの指標の一つで、ページの読み込み中に起こるレイアウトの移動量(がたつきの大きさ)を示します。

(キャンセルボタンを押そうとしたら読み込み中だったバナーが突然現れ、結果その分ボタンが下に移動してしまい、同意するボタンを誤って押してしまった図解です。似たような経験ありませんか?)
以下のページ内にある動画を見ていただければCLSの概要が掴めるかと思います。
web.dev – https://web.dev/cls/
詳しく調べたところページ上部に設置しているカルーセルのimg要素にheightを指定していないことが原因とわかりました。
対策としてはこのimg要素のheightを固定値にすればいいのですが、レスポンシブサイトの場合、srcsetを使用してアスペクト比の違う画像を差し替えている場合はwidth, heightの値は可変(%指定など)にする必要があり、固定値するとレスポンシブデザインに不都合が起きます。
そこで親要素のpadding-topに画像のアスペクト比の値を設定することでimg要素のheightの値を固定することなくCLS対策することがきました。
<div class="embed-responsive-variable-ratios">
<a href="#">
<!-- srcsetで画像を差し替える。ピクセル比2倍以上またはデフォルトは縦画像を表示、その他は縦画像表示 -->
<img src="https://placehold.jp/750x1334.png" srcset="https://placehold.jp/1366x768.png 1x, https://placehold.jp/750x1334.png 2x" alt="レスポンシブ画像">
</a>
</div>
.embed-responsive-variable-ratios a {
display: block;
position: relative;
height: 0;
overflow: hidden;
}
.embed-responsive-variable-ratios a img {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
@media screen and (orientation: portrait) { /* 縦画面 */
.embed-responsive-variable-ratios a {
padding-top: calc(1334 / 750 * 100%); /* 縦画像の上に内余白 (縦画像の縦サイズ ÷ 画像の横サイズ × 100%) */
}
}
@media screen and (orientation: landscape) { /* 横画面 */
.embed-responsive-variable-ratios a {
padding-top: calc(768 / 1366 * 100%); /* 横画の上に内余白 (横画像の縦サイズ ÷ 画像の横サイズ × 100%) */
}
}