かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

SVG に alt の代わりになる属性を付けたい

React / Next で SVGコンポーネントとして使うことが多かったのだけれど、SEO が必要なメディアの制作で SVG に image のような alt が設定できないか気になって調べてみたメモ

img タグを使う

<img src="/path/to/logo.svg" alt="ロゴ" />

font-size で大きさを変えたり、color で色を変えたりする必要のない画像であれば通常の img タグを使えば、従来どおり画像として認識され alt 属性が SEO にも効く。ロゴなど動的な変化が必要ない SVG 画像ならこのパターンがシンプルで良さそう

Inline SVG

fill="current color" にしておいて color で色を動的に変えたりできるのが SVG の強みだと思っている。
SVG を React Component として読み込ませた場合は Inline SVG になるので、先の img タグのように alt 属性を使うことは出来ない。

Search engines don’t index inline images. For the type of images used (e.g. icons), for most websites they’re not the sort of images that should be indexed anyway.
cf. Inline SVG Images: Page Speed & SEO Guide // Salience

Currently at the time of writing, we'd recommend you to go with <img> tags as the simplest option and <object> tags only if you require interactivity in your graphics. Avoid Inline SVG in order to be indexed in Google Image.
cf. Best Practices for SVG SEO in Google Image

最近の記事はあまり見つけられなかったが、どうやら Inline SVG は画像として Google にはインデックスされないっぽい。
color を変更したいなどのインタラクティブ性が必要な SVG 画像はボタンのアイコンなどになるはずなので、SEO 対策よりアクセシビリティとして有用かどうかを考えたほうが良さそう

Note that while some screen readers may ignore an SVG if it has no role or accessible name, other screen readers may still find the element and announce it as a “group” without an accessible name. It’s best to avoid these situations by always using aria-hidden="true" if the SVG is meant to be decorative.
cf. Contextually Marking up accessible images and SVGs | scottohara.me

role か accessible name を持たない場合、スクリーンリーダーは SVG を無視する場合があるので意味を持つ SVG には設定をしておくのが良さそう

role="img"

<svg role="img"></svg>

role="img" があればスクリーンリーダーが画像またはグラフィックと認識するっぽい

role="img" + title タグ

<svg role="imge">
  <title>Button</title>
</svg>

role="img" + title タグは画像として扱われ title タグの中身がスクリーンリーダーに読み上げられ、hover 時にブラウザデフォルトの tooltip で title の内容が表示される

tooltip が表示されるのでアイコンボタンなどで使う場合はボタンにマウスオーバーした際に SVG の上にマウスがあると意図しない tooltip が表示されてしまう可能性があるので、SVGコンポーネントとして使い回す場合は扱いが難しそう

import EditIcon from './editIcon.svg';

const EditIconButton: FC = () => {
  return (
    <button title="Edit this article">
      <EditIcon />
    </button>
  );
};

// editIcon.svg
<svg role="img">
  <title>Edit</title>
</svg>

上記の例では <EditIconButton />Edit this article を title (tooltip) として表示させたいが、内部の <EditIcon /> コンポーネントは Inline SVG<title> 要素があるために、アイコンの上にマウスオーバーしていると Edit が tooltip として表示されてしまう

また title はスクリンリーダーで読み上げられないケースがあるらしい

また、インタラクティブな要素内の <svg> 要素の <title> 要素は、ブラウザとスクリーンリーダーの組み合わせによっては読み上げられないことがあります。実際にMac VoiceOverを使用した検証において、Google Chromeでは問題なく読み上げられましたが、Safariでは読み上げられませんでした。
cf. アイコンボタンのアクセシブルな名前はボタンが持つべきかアイコンが持つべきか

role="img" + arie-label

<svg role="img" aria-label="edit"></svg>

aria-label属性
この属性で指定したラベルは画面上には表示されません。この属性は、画面には表示させずに支援技術に対してのみラベルを設定しておきたい場合に利用できます(この属性で指定したラベルはスクリーンリーダーなどでは読み上げられます)。
cf. 知っていると便利なaria-label属性の使い方 – ofujimiki.jp

aria-label 属性はスクリーンリーダーで読み上げられるが <title> 要素と異なり tooltip として表示されることはないので、SVGアイコンをコンポーネント化してボタンのアイコンなどに使う場合でもこちらの方が属性を props で渡せるので良さそう

import EditIcon from './editIcon.svg';

const EditIconButton: FC = () => {
  return (
    <button title="Edit this article">
      <EditIcon aria-label="Edit this article" />
    </button>
  );
};

// editIcon.svg
<svg role="img" aria-label="edit"></svg>

React Component として読み込んだ SVG に props で aria-label を渡せば、出力される Inline SVGaria-label 属性は props で渡したものに上書きされるので、SVG そのものにデフォルトの aria-label を持たせて利用用途に合わせて props で aria-label を変更するといった使い方ができそうです!

結論

  1. ロゴなど検索結果に画像インデックスさせたい・SEO 用途の場合は <img> 要素を使って SVG を読み込ませて、alt 属性に SEO 用のテキストを書く
  2. 意味のあるアイコンやグラフィックとして使う場合は SVGrole="img" + aria-label を設定する

のが良さそうかな〜と思いました。
SEOアクセシビリティもめちゃめちゃ詳しいわけではないので、誤りなどあればご指摘ください!

おわり


[参考]