svg について
SVG グラフィックの作成、最適化、レビューを行う開発者向けのアクセシビリティスキルです。用途や埋め込み方に応じて、代替情報、操作性、レスポンシブ表示、動き、信頼できない SVG のサニタイズを扱います。
主な機能
- 01目的に応じた SVG セマンティクスの選択
- 02アクセシブルな名前と説明の設定
- 03インタラクティブ画像のキーボード対応
- 04色、動き、拡大表示の指針
- 05信頼できない SVG のサニタイズ
活用シーン
- 01アイコンや画像の代替情報を確認
- 02複雑な図に見える説明を追加
- 03インタラクティブ SVG のキーボード操作を点検
- 04アップロードまたは生成された SVG をサニタイズ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mgifford/ accessibility-skills --skill svgインストール後、Claude Code で/svgを入力して読み込まれたか確認します。
同梱ファイルSYNC.md
詳細
SVG アクセシビリティスキル
正規の参照元:
mgifford/ACCESSIBILITY.mdのexamples/SVG_ACCESSIBILITY_BEST_PRACTICES.mdこのスキルはそのファイルを基にしています。判断に迷った場合は、例を優先してください。
SVG グラフィックの作成、最適化、レビュー時には、以下のルールを適用してください。 プロジェクトに SVG が含まれる場合にのみ、このスキルを読み込んでください。
基本方針
SVG のアクセシビリティは、グラフィックの目的と埋め込み方法によって異なります。装飾アイコン、情報を伝える画像、ボタン内のアイコン、インタラクティブな図では、それぞれ異なるパターンが必要です。まず、ユーザーがグラフィックから何を必要としているかを判断し、同じ情報や機能を提供する最もシンプルなセマンティック実装を選んでください。<title>、<desc>、role="img"、aria-labelがあるだけで SVG がアクセシブルになるわけではありません。最終的なコンテキストで結果をテストしてください。
SVG は、スクリプト、イベントハンドラー、外部リソースへの参照を含められるアクティブな XML 形式でもあります。信頼できない SVG(アップロード、貼り付けられたマークアップ、AI 生成の出力)は、レンダリング前にサニタイズする必要があります。以下のセキュリティセクションを参照してください。
重大度の尺度(このスキル)
| レベル | 意味 |
|---|---|
| 致命的 | SVG が重要な情報を伝えているにもかかわらず、アクセシブルな代替手段がない。または、信頼できない SVG をサニタイズせずにレンダリングしている |
| 深刻 | SVG がインタラクティブだが、AT ユーザーが操作できない、またはラベルが付いていない |
| 中程度 | AT での操作性が低下しているが、コンテンツには部分的にアクセスできる |
| 軽微 | ベストプラクティスからの逸脱。影響はわずか |
目的とコンテキストに応じてパターンを選択する
| コンテキスト | 推奨パターン |
|---|---|
<img>で読み込む装飾的な SVG | <img src="…" alt=""> |
<img>で読み込む意味のある SVG | <img src="…" alt="Useful description"> |
| 装飾的なインライン SVG | <svg aria-hidden="true">…</svg> |
| シンプルで意味のあるインライン SVG | <svg role="img" aria-labelledby="…"><title>…</title></svg> |
| 名前の付いたボタンまたはリンク内のアイコン | HTML コントロールに名前を付け、SVG を非表示にする |
| 複雑なグラフィック | 短い名前に加えて、表示される概要、データ、または詳細な説明を提供する |
| 再利用するスプライトアイコン | 共有シンボルではなく、外側の各<svg>インスタンスにラベルを付けるか、非表示にする |
| インタラクティブなグラフィック | ネイティブ HTML コントロールを優先し、同等の構造化された代替手段を提供する |
ARIA より先にネイティブ HTML のセマンティクスを使用してください。ソースが SVG ファイルだからといって、<img>にrole="img"を追加しないでください。これは冗長です。
重要:装飾的な SVG は AT から完全に隠す必要があります
<svg aria-hidden="true" focusable="false">
</svg>
aria-hidden="true"を指定すると、その SVG と子孫要素がアクセシビリティツリーから除外されます。このように隠す要素の中に、フォーカス可能またはインタラクティブなコンテンツを置かないでください。focusable="false"は、古い IE/旧 Edge の動作に対応するものです。これらのブラウザーを引き続きサポートするプロジェクトでは残してもかまいませんが、現代の環境で普遍的に必要なものではありません。意図的に隠す SVG に<title>/<desc>を追加しないでください。aria-hidden="true"の代わりにrole="presentation"を使用しないでください。ブラウザーとスクリーンリーダーの組み合わせによっては、読み上げを確実に抑制できません。
SVG が装飾的なのはどのような場合ですか? 同じ意味が隣接する表示テキストで伝えられている場合、または画像が純粋に装飾目的の場合は、装飾的です。削除するとユーザーに必要な情報が伝わらなくなる場合は、意味があります。
<img>で使用する外部 SVG
他の画像形式と同じテキスト代替のルールに従います。
<img src="/assets/images/service-area.svg" alt="Map showing the service area extending from Kingston to Ottawa" width="640" height="360">
<img src="/assets/images/flourish.svg" alt="" width="120" height="24">
<a href="/reports/annual-report.pdf">
<img src="/assets/icons/download.svg" alt="Download annual report">
</a>
<img>でのrole="img"は冗長です。altで名前を指定できる場合、aria-labelは不要です。<img>で読み込む場合、内部の SVG の<title>/<desc>は HTML のaltの代わりにはなりません。読み上げられるのは HTML の alt です。
重大:シンプルで意味のあるインライン SVG
<svg role="img" aria-labelledby="download-icon-title" viewBox="0 0 24 24">
<title id="download-icon-title">Download</title>
<path d="M12 3v12m0 0 5-5m-5 5-5-5M5 21h14"></path>
</svg>
<title> は <svg> の直接の子要素とし、一意の ID を付けて
aria-labelledby から参照する必要があります。一意のタイトル ID を管理することで
不必要に複雑になる場合は、単純な aria-label も妥当な代替手段です。
<svg role="img" aria-label="Download" viewBox="0 0 24 24">…</svg>
特別な理由があり、テスト済みの場合を除き、両方のパターンを併用しないでください。アクセシブル名の計算では、ARIA のラベル属性が <title> より優先されます
(aria-labelledby > aria-label > 直接の子要素である <title>)。注:ブラウザーによっては、ポインターを合わせたときに <title> がツールチップとして表示されますが、これは可視テキストや実際のアクセシブルなツールチップの代わりにはなりません。キーボード、タッチ、音声入力を使うユーザーが見つけられない場合があります。
重大:ボタンやリンク内のアイコン
アクセシブル名は HTML コントロール側で設定し、SVG アイコンは非表示にします。
<button type="button">
<svg aria-hidden="true" viewBox="0 0 24 24"><path d="M6 6 18 18M18 6 6 18"></path></svg>
Close
</button>
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" viewBox="0 0 24 24"><path d="M6 6 18 18M18 6 6 18"></path></svg>
</button>
ボタンと非表示のアイコンの両方に、同じ名前を別々に設定しないでください。重複した、または一貫しない読み上げが生じます。操作内容が分かりにくい場合は、可視ラベルを使用してください。見慣れたアイコンでも、製品によって意味が異なることがあります。
すでにラベルが付いているボタン(例:テーマセレクター)内で、<img> を使って外部 SVG アセットを読み込む場合は、ボタンが名前を提供するため alt="" を使用します。外部の <img> で読み込んだ SVG は、周囲のボタンから currentColor を継承しない点に注意してください。表示されるすべての背景でアセット自体の色を検証するか、手動のテーマに追従させる必要がある場合はパスをインライン化してください。
重大:アクセシブル名と説明 — ARIA の関係を正しく設定する
SVG のアクセシブル名の優先順位:aria-labelledby > aria-label > 直接の子要素である
<title> > その他のフォールバック。説明の優先順位:aria-describedby > 直接の子要素である <desc>。
<svg role="img" aria-labelledby="weather-title" aria-describedby="weather-desc" viewBox="0 0 320 180">
<title id="weather-title">Weekly temperature trend</title>
<desc id="weather-desc">Temperatures rise from 12 degrees Monday to 21 degrees Friday.</desc>
</svg>
HTML ドキュメント全体で ID が一意になるようにしてください。同じ SVG ID を固定で使用するコンポーネントを繰り返し使うと、あるインスタンスが別のインスタンスによってラベル付けされる場合があります。タイトルと説明の両方の ID を aria-labelledby に指定しないでください。両方の文字列が連結されてアクセシブルな 名前 になるため、名前には aria-labelledby を、説明には別途 aria-describedby を使用してください。重要な情報を <desc> に埋め込まないでください。長い SVG の説明をたどる際の支援技術(AT)の対応はさまざまです。重要な詳細は、代わりに可視の HTML に記載してください。
中程度:複雑なグラフィック、図、グラフ
複雑な SVG には、長いアクセシブル名だけでは不十分です。簡潔な名前、目的や結論を示す可視の要約、必要に応じて構造化された HTML による完全なデータ、インタラクティブな場合はキーボードで操作できるコントロールが必要です。
<figure>
<svg role="img" aria-labelledby="visitors-title" aria-describedby="visitors-summary" viewBox="0 0 640 360">
<title id="visitors-title">Website visitors from January to March</title>
</svg>
<figcaption id="visitors-summary">
Visitors increased each month, from 12,400 in January to 19,200 in March.
</figcaption>
<details>
<summary>View the chart data</summary>
<table>
<caption>Monthly website visitors</caption>
<thead><tr><th scope="col">Month</th><th scope="col">Visitors</th></tr></thead>
<tbody><tr><th scope="row">January</th><td>12,400</td></tr></tbody>
</table>
</details>
</figure>
詳細な表を aria-label/<title>/<desc> に重複して記載しないでください。長い画像名の文字列はたどりにくくなります。ARIA Graphics Module では構造化されたロール(graphics-document、graphics-object、graphics-symbol)が定義されていますが、実際の AT の組み合わせで対応状況をテストする必要があります。これらを使っても、同等のテキスト表現が不要になるわけではありません。グラフ固有の要件については、skills/charts-graphs/SKILL.md を参照してください。
再利用するアイコンと SVG スプライト
<svg aria-hidden="true" hidden>
<symbol id="icon-download" viewBox="0 0 24 24">
<path d="M12 3v12m0 0 5-5m-5 5-5-5M5 21h14"></path>
</symbol>
</svg>
<button type="button">
<svg aria-hidden="true" viewBox="0 0 24 24"><use href="#icon-download"></use></svg>
Download report
</button>
共有シンボル内の名前は、個々のインスタンスに適しているとは限りません。「Arrow」は、文脈によって「次へ」「前へ」「展開」「折りたたむ」のいずれにもなり得ます。共有シンボルではなく、コントロールまたは外側のレンダリング済みインスタンスに名前を付けてください。外部の <use> の参照先には、実在する別個の要素(通常は ID を持つ <symbol>)を指定する必要があります。再帰的な自己参照は作成しないでください。
中程度:色、コントラスト、テーマ
.icon {
fill: none;
stroke: currentColor;
stroke-linecap: round;
stroke-width: 2;
}
currentColor は便利ですが、必須ではありません。複数の色を使うグラフィックでは、複数のセマンティックトークンが必要になる場合があります。すべてのテーマで、意味のある組み合わせを一つずつ検証してください。色だけに頼らず、状態や系列、選択状態を示すテキストラベル、パターン、線のスタイル、形状を追加してください。SVG 内のテキストにもテキストのコントラスト要件が適用されます。必須のグラフィック情報には通常 3:1 のコントラスト比が必要ですが、意味のあるグラフィックに含まれているという理由だけで、装飾的な細部に 3:1 のコントラスト比が必要になるわけではありません。
@media (forced-colors: active) {
.icon { color: ButtonText; }
.chart-line { fill: none; stroke: CanvasText; }
.chart-line[data-selected="true"] { stroke: Highlight; stroke-width: 4; }
}
すべてのパスに無差別に fill と stroke の両方を設定しないでください。線画が塗りつぶされた形状になることがあります。forced-color-adjust: none は、不可欠であり、複数のシステムパレットでテスト済みの場合を除き、使用しないでください。
SVG 内のテキスト
重要なラベルを表示して読みやすく保ち、テキストのコントラスト要件を満たしてください。書体を保つためだけに、重要なラベルをパスに変換しないでください。また、実際のテキストによる代替手段の代わりに、font-size="0"、キャンバス外への配置、透明な SVG テキストを使用しないでください。重要な説明は HTML で提供してください。拡大縮小やズームをテストしてください。外側の SVG が拡大縮小されても、SVG 内のラベルが重なったり、切れたりすることがあります。<foreignObject> を使うと HTML を SVG に埋め込めますが、描画やフォールバックが複雑になります。同じ結果を得られる場合は、SVG の外側に通常の HTML を使用してください。
重大:インタラクティブな SVG
SVG 内で操作させるよりも、グラフィックの近くにネイティブの HTML ボタン、リンク、開閉可能な要素を配置する方法を優先してください。
<div class="map">
<svg aria-hidden="true" viewBox="0 0 640 360"></svg>
<ul class="map-locations">
<li><a href="/locations/ottawa">Ottawa service centre</a></li>
</ul>
</div>
SVG 内で操作させる必要がある場合は、実際のナビゲーションには SVG の <a href="…"> を使用し、目的を説明するアクセシブルネームを付け、論理的な DOM 順序とフォーカス順序を保ち、想定されるキーボード操作に対応し、視認できて切り取られないフォーカスインジケーターを表示し、ターゲットサイズの要件を満たし、選択済み/展開済み/押下状態を公開してください。音声入力で使えるよう、アクセシブルネームには表示ラベルを含めてください。視覚的なレイアウトを視覚以外の方法で操作できない場合は、同等の HTML リストまたは表を用意してください。すべてのデータポイントをタブ順序に含めないでください。数百か所のフォーカス位置があると、視覚化には技術的にアクセスできても、実際には使いものにならなくなります。<path>/<g> に tabindex="0" とクリックイベントリスナーだけを追加して、「ボタン」を作らないでください。ネイティブのボタンのセマンティクスもキーボード操作も提供されません。キーボードで操作できないインタラクティブな SVG は重大です。
深刻:動き、アニメーション、点滅
.loading-icon { transform-origin: center; }
@media (prefers-reduced-motion: no-preference) {
.loading-icon { animation: spin 1s linear infinite; }
}
動きを抑えるために、包括的な svg * ルールを使用しないでください。無関係なコンポーネントに影響したり、意味のある状態を上書きしたりする可能性があります。対象となるアニメーションコンポーネントに限定し、理解しやすい静的な状態を定義してください。
@media (prefers-reduced-motion: reduce) {
.diagram-panel { animation: none; transition: none; }
}
<animate>/<animateTransform> では begin="indefinite" を使用し、prefers-reduced-motion: no-preference が確認された場合に限り、beginElement() を呼び出して再生してください。
3 Hz 以上で点滅する場合、急速な SVG アニメーションは重大です(WCAG 2.3.1)。これは、動きを抑える設定に従うだけでは解決しません。点滅のしきい値は、設定に関係なく適用されます。WCAG 2.2.2 では、5 秒以上続く、不可欠ではない移動、点滅、自動更新コンテンツに対して、一時停止/停止/非表示の操作を用意する必要があります。WCAG 2.3.3(インタラクションによるアニメーション、AAA)では、ユーザーが不可欠ではない、インタラクションをきっかけとする動きを無効にできる必要があります。prefers-reduced-motion に従う方法は、AA でも有効です。
レスポンシブ SVG とズーム
グラフィックが内部の座標系を切り取らずに拡大縮小されるよう、viewBox を保持してください。最適化の過程でこれを削除することは軽微な問題にとどまらず、流動的なレイアウトを壊します。
.responsive-diagram { display: block; max-inline-size: 100%; block-size: auto; }
ズームを 200%/400% に設定し、幅の狭いビューポートでもテストしてください。キャンバスが拡大縮小できても、ラベルが再配置されたり読みやすさが保たれたりするとは限りません。複雑な図では、簡略化した小画面向けの表示と、その横に配置する HTML の説明を検討してください。柔軟性のない SVG レイアウトを補うために、ページのズームを無効にしないでください。
スタンドアロン SVG ドキュメント
ブラウザーで直接開かれる SVG は <img> ではなくドキュメントです。名前空間、言語、アクセシブルな名前を含めてください。
<svg xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="diagram-title"
viewBox="0 0 800 450" lang="en" xml:lang="en">
<title id="diagram-title">Request approval workflow</title>
</svg>
スタンドアロンファイルが複雑な場合は、ユーザーが開く場所の近くに、同等の HTML 形式の説明へのリンクを配置してください。
重要:セキュリティ、サニタイズ、ビルド処理
SVG は、スクリプト、イベントハンドラー、リンク、外部リソース、CSS、アニメーション、フィルター、<foreignObject> を介した埋め込み HTML を含めることができる、アクティブな XML 形式です。**画像のように見えるファイルを、自動的に不活性なコンテンツとして扱ってはいけません。**アクセシビリティメタデータは処理後も保持されなければなりませんが、セキュリティ境界を弱めてまで保持してはいけません。セキュリティチェックとアクセシビリティチェックは、同じ最終成果物に対して実施してください。
処理前に SVG の信頼レベルを分類してください:
| ソース | 必要な対応 |
|---|---|
| 作成者が管理(リポジトリ内でレビュー済みのアイコン) | 変更をレビューし、ビルドツールを制限し、最終出力を検証する |
| 管理されたソースから生成(Mermaid/チャートレンダラー) | レンダラーと設定を依存関係として扱い、生成された SVG を検証する |
| プラットフォームによって生成(ホスト型の図表サービス) | プラットフォーム/レンダラーのバージョンを記録し、ホストされた結果を検証する |
| 信頼できない(アップロード、貼り付けられたマークアップ、ユーザー編集、リモートファイル、AI 生成) | 入力制限を適用し、安全にパースし、SVG 対応の許可リストでサニタイズしてから、表示またはエクスポート前に検証する |
インライン SVG、<object>、<embed>、スタンドアロンドキュメントは、<img> よりも広範な機能を持つため、より慎重な確認が必要です。現在 <img> で安全な SVG も、後から他の人がダウンロードして直接開いたり、インラインで埋め込んだりする可能性があります。すべての埋め込みコンテキストに共通する単一のアクセシビリティ対応方法はありません。
**信頼できない SVG は、メンテナンスされている SVG 対応のサニタイザー/許可リスト(例:レビュー済みの SVG プロファイルを使用した DOMPurify)でサニタイズしてください。**汎用 HTML 許可リストでは、必須の SVG 機能が削除されたり、不要な機能が許可されたりする可能性があります。次のことは行わないでください:
- サニタイズする前に、信頼できない SVG を
innerHTMLで挿入する - 整形式の XML を安全な SVG とみなす
DOMParser、XMLSerializer、フォーマッター、SVGO をサニタイザーとして扱う- 正規表現を SVG サニタイザーとして使用する
- ファイル名、MIME タイプ、画像プレビューの成功を安全性の証明とみなす
- サニタイズ後のマークアップを、後から信頼できない文字列で変更する
サニタイズでは、次のものを削除または拒否してください:<script> とイベントハンドラー属性(onclick)、javascript: およびその他の未承認 URL スキーム、予期しない外部 href/xlink:href、CSS/@import/url() 内の外部リソース、明示的に必要とされない <foreignObject>/埋め込み HTML、未承認のアニメーション/インタラクティブ要素、処理命令、DTD、外部エンティティ。同一ドキュメント内の #fragment 参照(<use href="#icon">、marker-end="url(#arrowhead)")は通常必要であり、安全に許可できます。ただし、許可するすべてのフラグメントが、同じサニタイズ済みドキュメント内の許可された要素を参照していることを検証してください。フラグメントを許可することは、任意の外部 URL を許可することを意味しません。
サーバー側で処理する場合は、XML を安全にパースしてください:DTD 処理と外部エンティティの解決を無効にし、パーサーによるネットワーク/ローカルファイルへのアクセスを防ぎ、明示的に必要かつ安全に保護されている場合を除き、XSLT/XInclude を避け、入力/ネスト/エンティティの制限を設定し、パース/サニタイズに失敗した場合はフェイルクローズしてください。
リソース消費を制限してください — SVG はスクリプトを実行せずに CPU/メモリを枯渇させる可能性があります。入力/展開後のサイズ、要素/属性の数、パスの複雑さ、<use> のネスト深度、フィルターの複雑さ、埋め込みデータ URL のサイズ、レンダリング寸法に上限を設けてください。再帰参照やポリシーを超えるコンテンツは拒否してください。
最適化中もアクセシビリティを維持する — ビルドを設定し、次のものを保持します。
viewBox、使用する場合は <title>/<desc>、role/aria-*/言語属性、
ARIA、<use>、クリップパス、マスク、フィルター、グラデーションから参照される ID、
セマンティックな <text>、フォーカス/テーマ/強制カラー/視差効果を減らす設定のスタイル、公開スプライトのシンボル ID。繰り返し使うインラインコンポーネントには一意の ID を生成します。すべてのコピーを同じ ID に統合するオプティマイザーは、レンダリングとアクセシブルネームの両方を損ないます。オプティマイザーのバージョンを固定し、代表的なフィクスチャを使って設定変更をテストします。編集に適したプロファイルと本番用の最適化プロファイルは分けてください。
推奨される処理順序:(1)入力/リソースの制限を適用する、(2)安全な XML 設定で解析する、(3)承認済みプロファイルで信頼できない入力をサニタイズする、(4)制御された変換のみを適用する、(5)レビュー済みのバージョン管理された設定で最適化する、(6)最終 SVG のセキュリティとアクセシビリティの両方を検証する、(7)検証済みの結果のみを挿入/配信/エクスポートする。後続の手順で信頼できないマークアップが入り得る場合は、その手順の後でもう一度サニタイズしてください。
制限の厳しい CSP は、安全でない SVG 機能の一部による影響を軽減しますが、解析、サニタイズ、リソース制限、出力検証の代わりにはなりません。代替策ではなく、多層防御の一環として使用してください。
必要でないこと
- すべての SVG に
<desc>を付けること — 名前だけで意味を十分に伝えられる場合は、<title>+aria-labelledbyで十分です - 非インタラクティブな SVG 内のフォーカススタイル
- SVG がなくても内容を認識できる場合の
forced-colorsブロック - 装飾的な SVG に
role="img"を付けること — 代わりにaria-hidden="true"を使用してください
テスト
- コードレビュー: 各 SVG を装飾的/情報提供/機能的/複雑/インタラクティブに分類します。埋め込みパターンが適切か確認します。名前と説明の関係を調べます。繰り返し使うインラインコンポーネントに重複 ID がないか検索します。ビルド最適化で必要な属性が保持されることを確認します。ソースの信頼レベルを分類し、使用可能なすべての埋め込みコンテキストを特定します。サニタイザー/パーサー/オプティマイザー/レンダラーの設定変更をレビューします。最終出力の検証でセキュリティとアクセシビリティの両方を確認できることを確かめます
- ブラウザー/支援技術: アクセシビリティツリーに期待するロール/名前/説明があることを確認します。装飾的なアイコンが読み上げられず、名前のあるグラフィックが一度だけ読み上げられることを確認します。すべての SVG コントロールをキーボードのみで操作します。音声入力で指定する名前と表示ラベルを照合します。200%/400% のズームと狭いビューポートをテストします。サポートするすべてのテーマをテストします。
prefers-reduced-motion/prefers-contrast/強制カラーをテストします。色に依存しない意味伝達を確認します。SVG が不可欠な場合は、画像を利用できない状態でもテストします - セキュリティ/処理: 有効なフィクスチャと敵対的なフィクスチャの両方を用意します。サニタイザー単体ではなく、パイプライン全体をテストします — スクリプト/イベントハンドラーが拒否されること。安全でない URL スキームが拒否されること。予期しない外部リソースがブロックされること。DTD/外部エンティティが解決されずに拒否されること。未承認の
<foreignObject>が拒否されること。再帰的/過剰な<use>が拒否されること。サイズ超過/複雑すぎる入力が拒否されること。許可された同一ドキュメント内の参照は引き続きレンダリングされること。繰り返し使うインラインインスタンスが一意の ID を維持すること。最適化後の出力が引き続きセキュリティ規則に準拠し、アクセシブルな代替コンテンツと一致すること。サニタイザー/パーサー/オプティマイザー/レンダラー/許可リスト/依存関係のバージョンを変更するたびに、これらを実行します。
自動化ツールは、<img alt> の欠落、一部のアクセシブルネームの問題、重複 ID、コントラストの失敗、特定の ARIA エラーを検出できます。しかし、代替コンテンツが同等か、グラフィックが本当に装飾的か、インタラクティブなビジュアライゼーションが使いやすいかは判断できません。自動テストに合格しても、SVG の手動レビューに代わるものではありません。
よくある失敗
| 失敗 | 修正方法 |
|---|---|
<img src="graphic.svg"> に alt がない | 文脈に適した alt を追加します。装飾目的の場合は alt="" を指定します |
すべての HTML <img> に role="img" を追加する | ネイティブの <img> のセマンティクスと alt を使用します |
タイトルと説明の両方の ID を aria-labelledby に設定する | 名前には aria-labelledby、説明には aria-describedby を使用します |
長い表を <desc> に入れる | 重要な詳細は、構造化された HTML で視認できる形で示します |
| 同じタイトル ID を持つインラインアイコンを繰り返し使用する | インスタンスごとに一意の ID を生成するか、直接 aria-label を使用します |
| スプライトシンボルが自身を参照する | シンボル内に実際のパスを配置し、描画されるインスタンスからのみ参照します |
| 強制カラーの CSS で、すべてのパスの塗りと線の両方を設定する | 形状を変更せず、対象を絞ってシステムカラーを適用します |
クリック可能な <path> にクリックハンドラーしかない | ネイティブ HTML コントロールを使用するか、完全なキーボード操作のセマンティクスを実装します |
svg * と !important を使って動きを抑制する | アニメーションする各コンポーネントを対象にし、意味のある静的な状態を定義します |
| 整形式 XML をサニタイズ済み SVG として扱う | 安全に解析し、SVG に対応した許可リスト方式のサニタイザーを適用します |
<script> を削除する正規表現をサニタイザーと呼ぶ | 保守され、文書化されたポリシーを備える SVG 対応サニタイザーを使用します |
| サニタイズ後の SVG を信頼できない文字列で変更する | 以降の変換を制御するか、最終検証の前に再度サニタイズします |
| CSP をサニタイズの代替として扱う | CSP は追加の保護層としてのみ使用します |
| SVG が「まだ正しく見える」という理由で最適化ツールの更新を受け入れる | 最適化ツールのバージョンを固定してテストし、セマンティクス、参照、代替テキストを検証します |
完了チェックリスト
- すべての SVG を用途(装飾/情報提供/機能/複雑/インタラクティブ)と埋め込みコンテキストで分類している
- 装飾用 SVG:
aria-hidden="true" focusable="false"を指定し、<title>と<desc>を含めていない - 意味のある
<img>SVG には適切なaltがあり、装飾目的の外部画像にはalt=""を指定している - 意味のあるインライン SVG:
role="img"+<title>+aria-labelledby(またはaria-label)を指定している - 複雑な SVG:名前 + 視認できる概要 + 構造化された HTML の詳細がある
- 名前付きコントロール内のアイコンが、コントロールのアクセシブル名を重複して伝えていない
- 名前/説明に正しい ARIA の関連付けを使用している(labelledby ≠ describedby)
- 最適化後もすべての参照 ID が保持され、繰り返し使用されるインスタンス間で一意になっている
- 適切な箇所で
currentColorを使用し、テキスト以外の要素で 3:1 のコントラストを満たしている -
viewBoxが存在し、保持されている - アニメーション SVG は
prefers-reduced-motion: no-preferenceの場合にのみ動作し、設定にかかわらず 3 Hz 以上の点滅がない - インタラクティブな SVG をキーボードで操作でき、フォーカスが視認できる。ネイティブのラッパー要素を優先する
- 信頼できない SVG は、
innerHTMLに挿入する前に SVG 対応の許可リスト方式でサニタイズする - スクリプト、イベントハンドラー、安全でない URL スキーム、外部リソース、DTD/エンティティを拒否する
- リソース制限(サイズ、要素数、
<use>の深さ、フィルターの複雑さ)を適用する - 最後に重要な変換を行った後で、セキュリティとアクセシビリティの検証を実施する
- サポート対象の OS/ブラウザーの組み合わせで、スクリーンリーダーを使ってテストしている
主な WCAG 基準
- 1.1.1 非テキストコンテンツ(A) — 意味のある SVG にテキストによる代替がない場合は重大
- 1.3.1 情報及び関係性(A)
- 1.4.1 色の使用(A)
- 1.4.3 コントラスト(最低限)(AA)
- 1.4.5 文字画像(AA)
- 1.4.11 非テキストのコントラスト(AA)
- 2.1.1 キーボード(A)
- 2.2.2 一時停止、停止、非表示(A)
- 2.3.1 3 回の閃光、又は閾値以下(A) — 点滅/ストロボを伴うアニメーションでは重大
- 2.3.3 インタラクションによるアニメーション(AAA)
- 2.5.3 ラベルを含む名前(A)
- 2.5.8 ターゲットサイズ(最低限)(AA)
- 4.1.2 名前、役割、値(A)
参考資料
- ベストプラクティスガイド全文
- SVG アクセシビリティ API マッピング
- WAI-ARIA グラフィックスモジュール
- DOMPurify
- SVGO ドキュメント
- OWASP XML 外部エンティティ防止チートシート
- WCAG 2.2 解説 1.4.11 非テキストコントラスト
- MDN:prefers-reduced-motion
今後の標準動向: 非テキストコントラスト比 3:1 は、WCAG 3.0 の APCA モデルで変更される可能性があります。現行の 3:1 要件は引き続き適用されます。 https://www.w3.org/TR/wcag-3.0/ をご確認ください。