HTMLのpicture要素、source要素でPCとスマホの画像を切り替える


Webサイトでは多くの画像を利用してデザインしながらコンテンツを作っていきますが、利用する画像のサイズが大きいと表示速度に影響します。
またPCやタブレット端末、スマートフォンなど多くのデバイスにあう画像を表示させたいときは、デバイス幅によって画像の切り替えが必要になります。

背景画像などでは、CSSのメディアクエリで対応できますが、HTMLのマークアップでは要素にPC用とスマホ用の両方を記述し、クラスをつけてCSSとJavaScriptで表示・非表示をコントロールするなどをして対応することもあります。
しかし、この場合は一度両方の画像を読み込んでから処理するので、Webページの表示速度に影響してしまいます。

HTMLのマークアップでは、picture要素source要素を利用することで、スムーズにPCとスマホの画像を切り替えることができます。

どのように切り分けるのか、利用方法を見ていきましょう。

デバイス幅で画像を切り替え


picture要素を利用した画像の表示では、source要素で切り分けの処理をします。

source要素ではmedia属性srcset属性を設定していきます。
media属性でメディアクエリでデバイス幅を判別し、それに応じて読み込む画像をsrcset属性で画像を指定する流れです。

HTML

  
  
  landscape photography


上記では、source要素でスマートフォンとタブレット端末のデバイス幅で画像を切り分けています。
読み込まれるのは適応するソースだけになります。すべて読み込んでから表示処理をするわけではないので、レンダリング処理に影響しません。
最後はPCのデバイス幅でimg要素が適応され読み込まれます。

また、高解像度の画像も必要になってくることもあります。
Retina対応の画素密度が高いディスプレイの場合は、2倍の画像を用意しておくことで荒れがなくキレイに表示できます。

そうした場合には、srcset属性にカンマ区切りで高解像度の画像を指定して切り分けます。
このとき半角スペースをあけて「2x」とピクセル密度と共に指定します。

HTML

  
  
  landscape photography


この画像の切り分けは、source要素でもimg要素でも利用できます。
srcset属性では対応させる画像をカンマ区切りでたくさん追加できます。

srcset属性の複数指定
srcset="画像URL1 記述子1, 画像URL2 記述子2, 画像URL 記述子3"


もっと細かく1.5xなどを用意してもいいです。
今後、8Kディスプレイに対応するようなことが出てきたら、3xなんて指定もしていく必要があるかも。


あと、気になるのはIE対応です。
IEではpicture要素が効かないので、画像が表示されません。
完全に無視するならいいですが、そうもいかない場合もあります。

そこで、Picturefillを利用してサポートしていない古いブラウザに対応させます。

Picturefill
https://scottjehl.github.io/picturefill/

公式サイトの「Downloading Picturefill」の項目から、最新版のファイル「picturefill.min.js」をダウンロードしてください。「min」は軽量化された圧縮版です。

Getting Started with Picturefill」の項目に利用方法が書かれています。
使い方はシンプルで、headセクション内に以下のようにファイルを読み込むだけです。

<script src="picturefill.min.js" async></script>



また、CDNも利用できます。
cdnjs.comから細かくバージョンも選べます。

↓ ↓ ↓

https://cdnjs.com/libraries/picturefill

<script src="https://cdnjs.cloudflare.com/ajax/libs/picturefill/3.0.3/picturefill.min.js" async></script>



async属性をつけて非同期で読み込むことで、ページを効率的にロードでき、表示速度の改善につながります。


他にも、レンダリング処理が増えて表示速度に影響が気になる方は、JavaScriptまたはPHPでIEだけ読み込むようにすると良いでしょう。

ユーザーエージェントの情報を利用して、ブラウザを判断し読み込み処理をさせます。
こちらもhead内に記述しましょう。

JavaScript


PHP

<?php
$ua = getenv('HTTP_USER_AGENT');
if (strstr($ua, 'Trident') || strstr($ua, 'MSIE')) {
  echo '<script src="js/picturefill.min.js" async></script>';
}
?>



これで、IE以外のpicture要素が対応しているブラウザは読み込まないので、なにも影響することはないです。
IEのアクセスだけスクリプトを読み込みます。

背景画像などはCSSのメディアクエリで切り分けできますが、HTMLのマークアップで画像を切り分ける時にpicture要素でうまく対応できます。