🧱

Astroで<picture>タグを扱う方法

2023/09/19に公開

Astroで<picture>タグを扱う際に、少し詰まったので共有します。

前提

こちらの記事は Astro3 を利用しています。

<picture>タグとは

<picture>タグとは、異なるデバイスや画面サイズに対応する複数の画像を表示させることができます。
本来であればCSSのメディアクエリで切り替える必要がありますが、それをHTMLのみで行なうことが可能となります。

html
<picture>
  <source media="(min-width: 800px)" srcset="large-image.jpg" />
  <source media="(min-width: 400px)" srcset="medium-image.jpg" />
  <img src="small-image.jpg" alt="Description of the image" />
</picture>

// 画面の幅が800px以上の場合、large-image.jpg が表示されます。
// 画面の幅が400px以上、800px未満の場合、medium-image.jpg が表示されます。
// 上記の条件に該当しない場合、small-image.jpg がデフォルトとして表示されます。

Astroでの<picture>タグの対応状況

ドキュメントでは下記のように書かれています。

<Image />コンポーネントは、画像を最適化し、また(ローカル画像の場合は)オリジナルのアスペクト比に基づいて幅と高さを推測することでCLSを回避します。ただし、特定のフォーマットのみに対応しており、<picture>要素はなく、srcsetもサポートしていません。

要約すると、<Image />コンポーネントは、特定のフォーマットのみに対応しており、<picture>要素はなく、srcsetもサポートしていません。とのことです。

つまり、Astroのコンポーネントを使用するのではなく、普通のHTMLにAstroの画像パスを挿入していく形になります。

Astroでの<picture>タグの扱い方

下記のように、変数を定義した上で、HTMLのsrcまたはsrcset{画像の変数名.src}と記述することで、開発時・ビルド時にパスを解決してくれます。

astro
---
import largeImage from "../imagePath/large-image.jpg"
import mediumImage from "../imagePath/medium-image.jpg"
import smallImage from "../imagePath/small-image.jpg"
---

<picture>
  <source media="(min-width: 800px)" srcset={largeImage.src} />
  <source media="(min-width: 400px)" srcset={mediumImage.src} />
  <img src={smallImage.src} alt="" />
</picture>

画像がうまく表示されないとき

開発者ツールで画像パスを確認してください。もしかしたら、パスがうまく認識されていない可能性があります。
私が詰まった理由として、画像パスに半角スペースが入っていたために画像が認識されていませんでした。(<img>タグは問題なかったが、<source>タグのみ不具合が起きていた)

もし私と同様の不具合が起きている場合は、.replace(" ", "%20")を追加することで問題なく動かすことができました。(%20は半角スペースを表す)

astro
~~~ 省略 ~~~

<picture>
  <source media="(min-width: 800px)" srcset={largeImage.src.replace(" ", "%20")} />
  <source media="(min-width: 400px)" srcset={mediumImage.src.replace(" ", "%20")} />
  <img src={smallImage.src} alt="" />
</picture>

もしもっと良い方法をご存じの方は教えていただけると嬉しいです。

参考

▼Astroドキュメント
https://docs.astro.build/ja/guides/images/

Discussion