北上研究所

2025年06月18日 検証結果

Kitakami Yuma Project.のyumaです。

今回は前回検証した結果をまとめたいと思います。
何を検証したかについては前回の日記をご覧ください。

まず検証ページを作るために<picture>タグについて調べてたのですが、どうやら僕の認識が間違っていることが途中で判明しました。
以前まで僕は<picture>タグで画像のサイズを切り替えるものと思っていましたが、本来は<img>タグにsrcset属性を付けて切り替えるのが正しいそうです。

検証ページにパターンAとパターンBがあるのはそのせいだったり。
パターンAは僕が最初にやろうとしていた方法、パターンBは本来の正しい方法です。

とりあえずこれだけだと何が間違ってるのかわからないのでサンプルを載せます。
このサンプルは僕が当初やろうとしていた方法、つまりパターンAのサンプルです。

検証用の画像
<picture>
  <source srcset="../images/25_06_15.jpg, ../images/25_06_16.jpg 2x" media="(max-width:1024px)">
  <source srcset="../images/25_06_04.jpg">
  <img src="../images/25_06_26.jpg" alt="検証用の画像">
</picture>

これは幅が1024px以下なら25_06_15.jpg、1024pxより大きかったら25_06_04.jpg、<picture>タグが非対応なら25_06_26.jpgを表示するソースです。
スマホなどで高解像度の画像が表示できるなら25_06_16.jpgを読み込みます。
まあ結局サイトの都合で600x338にされるんだけどね!

実はこのやり方、間違いなんですよね。
というわけで正しい方法、つまりパターンBのサンプルをお見せします。

検証用の画像
<img srcset="../images/25_06_15.jpg 1024w, ../images/25_06_04.jpg 1920w" src="../images/25_06_26.jpg" alt="検証用の画像">

これも先ほどとほぼ同じで、幅が1024px以下なら25_06_15.jpg、1024pxより大きかったら25_06_04.jpg、srcset要素が非対応なら25_06_26.jpgを表示します。
先ほどと異なりスマホで開いた場合、25_06_16.jpgではなく25_06_04.jpgが表示されます。

一見そっくりな2つですが、HTML的に正しいのは下の方法です。
正確に言うと、ただ画像のサイズを変更させるだけなら下が正しいです。

軽く解説すると、上のサンプルは<picture>タグの中にある<source>タグのmedia属性によって画像のサイズを変更しています。
media属性にmax-width:1024pxという値を入れて動かしてるんですよね。

対して下のサンプルはsrcset要素で画像を指定する時に、アドレスの後ろに幅記述子を記述して画像のサイズを変更しています。
1024wって指定した場合、画面の幅が1024px以下なら指定した画像が表示されます。

正直上も下も記述方法が違うだけでやっていることはそっくりです。
しかし上と下ではそれぞれ担う役割が異なります。

下のサンプルは僕がやろうとしていた幅に合わせて画像のサイズを変更する機能です。
対して上のサンプルは幅に合わせて画像そのものを変更する機能です。

上のサンプルの本来の用途はスマホではイヌ、パソコンではネコのように異なる画像へ切り替えることです。
なので僕のやりたかった同じ画像のサイズ違いを切り替えるのは間違いです。

とはいえ上のサンプルのパターンを解説しているサイトも多い上、ちゃんとした企業が作った公式サイトでも上のパターンが使われていることが多いです。
具体的に言うと、AC6の公式ホームページは上のパターンで作られています。

ちなみにウマ娘 プリティーダービーの公式サイトも上のパターンですが、こちらは画像の縦横比やトリミングの位置が異なる画像へ切り替えてるので正しい使い方です。
あくまで同じ画像というのは、解像度以外の内容が同一の画像を指します。

色々と理由は考えられますが、上と下では挙動が異なるからかもしれません。
上はブラウザのサイズが変更された時、変更に合わせて画像を変更を行いますが、下は使用するブラウザごとに仕様が異なります。

Firefoxを使用した場合は上も下も動作は同じですが、ChromeやEdge(Chromium)では大きい画像を読み込んだ後はブラウザの幅が縮んでも大きい画像をそのまま使用します。
これだからChromeはメモリ大食いなんだよ。
Macは持ってないのでわかりませんが、Safariは最初に読み込んだ後はブラウザの幅が大きくなったり小さくなったりしても最初の画像を表示し続けるそうです。

このような挙動の違いがあるため、もしかしたらわざとsrcset属性ではなく<picture>タグを使用してるのかもしれませんね。
特にSafariの大きくしても画像が切り替わらない仕様は困ることもあるでしょう。

ちなみに実際のパターンBには<picture>タグも使われてます。
理由は画像のサイズを変更するのはsrcset属性ですが、画像の形式を変更するのは<picture>タグの役割だからです。

というわけで認識を改めたところで、気になっていたことの結果をまとめましょうか。

疑問1:画像(大)、画像(小)の2つの画像が設定された状態の時、その中間の画面サイズで表示されるのは画像(大)、画像(小)のどちらか。

結果:パターンA、パターンBどちらのパターンでも画像(大)が表示される。

疑問2:画像(小)に指定した幅と画面の幅が全く同じ幅であった場合、画像(大)、画像(小)のどちらが表示されるのか。

結果:パターンBは指定した幅と同じ幅の場合はその画像が表示されるため、この場合は画像(小)が表示される。
パターンAは指定する方法によって異なり、画像(小)にmedia="(max-width:数値)"と指定した場合は画像(小)が表示されるが、画像(大)にmedia="(min-width:数値)"と指定した場合は画像(大)が表示される。

疑問3:ピクセル比が2.5の端末で2倍と3倍しかなかった場合、どちらが表示されるのか。

結果:パターンAの場合、端末より大きい3倍の画像が表示される。
パターンBの場合、そもそもピッタリ2倍や3倍の画像を用意することが困難であるが、その場合でも端末より大きい3倍に相当する画像が表示される。

疑問4:パターンA、パターンBのどちらも画面の幅に合わせて変更を行うが、画像の表示される幅に合わせて変更することは可能か?

結果:何らかのフレームワークや作成ツールを用いれば可能かもしれないが、<picture>タグやsrcset単体では不可能と思われる。
ただしパターンAに指定できるメディアクエリーについてあまり知識がないため、もしかしたらできる可能性もある。

疑問5:パターンA、パターンBのどちらも画面の幅に合わせて変更を行うが、画面の高さに合わせて変更することは可能か?

結果:パターンA、パターンBのどちらでも可能。
パターンAの場合はmedia="(max-height:数値)"やmedia="(min-height:数値)"で指定。
パターンBの場合は幅記述子のwをhに変更する。

疑問6:幅記述子とピクセル密度記述子の両立は可能か。

結果:不可。
2種類の記述子が混在してはならないと定められている。

疑問7:幅記述子よりも画面の幅が大きい場合、どの画像が表示されるのか。

結果:もっとも大きな記述子が書かれた画像が表示される。
1920pxの画面で1024wが最大の画像を表示したら1024wの画像が表示される。

というわけで色々検証しましたがどうでしょうか?
流石に長くなり過ぎたので感想はまた後日書きたいと思います。

それではまた。