CSSのimage-set()を使い、背景画像を出し分けて、表示の最適化をはかる方法

CSSのimage-set()を使い、背景画像を出し分けて、表示の最適化をはかる方法
以前の記事では、pictureタグとsrcsetを使うことにより、表示する画像を最適化する方法について記事を書きました。

ただしpictureタグと srcset でできるのは、html内で直接配置されている画像のみであって、
背景画像を最適化することはサポートされていませんでした。

それを代替するような手段として使えるのが、今回ご紹介する
image-set() になります。

image-set()を使って背景画像を最適化する方法

コードとしては、次のようになります。
まずは、サンプルとしてカード型のUIがあったとします。

<div class="my-card">
  <div class="my-thumbnail">
    <p class="my-title">ReactもVueもそれぞれ良い所があるの</p>
  </div>
  <div class="my-bottom-container">
    <a class="my-link" href="/detail.html">詳細を見る</a>
  </div>
</div>

見た目はこんな感じのCSSです。注目してほしいのが、
.my-thumbnail に指定されている、
image-set(…中略…) の記述です。詳しいことは、コードに続いて次のセクションで記載します。

.my-card {
  background: #fff;
  border-radius: 0.5rem;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
  box-sizing: border-box;
  overflow: hidden;
  padding: 0;
  width: 300px;
}
.my-thumbnail {
  background-image:
  image-set(url("../img/img-sample.webp") type("image/webp"),
            url("../img/img-sample.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: cover;
  display: block;
  height: 160px;
  position: relative;
  width: 100%;
}
.my-title {
  bottom: 0.5rem;
  color: #fff;
  display: block;
  font-size: 0.875rem;
  padding: 0 1rem;
  position: absolute;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.my-bottom-container {
  align-items: center;
  background: #FFF;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3);
  display: flex;
  height: 80px;
  width: 100%;
}
.my-link {
  align-items: center;
  background: #323232;
  border-radius: 999px;
  color: #fff;
  display: flex;
  font-size: 0.6875rem;
  justify-content: center;
  height: 36px;
  margin: 0 1rem 0 auto;
  padding: 0 1rem;
  text-decoration: none;
  width: fit-content;
}

↑上記のhtml、cssで、次のような表示ができます。

【WebPに対応しているブラウザの場合…わかりやすいよう画像の左上に’WEBP’と記載しています
WebPに対応しているブラウザの場合

【WebPに対応していないブラウザの場合…わかりやすいよう画像の左上に’PNG’と記載しています
WebPに対応していないブラウザの場合

image-set()を使うと、背景画像を出し分けることができます

Webサイトの高速化のため、
WebPが使えるブラウザにはWebPを提供、
そうでないブラウザの補完としてPngを指定しておく

というような事を実現すべく、これまでは次のような記述を、html内に配置した画像に対して設定するケースがあったかと思います。

<picture>
  <source srcset="./assets/images/image-sp.webp" media="(max-width: 767px)" type="image/webp" />
  <source srcset="./assets/images/image-pc.webp" media="(min-width: 768px)" type="image/webp" />
  <source srcset="./assets/images/image-sp.png" media="(max-width: 767px)" type="image/png" />
  <source srcset="./assets/images/image-pc.png" media="(min-width: 768px)" type="image/png" />
  <img src="./assets/images/image-sp.png" width="800" height="450" alt="説明" />
</picture>

今回ご紹介する image-set() は、それの「背景画像版」と言っても良いような働きをしてくれるCSSです。
具体的には、次のように指定します。

.my-thumbnail {
  background-image:
  image-set(url("../img/img-sample.webp") type("image/webp"),
            url("../img/img-sample.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: cover;
  display: block;
  height: 160px;
  position: relative;
  width: 100%;
}

↑こちらの、最初の3行を見てください。
このように image-set() を使用する事で、
WebPが使えるブラウザにはWebPを提供、
そうでないブラウザの補完としてPngを指定しておく

ということが、背景画像に対しても可能になります。
(もっとも、現代の主要ブラウザはほぼ全てWebPには対応するようになってきたため、実際は他の画像形式が指定されるケースになるかとは思いますが)

留意点など

.my-thumbnail {
  background-image:
  image-set(url("../img/img-sample.webp") type("image/webp"),
            url("../img/img-sample.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: cover;
  display: block;
  height: 160px;
  position: relative;
  width: 100%;
}

↑image-set() はとても便利な指定であるのですが、
上記の例を見ていただくと分かる通り、
「backgroundに対して、ショートハンドでの記述ができなくなる」という点には留意が必要です。

つまり、通常の背景画像指定のように

background: url(../img/img-sample.png) no-repeat 0 0 / cover;

↑このようにショートハンド記法で、各種指定を一括で指定することができなくなるということです。

image-set() を使った場合は、

.my-thumbnail {
  background-image:
  image-set(url("../img/img-sample.webp") type("image/webp"),
            url("../img/img-sample.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: cover;
...(中略)...
}

このように background-repeat, background-position, background-size…
の様に個別に設定を指定してあげる必要が出てくる、ということです。

とは言え、これまで
「背景画像に関しては、画像最適化を簡単に提供できる仕組みがCSSのみでは存在しなかった」

という事を考えると、image-set() はじゅうぶん、使うに値するものかと思います。

MDNでの、image-set() に関する解説

毎度おなじみ、もはやWeb制作をする際の公式マニュアルと言っても過言ではないレベルの
リファレンスサイトである「MDN」(運営:mozilla)にも、
image-set()」に関する仕様がしっかり掲載されています。

image-set() – CSS:カスケーディングスタイルシート | MDN

↑こちらを読むと、画像形式による分岐だけではなく、画面解像度による分岐もできるという点が記載されています。

一読すると、image-set()に関しての知見が深まると思います。

そして、「Baseline 2023 Newly available」 と冒頭に記載もある様に、
この image-set() は、比較的最近(昨年ではありますが)になって
各種の標準的なブラウザで使える様になった技術、
ということが見て取れるかと思います。

もしも image-set() に対応していないブラウザを考慮する場合

現代ではもはや、あまり想定されるケースではないかもしれませんが、
もしも image-set() に対応していないブラウザを考慮する場合は、次の様に記載します。

.my-thumbnail {
  background-image: url(../img/img-sample.png);
  background-image:
  image-set(url("../img/img-sample.webp") type("image/webp"),
            url("../img/img-sample.png") type("image/png"));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: cover;
...(中略)...
}

↑単純に、image-set() よりも前の行に、通常の背景指定をしておく、というだけです。
(もちろん出し分けの分岐はされませんが)

あまり想定されるケースではないかもしれませんが、
もしも image-set() に対応していないブラウザを考慮する場合は覚えておくと良いかと思います。

この記事のまとめ

今回は、image-set() を使った
背景画像の出しわけ方法」について、
記事を書いてみました。

実際の制作案件において、私自身もたびたび
画像の最適化を行うケースがあります。
(とくに、過去に作られたページの高速化の案件などで、よくおこなう改善施策だったりします)

たかが画像の最適化、されど画像の最適化…。
そうなんです、案外、
実際に表示速度の指標改善を得られるケースもありますので、
試してみると、良い改善結果が得られるかもしれません。

この記事が皆さんのより良いWeb制作体験につながれば、嬉しく思います。
※この記事は内容の品質向上を目的に、随時更新を行う場合があります。

この記事をシェアする: