【HTML】PCとスマホの画像の出し分け方法!pictureタグの使い方と注意点について解説!

HTML

はじめに

ウェブサイトの制作において、適切に画像を表示させることはとても重要です。特に、異なるデバイスや解像度に適した画像を提供することは、ユーザーエクスペリエンスとパフォーマンスの向上に貢献します。

この記事では、画像を扱うための基本として画像形式の種類と選び方について学び、pictureタグの使い方や使用するメリット、注意点について解説します。

この記事の対象者

  • ウェブ制作を基礎から学びたい方
  • ユーザーの環境毎に画像を出し分ける方法を学びたい方
  • 画像形式の選び方について知りたい方

この記事の目標

  • 適切な画像形式を選べるようになる
  • ユーザー環境毎に画像の出し分けができるようになる
  • pictureタグを使用しても適切にレイアウトシフト対策ができるようになる

この記事で使用するHTMLタグ

  • <img>
  • <picture>
  • <source>
  • その他:<div>, <style>

画像の種類について

ウェブサイトで使用される主な画像の種類として、JPEG、PNG、WebPなどが挙げられます。

ウェブ制作では画像の品質とファイルサイズのバランスを考慮する必要があり、画像に適した種類を選択することや、適切な画像サイズであることが求められます。

他にも様々な種類の画像がありますが、まずは代表的な画像の種類であるJPEG、PNG、WebPの特徴について理解しましょう。

JPEG

JPEG形式の画像は色数の多いリアルな画像に適しており、1670万色まで扱える上にファイルサイズが比較的小さいので、ウェブ制作では主に写真画像に使用されます。

非可逆圧縮という方式により、ファイルを上書き保存する度に画質が悪くなる特徴があります。

JPEG形式の画像は背景を透明にすることができないので、ロゴやイラスト、アイコン等には不向きです。

PNG

PNG形式の画像は透明な背景や図形が含まれる画像に適しています。JPEGのように画質が悪くなるといったことがないため、アイコンやロゴなど、編集頻度の高い画像によく使用されます。

同じ色数の画像の場合、JPEGと比べてファイルサイズが大きくなるため、写真画像には不向きです。

WebP

Googleが開発した新しい画像フォーマットで、高い圧縮率と高品質な画像表示を両立させることができます。写真画像でもJPEGよりファイルサイズが小さくなりますが、WebP形式の画像をサポートしていないブラウザもあるため表示されない可能性があります。

ウェブ制作でWebP形式の画像を扱う際は、サポートされていないブラウザへの対策を行う必要があります。

pictureタグについて

pictureタグは、異なるデバイスや解像度に適した画像を提供するための重要な要素です。通常で画像表示に使用するimgタグと比較して、pictureタグがどのように有用であるかを解説します。

なぜpictureタグが必要なのか

imgタグでもsrcset属性を定義することで、高解像度ディスプレイや、PCとスマホへの画像の出し分けはできます。

しかし、WebP形式の画像をimgタグで実装しようと考えると、サポートされていないブラウザを調べた上でJavaScript等で表示させる画像を切り替えるといった手間が必要になります。

また、意図した結果になっているかを複数のブラウザでバージョン毎に確認する必要があると考えると、imgタグのみでWebP画像を扱うことはあまり現実的ではありません。

pictureタグを使用すると、このような問題を簡単に解決することができます。

pictureタグの子要素としてimg要素とsource要素を組み合わせることで、ブラウザがある形式の画像をサポートしている場合には表示し、サポートしていない場合はimg要素の画像を表示するといったことが可能になります。

<picture>

  <source
    srcset="images/main-visual.webp"
    type="image/webp">

  <img src="images/main-visual.jpg"
    alt=""
    width="1280"
    height="600">

</picture>

この例では、sourceタグのtype属性に「image/webp」と指定することで、WebP形式の画像をサポートしているブラウザでは「main-visual.webp」が表示され、サポートされていなければ「main-visual.jpg」が表示されるという挙動になります。

main-visual.webpが表示される場合でも、img要素のaltやwidth、heightといった属性は適用され、img要素のsrc属性が書き換わることもありません。なので、img要素にloading=”lazy”を指定すれば遅延読み込みも可能です。

pictureタグでできること

ウェブ制作において、様々なデバイスへの対応を行うことはとても重要です。前述した画像形式別の出し分け以外にも、pictureタグを使用することで以下のことが実現できます。

  • スマホとPCでの画像の出し分け
  • 高解像度ディスプレイへの対応
  • クロスブラウザでの互換性の維持

スマホとPCでの画像の出し分け

pictureタグが使われるケースとして、スマホとPCでの画像の出し分けをしたい場合によく使用されます。imgタグとCSSを使用して実装される場合もありますが、pictureタグで実装した方が適切な理由を解説します。

imgタグでもCSSを利用することでスマホとPCでの画像の出し分けをすることは可能です。imgタグで行う場合、以下が一般的な手法です。

<div class="img-wrap">

  <img class="img-pc"
    src="images/main-visual-pc.jpg"
    alt=""
    width="1280" height="600">

  <img class="img-sp"
    src="images/main-visual-sp.jpg"
    alt=""
    width="375"
    height="600">

</div>

<style>
  .img-pc {
    display: none;
  }
@media screen and (min-width: 768px) {
  .img-pc {
    display: inline;
  }
  .img-sp {
    display: none;
  }
}
</style>

この例では、img要素を2つ配置してPC用のimgにはdisplay: noneを当てて非表示にしています。

また、メディアクエリを使用して画面幅が768px以上の場合にPC用のimgを表示し、スマホ用のimgが非表示になるようにしています。

このような実装は見かけ上の問題はないのですが、不要な画像の取得を行ってしまうという問題があります。

昨今のウェブ制作ではたくさんの画像が使用されることも多く、ファイルサイズの大きくなりがちな画像を無駄に取得することはパフォーマンスに大きな影響を与えてしまいます。

pictureタグを使用することで、不要な画像を取得せずに画像の出し分けを行うことができます。以下が例です。

<picture>

  <source
    srcset="images/main-visual-pc.jpg"
    media="(min-width: 768px)">

  <img src="images/main-visual-sp.jpg"
    alt=""
    width="375"
    height="600">

</picture>

この例では、sourceタグにmedia属性を記述することで画面幅に応じて画像の出し分けを行っています。

画面幅が768px以上のデバイスでは「main-visual-pc.jpg」が表示され、それ以外では「main-visual-sp.jpg」が表示されます。

mediaの指定方法はCSSのメディアクエリの書き方と同じなので、レスポンシブデザインの基本について学習を終えている方なら使いこなせるでしょう。

高解像度ディスプレイへの対応

sourceタグのsrcset属性もimgタグと同じ使い方ができるので、末尾に2xと記述することで2倍の解像度のディスプレイを使用しているユーザーに対しての出し分けができます。

以下はpictureタグを使用した記述例ですが、ただこれだけの目的であればimg要素で実装した方がシンプルで良いと思います。

<picture>

  <source
    srcset="images/main-visual.jpg 1x,
    images/main-visual-2x.jpg 2x">

  <img
    src="images/main-visual.jpg"
    alt=""
    width="1280"
    height="600">

</picture>
<img
  src="images/main-visual.jpg"
  srcset="images/main-visual.jpg 1x,
          images/main-visual-2x.jpg 2x"
  alt=""
  width="1280"
  height="600">

また、pictureタグには複数のsourceタグを記述できるので、PCとスマホそれぞれに対してWebPの対応も含めて記述できます。

<picture>

  <source
    srcset="images/main-visual-pc.webp 1x, 
            images/main-visual-pc-2x.webp 2x"
    media="(min-width: 768px)"
    type="image/webp">

  <source
    srcset="images/main-visual-pc.jpg 1x,
            images/main-visual-pc-2x.jpg 2x"
    media="(min-width: 768px)">

  <source
    srcset="images/main-visual-sp.webp 1x,
            images/main-visual-sp-2x.webp 2x"
    type="image/webp">

  <source
    srcset="images/main-visual-sp.jpg 1x,
            images/main-visual-sp-2x.jpg 2x">

  <img
    src="images/main-visual-sp.jpg"
    alt=""
    width="375"
    height="600">

</picture>

クロスブラウザでの互換性の維持

WebPやpictureタグのサポートがされていない場合でも、picture内のimg要素の画像が表示されるだけなので大きな問題になることはほとんどありません。また、pictureタグは現在のほとんどのモダンブラウザでサポートされており、2023年8月時点で95パーセント以上のユーザー環境で正常に動作します。

pictureタグの注意点

pictureタグを使用する際、以下の点に注意する必要があります。

  • sourceタグの順番に気を付ける
  • pictureタグの使用によって記述が複雑になる可能性がある
  • 出し分ける画像のアスペクト比が異なるとレイアウトシフトが起こる

sourceタグの順番に気を付ける

picture内のsourceタグは上から順番に判定されます。

多くの条件にマッチするものを上に記述してしまうと、意図した画像が読み込まれないので注意しなければいけません。

<picture>

  <source srcset="images/main-visual.jpg">
  <source srcset="images/main-visual.webp" type="image/webp">

  <img
    src="images/main-visual.jpg"
    alt=""
    width="375"
    height="600">

</picture>

この例では、WebP形式をサポートしている環境ではmain-visual.webpを読み込んでほしいという意図で記述されていることが伺えますが、残念ながら期待どおりにはなりません。

HTMLの解析は上から順番に実行されるため、先に記述されているmain-visual.jpgが読み込まれてしまいます。

pictureタグの使用によって記述が複雑になる可能性がある

pictureタグを使用することであらゆる条件での画像の出し分けを実現できますが、必要以上にpictureタグを使用するとかえって読みづらいコードになる可能性があります。

pictureタグのメリットとして最も大きいのは、media属性を指定してデバイスの幅毎に画像を出し分けられるところです。

それ以外では、imgタグとsrcsetやsizes属性などを組み合わせた方がコードも単純でわかりやすくなります。例えば、スマホとPCで扱う画像が大きさのみの違いであれば、pictureタグの使用はあまり意味がありません。

以下はpictureタグを使用してPCとスマホ向けにそれぞれ高解像度ディスプレイ対策を行う場合の記述例です。画像を3種類用意し、全てアスペクト比が同じであり、違いは画像の大きさのみと仮定しています。

<picture>

  <source
    srcset="images/image-800.jpg 1x,
            images/image-1600.jpg 2x"
    media="(min-width: 768px)">

  <source
    srcset="images/image-400.jpg 1x,
            images/image-800.jpg 2x">

  <img
    src="images/image-400.jpg"
    alt=""
    width="400"
    height="200">

</picture>

結果、

  • スマホではimage-400.jpgを取得
  • 高解像度スマホとPCではimage-800.jpgを取得
  • 高解像度ディスプレイを使用したPCではimage-1600.jpgを取得

という挙動になります。pictureタグを使用してこのように実装することができますが、少し冗長に感じます。imgタグ1つのみで実現した方が記述も少なく簡潔になります。

<img
  src="images/image-400.jpg"
  alt=""
  width="400"
  height="200"
  srcset="images/image-400.jpg 400w,
          images/image-800.jpg 800w
          images/image-1600.jpg 1600w">

この例では、imgタグのsrcset属性で3種類の画像を出し分けています。どの画像を取得するかはウェブブラウザが自動で判断し、ユーザー環境の画面サイズと解像度に合わせて最適なものが選ばれます。結果として、前述したpictureタグでの実装とほぼ変わらない挙動になります。

上記の2つの例での違いを説明すると、pictureタグの例はスマホとPCをmedia=”(min-width: 768px)”で切り分けています。

imgタグの例ではsrcset属性で画像幅をウェブブラウザに伝えることで自動で判断させているため、この例での結果はユーザー環境によっては厳密に同じではありません。

出し分ける画像のアスペクト比が異なるとレイアウトシフトが起こる

pictureタグを使用する際のメリットとして、スマホとPCで異なる画像を表示できるという点の説明を先述しましたが、この実装を行う場合、出し分ける画像のアスペクト比が異なるとレイアウトシフトが起こります。

レイアウトシフトの対策としてimg要素にwidth、height属性を指定する手法は一般的ですが、pictureタグ内のimg要素の属性はどのsource要素にマッチしたとしても引き継がれてしまいます。

なので、source要素で指定している画像のアスペクト比が異なる場合はこの手法を使用することはできません。

<picture>

  <source
    srcset="images/image-pc.jpg"
    media="(min-width: 768px)">

  <source
    srcset="images/image-sp.jpg">

  <img
    src="images/image-sp.jpg"
    alt=""
    width="400"
    height="600">

</picture>

この例では、img要素のwidth、height属性によってスマホ環境でのレイアウトシフト対策は実装できています。しかし、image-pc.jpgとimage-sp.jpgのアスペクト比が異なる場合、画面幅が768px以上のデバイスで表示した時でもウェブブラウザはwidth=”400″、height=”600″の領域しか確保しません。

この問題は、CSSのaspect-ratioプロパティを使用したレイアウトシフト対策を行うことで解決することができます。

<div class="img-wrap">
  <picture>
    <source srcset="images/image-pc.jpg" media="(min-width: 768px)">
    <source srcset="images/image-sp.jpg">
    <img src="images/image-sp.jpg" alt="">
  </picture>
</div>

<style>
.img-wrap {
  aspect-ratio: 400 / 600;
}
@media screen and (min-width: 768px) {
  .img-wrap {
    aspect-ratio: 1280 / 640;
  }
}
</style>

aspect-ratioを記述することによって、ウェブブラウザは要素の表示領域を確保することができます。

divはブロック要素のため、デフォルトでは親要素の幅いっぱいのwidthを持ちます。divに対して「img-wrap」というクラスを当て、img-wrapクラスにはaspect-ratio: 400 / 600という指定をしています。

これにより、img-wrap自体の要素幅からアスペクト比に基づいた高さが計算され、画像が表示されるよりも先に画像の表示領域をウェブブラウザに伝えることができます

また、メディアクエリを使用して「min-width: 768px」の条件ではaspect-ratio: 1280 / 640となるように指定しています。

min-width: 768pxという条件はpictureタグ内の画像を出し分けるためのブレイクポイントと同じなので、この手法により、アスペクト比の異なる2つの画像に対してのレイアウトシフト対策ができます。

最後に

画像形式の種類と選び方、pictureタグの使い方や使用するメリット、注意点について解説しました。

あらゆる環境に対して対策を行うことはユーザーエクスペリエンスやパフォーマンスの向上に貢献します。

しかし、1つの画像要素に複数の画像を用意することは作業工数が肥大化するというデメリットもあり、どのような状況でも最適な判断とは言えません。

最初は最低限の構造でコーディングを行い、画像が荒れたりパフォーマンスに影響を与えているものがあった場合に対策を行うという判断も時には必要でしょう。

ただ、異なるユーザー環境に対して適切な画像の出し分けを実装できることは、質の高いウェブサイトを制作するための必須スキルだと思うのでぜひマスターしましょう。

タイトルとURLをコピーしました