コンテンツにスキップ
svelte-vitals
日本語
Esc
移動開く⌘Jプレビュー
このページの内容

a11y/accessible-name · アクセシブルネームのない操作要素

ボタン・リンク・画像ボタン・iframe には、アクセシブルネームを算出できる手がかりが必要です。

重大度: warning · カテゴリ: a11y

チェック内容

<button><a href="…"><input type="image"><iframe> のうち、アクセシブルネームを算出できないものを検出します。コンポーネントのソースを解析します。

次のいずれかが存在すれば名前の手がかりとみなし、検出しません。

  • 空白以外のテキストを含む子孫、例: <button>Save</button>
  • aria-labelaria-labelledbytitle 属性。リテラルで空でない値、または式(レンダリング結果は静的にはわからなくても、属性が存在すること自体で十分とみなします)。title を数えるのは名前の計算が最後の手段として使うからですが、コントロールの命名手段としては貧弱です。タッチ操作のユーザー、キーボード操作のユーザー、そして多くのスクリーンリーダーや拡大鏡のユーザーには届きません。可視テキストか aria-label を優先してください。
  • alt を持つ子孫 <img>。非空のリテラル、または式(上の aria-label と同じ扱い)。
  • <input type="image"> 自身の alt(同じ規則)。
  • 名前を与えている <label>。囲んでいる場合と、forid を指している場合。名前の計算ではこの label の段階が要素自身のサブツリーより先に来ます。対象は <button><input type="image"> のみで、<a> にこの段階はありません。有効なのは label 自身が何かを与えている場合に限られ、空だと証明できる label はコントロールを無名のままにするので引き続き検出されます。また囲む label が届くのは最初の labelable 要素だけなので、同じ label 内の 2 つ目のコントロールは単独で判定されます。for 経由の判定は同一ファイル内に限られ、他コンポーネントの label は既知の制限です。

名前の手がかりが見つからない場合でも、次のものは検出しません。

  • 内容が静的に判断できない要素。{式} の子、コンポーネントの子、{@render …}{@html …}<slot><svelte:fragment>(内容は親から渡される)、ハイフンを含むカスタム要素(shadow root が内容を供給しうる)、あるいは要素自身へのスプレッド属性。

このルールは「名前がないと証明できる」ものだけを検出し、動的な内容を推測することはありません。

名前空間はここでは追跡していません。<svg> 内の <a href> は HTML の <a> として判定されるため、計算可能なアクセシブルネーム(テキスト子孫・aria-labelaria-labelledby<title> のいずれか)を持たない SVG のリンクは報告されます。SVG のアクセシビリティ指針が求めることと同じなので、理由は違えど結論は変わりません。

<button></button>
<a href="/x"><img src="i.png" /></a>

iframe に対するチェック

<iframe> の名前になるのは titlearia-labelaria-labelledby のみです。リテラルで空でない値、または式(判定不能 → 命名ありとみなす。上と同じ扱い)。空のリテラル title="" は名前を算出しないため検出されます。子コンテンツは決して数えません: iframe の中身はフレーム非対応ブラウザ向けのフォールバックであってレンダリングされる内容ではないので、内容からの命名という段階が存在しません。また <label> も名前を与えられません(iframe は labelable ではありません)。

iframe に対するチェックに限って、次のものは検出しません。

  • aria-hidden="true"hidden 属性、role="presentation"/role="none" を持つ iframe。名前が誰の役にも立たない、隠しトラッキング/解析フレームの類型です。これらの属性が式値の場合は判定不能 → 検出しない、というルール全体の規約どおりです。このスキップは iframe に対するチェックだけに適用されます: 隠れた無名ボタンは引き続き報告されます。
  • <svg> 内の iframe。SVG に iframe はなく、要素はレンダリングされません。(上の <a> の注記より狭い扱いです。SVG の <a> は本物のリンクなので両方の名前空間で判定されます。)
  • スプレッド属性を持つ iframe。レンダリングされる属性が判定不能です。

なぜ重要か

支援技術はインタラクティブなコントロールをアクセシブルネームで読み上げます。名前がないと、スクリーンリーダーは「ボタン」「リンク」といった素のロールにフォールバックし、ページ上の他の無名コントロールと区別がつかなくなります。アイコンだけに頼っている晴眼ユーザーにはこのギャップが見えないため、問題は見た目のレビューでは見つかりません。無名の <iframe> は同じ問題をより大きなスケールで起こします: 素の「フレーム」として読み上げられ、中に入るまで埋め込み動画なのか地図なのか広告枠なのか知るすべがありません。

修正方法

要素に可視テキスト、ラベル付け用の属性、あるいはアイコン画像への alt を与えます。

<button aria-label="Save">💾</button>
<a href="/x"><img src="i.png" alt="Home" /></a>
<input type="image" src="search.png" alt="Search" />
<iframe src="https://example.com/embed" title="Product demo video" loading="lazy"></iframe>

Svelte コンパイラとの重複

iframe については、title が無いときコンパイラが a11y_missing_attribute を警告します。この重複は意図的です: コンパイラの警告はビルドログに流れるだけで、スコアもゲートも抑制もしません。一方このルールはヘルススコアに反映され、svelte-vitals-disable-next-line を尊重し、--fail-on で CI を失敗させられます。

コンパイラのチェックは「title の存在のみ」を見るため、相違点が4つあります。

  • aria-label/aria-labelledby はこのルールではフレームの名前になりますが、コンパイラは警告し続けます。コンパイラを黙らせるのは title だけです。
  • 空の title="" はコンパイラを黙らせますが名前を算出しないため、このルールは報告します。空 title は何も命名せずにビルド警告を消す常套手段です。
  • 隠し・プレゼンテーション用の iframe(aria-hidden="true"hiddenrole="presentation"/"none")はコンパイラが警告し、このルールはスキップします。
  • 式値の title はどちらも黙らせます。

ボタン・リンク・画像ボタンに対するチェックにはコンパイラの対応物がありません(a11y_missing_content が対象にするのはアンカーと見出しだけで、根拠も異なります)。

モードによる違い

ありません。このルールが読むのは同じ .svelte / .ts のソースファイルなので、CLI、Vite プラグインのビルド、ライブダッシュボードの静的ベースラインのいずれでも結果は同一で、レンダリング済み HTML の解析で再評価されることもありません。--route で実行範囲を絞ると、このルールは動きません。コンポーネントスコープのルールには、検出を紐づけるルートが無いためです。

無効化

このルールからは見えない別の方法(ラップしている label 要素など)で名前を与えている場合は、<!-- svelte-vitals-disable-next-line a11y/accessible-name --> で個別の要素を抑制するか、ルールを無効化してください。

export default {
  rules: {
    'a11y/accessible-name': 'off'
  }
};