サイトロゴ

Enjoy Creating
Web & Mobile Apps

MENU BOX
WEB
MOBILE
OPEN

ホーム

 > 

 > 

【picture要素】デバイスによって異なる画像を表示させたい

【picture要素】デバイスによって異なる画像を表示させたい

この記事にはプロモーションが含まれています。

いきなりですが、皆さんはスマホでWebサイトを見る時、スマホを縦に持つでしょうか?横に持つでしょうか?
…おそらくですが、多くの方が縦に持って画面を見るのではないかと思います。

一方で、パソコンの画面は横長に作られているため、スマホとパソコンでは同じ画像でも見やすさが変わるということになります。

スマホ(縦持ち)では横長の画像は小さく表示されて見づらいですが、正方形や縦長の画像は見やすくなります。
反対に、パソコンでは横長の画像が見やすく、縦長の画像はスクロールさせないと全体が見えないなど不便を感じさせてしまいます。

対処法として、縦横比の異なる2つの画像を用意した上でCSSのdisplayプロパティを使い、表示・非表示を切り替えるという方法があります。
しかし、この方法だと非表示の画像データも読み込んでしまう=表示速度に影響を与える…という大きなデメリットがあります。

そこで、今回紹介するpicture要素を利用することで、余計な画像データを読み込むことなく、画像の表示切り替えが可能となります。

下の画像は、picture要素でスマホとパソコンで表示画像を切り替えています。
パソコンでは横長、スマホでは正方形の画像が表示されるようになっています。(画像をクリックしても何も起こりません)

本記事のサムネイル画像

レスポンシブ対応・Webページの軽量化(表示速度UP)は、SEO対策としても重要です。
picture要素を使いこなして、見やすい・軽い・ユーザーに親切=検索エンジンにも評価される…そういったWebページにしていきましょう!

– 目次 –

picture要素の使い方

まずは基本的なpicture要素の使い方からご紹介します。
picture要素は、中にsource要素(0個以上)img要素(1つ)を含める構造になっています。

source要素はmedia属性の指定とセットでデバイスの画面(ブラウザ)幅を判別し、条件に合う画像を読み込む役割を担っています。
img要素はsource要素で指定した画像を含め、画像を出力(表示)するための要素として必要です。

また、img要素のみで画像を振り分ける場合はsrcset属性もsrc属性もimg要素の属性として指定しますが、picture要素を使って画像を明示的に切り替える場合、srcset属性はsource要素に、src属性はimg要素にそれぞれ指定します。

以上をまとめると、picture要素の基本的な構造は下のようになるということが言えます。

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!
  1. ・picture要素には0個以上のsource要素と、1つのimg要素を含める!
  2. ・source要素にはmedia属性を指定して、メディアクエリーに合致した画像を表示させる役割がある!
  3. ・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!
  1. ・srcset属性にはサイズ(画質)の異なる複数の画像を指定することが可能!
  2. ・srcset属性は画像ファイルのパスと、画像の横幅に『w』という単位をつけて指定する!
  3. ・高解像度ディスプレイの場合、物理的な横幅よりも大きな画像を表示できるので、srcset属性を活用していこう!

CSS調整の注意点

source要素はimg要素と同じように、画像ファイルのパスを指定して画像を読み込むためのものですが、最終的に画像は全てimg要素として出力されます。

下の画像は、ブラウザの検証機能を使ってスマホ表示の画像がどの要素として表示されているかを調べたものです。
画像の読み込み指定はsource要素で行なっているのに、画像はPC表示用として用意しておいたimg要素で表示されているのがわかります。

source要素ではなく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!
  1. ・source要素で画像ファイルの読み込み指定したものも、最終的にはimg要素として出力される!
  2. ・そのため、画像の幅などをCSSで調整する際はセレクタ指定をsource要素にしても無意味!
  3. ・画像の調整を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!
  1. ・ゴリ押しではあるが、容量が軽いダミー画像を用意してCSSで表示切り替えを行うことで、データ容量を節約しつつ特定のデバイスのみ画像を表示できる!
  2. ・よりスマートな方法で画像の表示/非表示を行いたい場合は、JavaScriptを使うと良い!
– 人気の注目記事 –


今回の動画で紹介したコード!

今回の解説動画で使用したコードです。学習用としてご自由にコピペしてお使い下さい。(※スクロールできます)

<!DOCTYPE html>
<html lang="ja" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style media="screen">
    .pc_img {
      display: block;
      margin: 0 auto;
      width: 500px;
    }
    .sp_img {
      display: none;
    }
    @media screen and (max-width: 800px) {
      .pc_img {
        display: none;
      }
      .sp_img {
        display: block;
        width: 250px;
        margin: 0 auto;
      }
    }
      picture img {
        display: block;
        margin: 0 auto;
        width: 100%;
        max-width: 600px;
      }
      @media screen and (max-width: 800px) {
        picture img {
          max-width: 250px;
        }
      }
    </style>
  </head>
  <body>
    <div style="height: 500px"></div>

    <!--<img src="img/pc-image01-8.png" alt="" class="pc_img">
    <img src="img/sp-400.png" alt="" class="sp_img">-->

    <div style="height: 500px"></div>

    <picture>
        <source srcset="img/sp-400.png 400w, img/sp-800.png 800w"
                media="(max-width: 800px)">
        <img src="img/pc-image01-8.png" alt="サンプル画像">
    </picture>

    <div style="height: 500px"></div>

  </body>
</html>


« »

カテゴリーリンク

著者について- author profile -

ROYDOプロフィール写真
Michihiro

モバイルアプリ(iOS・Android)ディベロッパー&デザイナー

これまでに、可読性の高いカラーパターンを自動で生成するアプリや、『第3火曜日』といった形式で通知をスケジュールできるアプリなどを制作。

サブでWebデザイン・フロントエンドエンジニアとしても活動しています。

📝ツール・言語:JavaScript/React Native/Kotlin/Android Studio/Swift/SwiftUI

🎓資格:基本情報技術者/ウェブデザイン技能検定3級

Twitterアイコン Instagramアイコン