# 表示と名前が食い違うボタンとリンク

Source: https://easeweb.dev/learn/label-in-name
Topics: ボタンとリンク > アクセシブルな名前が、表示されているテキストで始まる (WCAG 2.5.3)
The fix: 各ボタンの名前を、表示されている言葉で始めます。aria-label を外して「かごに入れる」を名前にし、商品名は aria-describedby でカードの見出しを指して説明にするか、商品名を表示の言葉の後ろに、ボタン内の視覚的に隠したテキストとして入れます。
Test with: speech input, screen reader, keyboard
References: https://www.w3.org/WAI/WCAG22/Understanding/label-in-name.html https://www.w3.org/WAI/WCAG22/Techniques/failures/F96 https://www.w3.org/WAI/WCAG22/Techniques/general/G208 https://www.w3.org/WAI/WCAG22/Techniques/general/G211 https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/ https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-describedby

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

生活雑貨のショップが、商品を一覧で並べています。各カードには写真、商品名、価格、濃い色の「かごに入れる」ボタンがあります。開発者はボタンの名前がすべて同じだと気づき、それぞれに商品名を入れた `aria-label`「Linen toteをカートに追加」を付けました。スクリーンリーダーのボタン一覧では分かりやすくなります。ところが音声操作の利用者がカードを見て「かごに入れるをクリック」と話しても、何も起きません。その名前のボタンがページにないからです。スクリーンリーダー利用者には「Linen toteをカートに追加、ボタン」と聞こえますが、ページやヘルプの文は「かご」と書いています。

## 確認できる問題

`aria-label` はボタン自身のテキストに代わってアクセシブルな名前になるため、ボタン上の「かごに入れる」は名前にまったく含まれません。WCAG 2.5.3「ラベルを含む名前」（レベルA）は、見えるテキストのラベルがある操作要素の名前に、そのテキストが含まれることを求めています。見えている言葉を話して操作できるようにするためです。名前には表示どおりの言葉が含まれている必要があり、大文字小文字やほとんどの句読点は問いません。WCAGの解説書（Understanding）は、名前がその言葉で始まるのが望ましい実践だとしています。

同じ問題は、次の形でも起きます。
- カードの見出しだけを指す `aria-labelledby`。名前が「Linen tote」になり、「かごに入れる」が抜けます。
- 表示の言葉を `aria-hidden="true"` で包み、「Linen toteをカートに追加」のような別の言葉を視覚的に隠して入れる形。
- 「かご (2)」と表示し、`aria-label="ショッピングカート"` を付けた、アイコンと文字のリンク。

「Linen tote、かごに入れる」のように、言葉を含んでいても先頭にない名前は2.5.3を満たしますが、望ましい形ではありません。「かごにLinen toteを入れる」のように表示の言葉の間に隠した言葉を挟むと、言葉は残っても一続きではなくなります。解説書はこれを将来の不適合の候補として挙げているだけですが、失敗例F96はすでにこの形を例に挙げています。画面の言葉が、一続きの文字列として名前に含まれないからです。不適合として扱ってください。

## 利用者への影響

aria-label は助けるつもりで付けられ、スクリーンリーダーのボタン一覧では実際に役立ちます。各商品が別々の項目になるからです。それ以外の場面では、聞こえる言葉と見える言葉を食い違わせます。

## 自動チェックとAIの限界

axe にはこの問題を調べる `label-content-name-mismatch` ルールがありますが、試験的なルールのため、指定したときだけ実行されます。この診断ではこのルールを実行し、見つかったものを人が確かめる要確認項目として報告します。このルールは `aria-label` や `aria-labelledby` を表示テキストと比べるため、修正前の例、見出しだけを指す `aria-labelledby`、アイコンのリンクは検出できます。ただし、中身の隠したテキストで名前が付いたボタンや、`<input type="submit" value="検索" aria-label="商品を探す">` のような入力ボタンは調べません。この診断独自のチェックが、画面に描かれた言葉とブラウザーが算出した名前を比べて、それらを検出します。「ボタンの名前がすべて同じ」という指摘へのAIの手早い修正は、修正前の例そのものになることがあります。ボタンごとに、モデルが選んだ言葉の aria-label を付けてしまいます。

## 修正前：別の言葉の aria-label

```html
<ul class="products">
  <li class="card">
    <img src="linen-tote.jpg" alt="">
    <h3>Linen tote</h3>
    <p class="price">$48</p>
    <button type="button" aria-label="Linen toteをカートに追加">かごに入れる</button>
  </li>
  …
</ul>
```

```css
.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 1rem;
}
```

ボタンには「かごに入れる」と表示されていますが、名前は「Linen toteをカートに追加」です。表示の言葉が名前にないため、「かごに入れるをクリック」はどこにも届きません。

## 修正後：ボタン自身の言葉にし、商品名を説明にする

```html
<ul class="products">
  <li class="card">
    <img src="linen-tote.jpg" alt="">
    <h3 id="product-linen-tote">Linen tote</h3>
    <p class="price">$48</p>
    <button type="button" aria-describedby="product-linen-tote">かごに入れる</button>
  </li>
  …
</ul>
```

```css
.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 1rem;
}
```

aria-label を外すと、ボタンのテキストが再び名前「かごに入れる」になります。見出しは説明になり、スクリーンリーダーは名前と役割の後に読み上げます。「かごに入れる、ボタン、Linen tote」です。「かごに入れるをクリック」はどのカードのボタンにも一致するため、音声操作は繰り返しのラベルのときと同じように番号を付け、利用者はどれかを選べます。

## 修正後：表示の言葉の後ろに、隠したテキストで商品名を入れる

```html
<ul class="products">
  <li class="card">
    <img src="linen-tote.jpg" alt="">
    <h3>Linen tote</h3>
    <p class="price">$48</p>
    <button type="button">かごに入れる<span class="visually-hidden"> Linen tote</span></button>
  </li>
  …
</ul>
```

```css
.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 1rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
```

名前は「かごに入れる Linen tote」になります。解説書が勧めるとおり画面の言葉で始まり、フォーカスしたときもボタン一覧でも、商品を区別できます。隠したテキストはページの普通のテキストなので、ブラウザーの翻訳で表示の言葉と一緒に訳されます。

## どの方法を選ぶか

どちらも名前を表示の言葉で始め、2.5.3を満たします。説明を使う方法は、名前を表示の言葉そのままに保ち、カードの見出しがボタンのすぐそばにある一覧に向いています。ただし説明はスクリーンリーダーのボタン一覧には出ず、一覧ではどの項目も「かごに入れる」のままです。説明の読み上げを切っている人もいます。隠したテキストは商品名を名前そのものに入れるため、どこに一覧されても各ボタンを区別できます。代わりにボタンごとに隠した span が1つ要ります。同じボタンがページに何度も並ぶときは隠したテキストを、はっきりした見出しのそばに数個並ぶだけなら説明を選びます。音声認識ソフトの違いもあります。DragonとWindowsの音声アクセスは名前の一部でも照合しますが、Appleの音声コントロールは名前全体が必要だと報告されています。隠したテキストの方法では、MacやiPhoneで「かごに入れるをクリック」と話してもボタンに届かず、番号に頼ることになるかもしれません。利用者の多くがApple製品を使うなら、ボタン一覧が短くなる利点と比べて選んでください。

## 実装の判断

**aria-labelかaria-describedbyか。** この二つは役割が違います。`aria-label`（と `aria-labelledby`）は名前を決めます。音声操作が照合し、スクリーンリーダーが最初に読み、ボタン一覧に表示するのが名前です。ボタンの文字は、この名前に置き換わります。`aria-describedby` は名前を変えずに説明を足し、説明は名前と役割の後に読まれます。音声操作は説明では照合せず、説明の読み上げを切っている人もいます。そのため、どちらを使うかは、操作要素に何が表示されているかで決まります。
- 言葉が表示されている：その言葉が名前なので、`aria-label` は付けません。どの商品か、補足の説明などは、説明にするか、名前の中で言葉の後ろに足します。
- アイコンだけが表示されている：残す言葉がないため、`aria-label` で名前を付けます。
- 言葉が表示されている操作要素の `aria-label` が安全なのは、その言葉で始まる場合だけです。その場合も、言葉の後ろに隠したテキストを置けば、ARIAなしで同じことができます。

**足す言葉は、ARIAよりHTMLで。** ボタン自身の `id` を先に、見出しの `id` を後に並べた `aria-labelledby="add-linen-tote product-linen-tote"` でも、隠したテキストと同じ名前「かごに入れる Linen tote」になります。ボタン内に span を入れられないコンポーネントでは、こちらが使えます。隠したテキストはidが要りません。どちらもページ上のテキストなので、ページと一緒に翻訳されます。マークアップに書いた `aria-label` はそうとは限らず、ブラウザーの翻訳機能によっては元の言語のまま残り、食い違いが戻ることがあります。

**表示の言葉を先頭に、一続きで。** 足す言葉は表示の言葉の後ろに置き、前や間には入れません。「Linen tote、かごに入れる」は適合しますが、見えている言葉で始まりません。「かごにLinen toteを入れる」は、利用者が話す言葉を分断します。

**言葉を言い換えない。** 「カート」と「かご」、「購入」と「注文」、「ログイン」と「サインイン」は、開発者には同じでも、音声認識には別の言葉です。名前にもヘルプの文にも、画面に出ている言葉を使います。

**アイコンと記号。** アイコンだけのボタンには見える言葉がないため、2.5.3の対象外です。言葉の名前が必要なことは、[名前がないアイコンだけのボタン](/ja/learn/icon-buttons)で扱っています。「次へ」の後ろの矢印のように、言葉に添えた記号はラベルの一部ではないため、名前は「次へ」で足ります。

**フォームの入力欄。** 同じ達成基準は入力欄のラベルにも当てはまります。入力欄の上に表示したラベルと違う aria-label は、[ラベルがない・表示と食い違うフォームの入力欄](/ja/learn/form-labels)で扱っています。

## 修正の確認

1. ブラウザーのアクセシビリティツリーで各ボタンとリンクを確認し、名前が表示されている言葉を含み、その言葉で始まることを確認する。
2. 音声操作で「かごに入れるをクリック」と話し、ボタンが反応するか、同じ言葉のボタンに番号が表示され、どれかを選ぶとそのボタンが押されることを確認する。他のボタンも、それぞれの言葉で同じように確認する。
3. スクリーンリーダーでTabキーを使って商品一覧を移動し、各ボタンが表示の言葉から読み上げられ、続いて商品名が読まれることを確認する。
4. ブラウザーでページを翻訳し、各ボタンの名前が表示テキストと一緒に翻訳されることを確認する。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通のボタンや商品カードのコンポーネントを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。音声認識ソフトによって、話した言葉の照合方法は異なるため、利用者が使う音声操作で確認してください。外部のウィジェットやコンテンツの編集者が追加するボタンも、同じように確認が必要です。表示の言葉で始まる名前が、商品について十分に伝えているかは別の問題です。リンクについては[リンクテキストが空、または「詳しくはこちら」だけのリンク](/ja/learn/link-text)で扱っています。実際に使用する支援技術で、操作全体を確認してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
