▼動画解説は下のサムネイルから(YouTubeに飛びます)
picture要素の使い方
まずは基本的なpicture要素の使い方からご紹介します。
picture要素は、中にsource要素(0個以上)とimg要素(1つ)を含める構造になっています。
source要素はmedia属性の指定とセットでデバイスの画面(ブラウザ)幅を判別し、条件に合う画像を読み込む役割を担っています。
img要素はsource要素で指定した画像を含め、画像を出力(表示)するための要素として必要です。
また、img要素のみで画像を振り分ける場合はsrcset属性もsrc属性もimg要素の属性として指定しますが、picture要素を使って画像を明示的に切り替える場合、srcset属性はsource要素に、src属性はimg要素にそれぞれ指定します。
以上をまとめると、picture要素の基本的な構造は下のようになるということが言えます。
source要素は複数あっても構いませんが、img要素は1つだけです。
また、source要素のmedia属性は上から順に判定され、条件にマッチした時点でその画像が表示されます。
よって、極端な例ですが
<source srcset=”img/image01.png” media=”(min-width: 200px)”>
<source srcset=”img/image02.png” media=”(max-width: 1000px)”>
と指定したならば、どんなデバイスでもimage01の画像しか読み込まれないということになります。
※200px以下のデバイス(ブラウザ幅)など、特別な条件でないとあり得ないからです。
下のコードは、picture要素とsource・img要素を使って
・スマホ〜小さなタブレット用として、横幅800pxまでのデバイスではimage01.pngを、それ以外(主にPC)のデバイスではimage02.pngを読み込ませる
ためのコードサンプルです。
HTML
<picture>
<source srcset="img/image01" media="(max-width: 800px)">
<img src="img/image02.png" alt="PC用の画像">
</picture>
単純なスマホとパソコンの画像切り替えであれば、上記のコードだけでも十分です。
ただ、画質(データ容量)が違うだけで縦横比や内容が同じ画像を切り替えたいのであれば、img要素のsrcset属性を使った方がブラウザが自動的に適切な画像を選択してくれるので楽です。
そうではなくて、縦横比や内容も異なるような画像を切り替えたい場合には、source要素のmedia属性で明示的に画像を切り替えられるこちらの方法が適しています。
※img要素のsrcset属性の使い方については、こちらをご参照ください。
下の動画は、picture要素(source/img要素含む)を使って、スマホ用の縦長画像とPC用の横長画像の読み込み&表示が切り替わっていることを確認したものです。
media条件をmax-width:800pxとしているので、800pxを分岐点として画像が切り替わっているのがわかりますね。
POINT!
- ・picture要素には0個以上のsource要素と、1つのimg要素を含める!
- ・source要素にはmedia属性を指定して、メディアクエリーに合致した画像を表示させる役割がある!
- ・img要素にはsource要素でファイルのパスを指定した画像を含めて、画像を表示させるための要素としての役割がある!
source要素のsrcset属性
source要素にはsrcset属性を指定するわけですが、img要素にsrcset属性を指定する場合と同じく、画像のサイズを複数用意してデバイスの解像度に合わせてセットしておくということが可能です。
スマートフォンの横幅は300〜400px前後ですが、解像度が高いiPhoneのRetinaディスプレイでは物理的な横幅の2倍程度の画像を表示することができます。
つまり、本来であればスマートフォン向けの画像の横幅は400pxで事足りるのですが、高解像度ディスプレイでは800pxの表示能力を持つので400pxの画像だと画質が劣化したように見えてしまいます。
そこで、srcset属性にサイズ(画質)の異なる画像を複数用意しておくことで、ブラウザがデバイスの解像度に合わせて最適な画像を自動で読み込んでくれます。
srcset属性の指定方法については、こちらの記事に詳しく記載してますが、本記事でも簡単に解説します。
srcset属性には画像ファイルのパスと、その画像の横幅(px)に『w』という単位をつけて指定します。
複数指定する場合は
,
で区切ります。
横幅400px(image400.png)と800px(image800.png)の画像を用意してあるならば、
srcset=”image400.pmg 400w, image800.png 800w”
と指定すればOKです。(ファイルのパスの部分は、ファイル名やファイルの場所・絶対or相対パスの違いによって変わります)
これを踏まえて、picture要素を使って画像を複数指定したものが下のコードです。
HTML
<picture>
<source srcset="img/image01-400.png 400w, img/image01-800.png 800w" media="(max-width: 800px)">
<img src="img/image02.png" alt="PC用の画像">
</picture>
上のサンプルコードでは、結局どのデバイスで何の画像が読み込まれるのでしょうか?図を使って確認していきましょう。
…ということになります。
ここで注意点なのですが、source属性のmedia属性のメディアクエリーはあくまで物理的なデバイス幅を計測するという点です。
高解像度ディスプレイだからといって、media条件のpx指定幅も2倍になるかというとそういうわけではありません。
srcset属性の指定だけではデバイスの物理的な横幅に合わせて任意的に画像を切り替えるということが困難ですが、picture要素とsource要素のmedia属性を利用することでそれが容易に可能となります。
POINT!
- ・srcset属性にはサイズ(画質)の異なる複数の画像を指定することが可能!
- ・srcset属性は画像ファイルのパスと、画像の横幅に『w』という単位をつけて指定する!
- ・高解像度ディスプレイの場合、物理的な横幅よりも大きな画像を表示できるので、srcset属性を活用していこう!
CSS調整の注意点
source要素はimg要素と同じように、画像ファイルのパスを指定して画像を読み込むためのものですが、最終的に画像は全てimg要素として出力されます。
下の画像は、ブラウザの検証機能を使ってスマホ表示の画像がどの要素として表示されているかを調べたものです。
画像の読み込み指定はsource要素で行なっているのに、画像はPC表示用として用意しておいたimg要素で表示されているのがわかります。
この結果から言えることは、画像の幅(width)などを調整するためのCSSとして、セレクタ指定をsource要素にしても意味がないということです。
無効になる(効かない)ケース
HTML
<div class="sample_color">
<p>サンプルテキスト</p>
</div>
CSS
picture source {
width: 100%;
}
画像の大きさをCSSで調整するには、セレクタ指定はあくまでimg要素に対するものでなければなりません。
class指定する場合も同様で、source要素にclass名を付けるのではなく、img要素にclass名をつけてセレクタに指定する必要があります。
調整が有効なケース
HTML
<div class="sample_color">
<p>サンプルテキスト</p>
</div>
CSS
picture img {
width: 100%;
}
source要素として画像が表示されずに全てimg要素として画像が表示される以上、スマホとPCで画像の表示幅を変えたい場合は、CSS側でも改めてメディアクエリーを記載して条件別に指定する必要があります。
その場合のブレークポイントは、source要素のmedia属性に指定したmedia条件と一致させるようにすると良いでしょう。(下記サンプルコード参照)
CSS
picture img {
width: 100%;
}
@media screen and (max-width: 800px) {
picture img {
max-width: 250px;
}
}
POINT!
- ・source要素で画像ファイルの読み込み指定したものも、最終的にはimg要素として出力される!
- ・そのため、画像の幅などをCSSで調整する際はセレクタ指定をsource要素にしても無意味!
- ・画像の調整をCSSで行う場合は、あくまでもimg要素に対して行うようにしよう(class名を付ける場合も同様)!
スマホのみ・PCのみ画像を表示させたい場合
やや邪道ではありますが、picture要素関連を利用して画像の読み込みデータ容量を抑えつつ、スマホのみ・PCのみ画像を表示させることもできなくはありません。(ゴリ押しですが)
やり方は簡単で、非表示にさせたい方にデータがめちゃくちゃ軽いダミーの画像をセットし、CSS等で表示・非表示を切り替えるだけです。
※表示させたい方には、当然ですがちゃんとした画像を用意してセットしておく必要があります。
CSSでdisplay: none;として画像を非表示にしても画像のデータは読み込まれてしまいますが、そのデータを無視できるほど軽くしておけばページの表示速度にはほぼ影響を与えずに済む…という理屈です。
下のコードは、スマホのみで画像を表示させ、PCではダミーの軽い画像を読み込ませてCSSで非表示にしている例です。
HTML
<div class="sample_color">
<p>サンプルテキスト</p>
</div>
CSS
picture img {
width: 100%;
display: none;
}
@media screen and (max-width: 800px) {
picture img {
max-width: 250px;
display: inline;
}
}
1枚の画像に対してCSSで表示/非表示の切り替えを行なって読み込ませる必要のない画像を読み込ませてしまうより、1KBにも満たないダミー画像を用意しておいた方がデータ容量的には圧倒的に節約できます。
ただし、最初に言ったようにこの方法はやや邪道的でスマートとは言えないので、もう一つJavaScriptを使った方法をご紹介しておきます。
JavaScriptを使って条件指定のもとでimg要素を生成することで、ダミー画像を用意せず特定の大きさのデバイスでのみ画像を表示させることができます。
HTML
<div class="sp_img"></div>
JavaScript
const sp_imgBox = document.querySelector('.sp_img');
const w = window.innerWidth;
if(w <= 800) {
const sp_imgElemet = document.createElement('img');
sp_imgElemet.src = '画像ファイルのパス';
sp_imgBox.appendChild(sp_imgElemet);
}
本記事はHTMLに関する記事なので、JavaScriptプログラムに関する詳しい解説は割愛しますが、上記のコードはデバイス(ブラウザ)の幅が800pxより小さければ<div class=”sp_img”></div>の中にimg要素を生成して画像を埋め込む…という処理になります。
POINT!
- ・ゴリ押しではあるが、容量が軽いダミー画像を用意してCSSで表示切り替えを行うことで、データ容量を節約しつつ特定のデバイスのみ画像を表示できる!
- ・よりスマートな方法で画像の表示/非表示を行いたい場合は、JavaScriptを使うと良い!
– 人気の注目記事 –