source要素にwidth/height属性を指定して各画像のアスペクト比の維持とCLSの改善を図る
UI開発者 橋本Google Chrome 90からsource要素におけるwidth属性、height属性の指定がサポートされました。
これまでpicture要素で表示する画像のアスペクト比は、picture要素に含まれるimg要素に指定されたwidth属性、height属性から計算されていましたが、source要素に指定したwidth属性、height属性からもアスペクト比が計算されるようになります。
width属性とheight属性を付けることで解決できる問題
Core Web Vitalsの3つ指標のうちの1つにCumulative Layout Shift、略してCLSというレイアウトシフトがどれくらい発生したかをスコアにしたものがあります。
レイアウトシフトとはページの閲覧時、ビューポート内にユーザーの操作なしで動的にコンテンツが追加されたり、画像を読み込んだ際に発生するユーザーの予期せぬレイアウトのズレのことです。
これを回避するためには、ページのリソースが完全に読み込まれるまでローディング画面を表示したり、レイアウトシフトを引き起こしているimg要素に対してwidth属性、height属性を指定する方法があります。
属性を指定しておくと画像を読み込んでいる最中でも指定された縦横のスペースが確保された状態でページが描画されるため、画像が表示された際にもレイアウトシフトが発生しなくなります。
合わせてレスポンシブに対応するためには、以下のようにCSSでスタイルの上書きが必要です。
<img src="hoge.jpg" width="1200" height="800" alt="">
<style>
img {
width: 100%;
height: auto;
}
</style>
しかし、img要素に指定したwidth属性、height属性と、CSSで指定した値に差異がある場合、初期表示時の高さとスタイル適用後の高さに差異が生まれ、結果的にレイアウトシフトが発生してしまいます。
これを解決するために、以前はpadding-topを用いたハック的なやり方でアスペクト比を維持する方法がありましたが、Chrome 79、Firefox 71、SafariのTechnology Preview Release 99などのバージョンから、img要素に指定したwidth属性とheight属性からアスペクト比をブラウザが計算してくれるようになったので、このハックを用いる必要もなくなりました。
また、今年の2月に執筆した「2021年に伸びるCSSプロパティ3選」で取り上げたaspect-ratioプロパティも全モダンブラウザで対応されれば、より明示的にアスペクト比の指定ができるようになります。
picture要素とsource要素の課題
img要素だと異なるアスペクト比の画像を画面幅によって切り替えるということができないため、代わりにpicture要素を用いる必要があります。
picture要素での指定例
picture要素は画面幅によってアスペクト比が違う画像の出し分けができるだけでなく、指定の画像形式をサポートしているブラウザとサポートしていないブラウザで拡張子を出し分けることもできます。
以下はその一例です。
<picture>
<source srcset="hoge_sp.jpg" media="(max-width: 600px)">
<img src="hoge_pc.jpg" alt="" width="1200" height="800">
</picture>
<picture>
<source type="image/webp" srcset="hoge.webp">
<img src="hoge.jpg" alt="" width="1200" height="800">
</picture>
picture要素を用いる際、同じアスペクト比である別の画像を出し分けるだけであればimg要素にwidth属性とheight属性を指定している状態でも問題はありませんでした。
しかし、source要素とimg要素で異なるアスペクト比の画像を使用する場合にはimg要素に指定したwidth属性、height属性によるアスペクト比に固定され、source要素の画像はその比率に合うように引き伸ばされる、または縮められてしまいます。
だからといって、width属性、height属性を指定しないとレイアウトシフトが発生してしまうので、source要素にwidth属性、height属性を指定して、画像ごとにアスペクト比を維持できるようにする必要がありました。
source要素にwidth属性とheight属性を適用した例
<picture>
<source type="image/webp" srcset="hoge_sp.webp" media="(max-width: 600px)" width="300" height="150">
<source type="image/webp" srcset="hoge_pc.webp" width="1200" height="800">
<img src="hoge_pc.jpg" alt="" width="1200" height="800">
</picture>
当社のTOPページのメインビジュアルにもpicture要素を使用しているので、早速source要素にwidth属性とheight属性を指定してみましたが、画面幅によって画像の切り替わりとともに、アスペクト比が指定通りに計算されていました。
今後picture要素を用いてアスペクト比の異なる複数の画像を切り替える際は、width属性、height属性をsource要素に指定しておくとよいでしょう。