AIにSvelteのコードをレビューさせたら、アクセシビリティを指摘された
背景
実務でAIにコードレビューを依頼すると、role="button"やaria-label="閉じる"といった属性をよく指摘されます。
「実装上エラーは出ていないし、画面上は動いているからいいや」ではなく、なぜこれらが必要なのか、その理由を正しく理解するためにまとめてみました。
アクセシビリティ(A11y)とは
「アクセシビリティ(Accessibility)」という言葉は、Access(アクセス)とAbility(能力・できること)を組み合わせた言葉です。
よくa11y と省略されていますが、これは「A」から「y」の間の11文字のことを指しています。
Webアクセシビリティとは、障害のある人だけでなく、「あらゆる人が、どのような状況でもWebを使えるようにすること」 を指します。
例えば
- 視覚障がいのある方: スクリーンリーダー(音声読み上げソフト)で耳から情報を得る。
-
マウスが使えない方:: キーボードの
Tabキーだけで全てのボタンやリンクを操作する。 - 一時的な不自由: 怪我で片手が使えない、太陽が眩しくて画面がよく見えない状況など。
こうした状況で、「この要素は何者で、どう操作すべきか」という情報を正確に伝えるために「HTMLタグだけでは伝わらない情報をrole属性やaria属性で補うために指定すべきだ」とAIに指摘されていました。
Svelteとアクセシビリティについて
Svelteは、開発段階からアクセシビリティを意識させる仕組みが組み込まれています。
1.開発・コンパイル時の警告
例えば、<div> タグに onclick イベントを付けただけで、キーボード操作の考慮がない場合、警告(a11y_click_events_have_key_events)を出します。
2.「Runes」による状態管理とa11yの同期
Runesでアクセシビリティ属性を制御することも可能です。
メニューの開閉状態(isOpen)を$stateで管理し、aria-expandedの値を同期することで、支援技術(スクリーンリーダー)に対して常に正確な情報を伝えることができます。
Svelte 5での実装例
Svelte 5で実装してみた例です。
状態(isOpen)と属性(aria-expanded)を連動させています。
<script>
let isOpen = $state(false);
</script>
<button
onclick={() => isOpen = !isOpen}
aria-expanded={isOpen}
>
メニュー
</button>
{#if isOpen}
<section aria-label="メニュー詳細情報">
コンテンツ内容...
</section>
{/if}
よく見る属性まとめ
AIの指摘によく指摘される属性をまとめました。
| 属性 | 役割 | 具体例 |
|---|---|---|
| role="..." | 要素の「役割」を定義 |
div をボタンにする際、role="button" と明示する |
| aria-label | テキストがない要素に「名前」を付与 | アイコンだけの「×」ボタンに aria-label="閉じる" と付ける |
| aria-hidden | 支援技術から「隠す」 | 装飾目的のアイコンなど、読み上げ不要な要素を無視させる |
| aria-expanded | 「開閉状態」を伝える | アコーディオンやメニューが現在開いているかを示す |
まとめ
AIがroleやaria-labelなどを指摘していたのはWebアクセシビリティの品質を満たすためでした。アクセシビリティについて簡単にまとめてみましたが、かなりの種類があったためコンポーネントの実装などから少しずつ取り組みながら学んでいきたいと思います。
Discussion