# ラベルやヒントがツールチップにしかない入力欄

Source: https://easeweb.dev/learn/title-tooltips
Topics: ボタンとリンク > ラベルや説明が、ツールチップだけでなく画面に表示される (WCAG 3.3.2)
The fix: 欄に必要な言葉は、すべて画面に表示します。各欄にlabel要素を付け、形式はラベルの下の行に書いてaria-describedbyで欄に結び付けるか、形式をラベルの中に書きます。そのうえでtitle属性を削除します。
Test with: keyboard, touch, screen reader, zoom
References: https://www.w3.org/WAI/WCAG22/Understanding/labels-or-instructions.html https://www.w3.org/WAI/WCAG22/Techniques/html/H65 https://html.spec.whatwg.org/multipage/dom.html#the-title-attribute https://html.spec.whatwg.org/multipage/input.html#the-pattern-attribute https://www.w3.org/WAI/tutorials/forms/instructions/ https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title

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

## 場面

ショップの購入手続きに「ギフトカード」の欄があります。空の入力欄が二つ横に並び、その横に「適用」ボタンがあります。デザインにラベルを置く場所がないため、各欄の名前は`title`属性に入れてあります。一つ目の欄にマウスポインターを重ねると「ギフトカード番号」、二つ目に重ねると「PIN」と小さなツールチップが出ます。スクリーンリーダーの利用者がTabキーを押すと「ギフトカード番号、編集テキスト」と聞こえます。目で見ている人がTabキーを押すと、フォーカスは空の欄に移るだけで、ほかには何も表示されません。スマートフォンにはポインターがないため、ツールチップはまったく出ません。どちらが16桁のカード番号で、どちらが4桁のPINなのかは、推測するしかありません。ラベルは表示したものの、形式はtitleに残したままのフォームもよくあります。「16桁」「4桁」はマウスポインターを重ねたときにしか出ないため、キーボードやタッチ操作の利用者には一度も見えません。

## 確認できる問題

3.3.2「ラベル又は説明」は、入力が必要な箇所に、ラベルや説明を求めています。その解説は、正しい入力に特定の決まりがあるときは特に、欄が求める形式もラベルや説明で示せるとしています。`title`は補足のテキストで、パソコンのブラウザーはマウスポインターが要素の上にある間だけ、ツールチップとして表示します。Tabキーで欄に移っても、タップしても何も出ません。HTML標準自体も、titleに頼るとキーボードだけやタッチだけで操作する人が取り残される、と注意しています。一つ目のフォームでは、二つの欄を見分ける言葉はtitleにしかありません。マウスを使わない人にとっては、ラベルがまったくないのと同じです。W3Cの達成方法H65はtitleで欄に名前を付ける方法ですが、検索ボタンの隣の検索欄のように、画面から目的が分かる欄のためのものです。この例では、画面上に欄を見分ける手がかりがありません。

アクセシビリティツリーを見ても、欠けているものはありません。`label`も`aria-label`も`aria-labelledby`もない欄は、`title`からアクセシブル名を取ります。そのため各欄には名前があり、4.1.2「名前（name）・役割（role）及び値（value）」は満たしています。足りないのは、画面に見える言葉のほうです。二つ目のフォームではラベルが画面にあり、titleは名前ではなく欄の説明になります。スクリーンリーダーは名前の後に「16桁」と読みます。しかしショップはその桁数しか受け付けないため、桁数は入力する前に知る必要のある説明です。それなのに画面には、マウスを使う人にしか表示されません。HTML標準は、`pattern`属性を使う欄には、そのパターンを説明するtitleを付けるよう求めています。そのため、形式がtitleにだけ書かれることもあります。

## 利用者への影響

スマートフォンやタブレットでは、誰もポインターを欄に重ねられません。タッチで操作する人には、障害の有無にかかわらず、ラベルも形式も見えません。

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

一つ目のフォームは、スクリーンリーダーで確かめても合格します。どの欄も名前付きで読まれるからです。axeの`label`ルールもtitleを名前と数えるため、欄を合格にします。axeの`label-title-only`ルールはtitleだけで名前の付いた欄を検出しますが、ベストプラクティスのルールでWCAGの達成基準のタグが付いていないため、WCAGのタグに絞ったスキャンでは実行されません。EaseWebの診断では、確認用の手がかりとして実行します。ラベルのある欄のtitleに、画面にない説明が入っているかを判定する自動ルールはありません。診断はそうしたtitleを手がかりとして挙げ、その言葉が必要かどうかは人が判断します。AIに「ラベルを付けて」と頼むと、同じ言葉の`aria-label`を足すことがあります。欄に名前が二重に付くだけで、画面には相変わらず何も表示されません。

## 修正前：titleだけのラベル

```html
<form class="gift-card">
  <h2>ギフトカード</h2>
  <input name="card" inputmode="numeric" title="ギフトカード番号">
  <input name="pin" inputmode="numeric" title="PIN">
  <button type="submit">適用</button>
</form>
```

どれが何の欄かを示すものが、画面にありません。名前はtitleにあるため、マウスポインターを重ねたときにしか出ません。スクリーンリーダーは欄の名前として読みますが、フォームを目で見る人には一度も見えません。

## 修正前：titleだけにある形式

```html
<form class="gift-card">
  <h2>ギフトカード</h2>
  <label for="card">ギフトカード番号</label>
  <input id="card" name="card" inputmode="numeric" title="16桁">
  <label for="pin">PIN</label>
  <input id="pin" name="pin" inputmode="numeric" title="4桁">
  <button type="submit">適用</button>
</form>
```

ラベルは画面に表示されましたが、「16桁」と「4桁」はtitleにしかありません。目にするのは、欄にマウスポインターを重ねた人だけです。

## 修正後：ラベルと、その下のヒント

```html
<form class="gift-card">
  <h2>ギフトカード</h2>
  <label for="card">ギフトカード番号</label>
  <p id="card-hint" class="hint">16桁</p>
  <input id="card" name="card" inputmode="numeric" aria-describedby="card-hint">
  <label for="pin">PIN</label>
  <p id="pin-hint" class="hint">4桁</p>
  <input id="pin" name="pin" inputmode="numeric" aria-describedby="pin-hint">
  <button type="submit">適用</button>
</form>
```

各欄に`for`と`id`で結び付けた`label`があり、形式はラベルの下の短い行に書いて、`aria-describedby`で欄に結び付けています。誰にでも同じ言葉が届きます。言葉は画面に表示され、スクリーンリーダーはラベルを欄の名前、ヒントを説明として読み、ラベルをクリックすると欄にカーソルが入ります。titleは削除したので、ツールチップにしかない言葉は残っていません。

## 修正後：ラベルの中の形式

```html
<form class="gift-card">
  <h2>ギフトカード</h2>
  <label for="card">ギフトカード番号（16桁）</label>
  <input id="card" name="card" inputmode="numeric">
  <label for="pin">PIN（4桁）</label>
  <input id="pin" name="pin" inputmode="numeric">
  <button type="submit">適用</button>
</form>
```

形式が短ければ、ラベルの中に書けます。ラベル全体が欄の名前になるので、スクリーンリーダーは名前と一緒に形式を読み、説明は必要ありません。長い説明を入れると名前も長くなり、欄に移るたびに全部読まれます。短い形式に限って使ってください。

## どの方法を選ぶか

どちらも欄に必要な言葉をすべて表示し、3.3.2を満たします。ラベルの下のヒントは、短い言葉に収まらない説明に向いています。ラベルが短いままなので、ラベルを声に出して欄に移る音声操作の利用者や、欄に移るたびに名前を聞くスクリーンリーダーの利用者の負担が増えません。ヒントだけ控えめな見た目にもできます。説明をすぐ読むか、少し間を置いて読むかは、スクリーンリーダーによって異なります。ラベルの中に書く方法はARIAが要らず、名前の一部としてどのスクリーンリーダーにも届きます。この例のように形式が短い言葉で済むなら、こちらを選んでください。

## 実装の判断

**titleは削除します。** ラベルと同じ言葉のtitleは、すでに画面にある言葉をツールチップで繰り返すだけです。それ以上のことを書けば、また隠れたメッセージになります。例外は`pattern`属性です。HTML標準はパターンを説明するtitleを求めており、ブラウザーは「指定されている形式で入力してください」というメッセージに、titleの内容を使うことがあります。そのtitleは表示したヒントとまったく同じ言葉にするか、ブラウザーのメッセージの代わりに、欄に結び付けた独自のエラーを出します。[直し方がわからないフォームエラー](/ja/learn/accessible-form-errors)を参照してください。

**フォーカスしたときに出る説明。** W3Cの達成基準3.3.2の解説は、欄にフォーカスがある間だけ表示される説明を認めています。ラベル自体が常に画面にあるなら、ヒントは必要なときだけ表示してもかまいません。ポインターを重ねたときだけでなくフォーカスしたときにも表示し、フォーカスが離れるまで残し、Escapeキーで閉じられるようにします。このようなポップアップに必要なことは、[近づくと消え、閉じられないツールチップ](/ja/learn/hover-content)で扱っています。ブラウザーはtitleをフォーカスでは表示しないため、titleではこれができません。

**入力された値を受け付けます。** カードには番号が4桁ずつ区切って印刷されているので、「スペースなし」とヒントに書き足すのではなく、スペースのまま受け付けて取り除きます。[入力をはじかず、こちらで変換する](/ja/learn/rules-of-thumb#convert-not-reject)を参照してください。

**titleが出てくるほかの場面。** 次のものは別のガイドで扱っています。

- アイコンだけのボタンにtitleを付けると名前は付きますが、目で見ているキーボードやタッチの利用者には、アイコンしか見えません。こうしたボタンの名前は、[名前がないアイコンだけのボタン](/ja/learn/icon-buttons)で扱っています。
- `iframe`には`title`が必要です。スクリーンリーダーにフレームの名前を伝えるもので、目で見る必要はありません。[タイトルがない、または中身の分からないiframe](/ja/learn/frame-titles)を参照してください。
- プレースホルダーをラベル代わりにするのも、ラベルが画面から消えるよくある形です。[ラベルがない・表示と食い違うフォームの入力欄](/ja/learn/form-labels)で扱っています。

**コンポーネント。** 共通の入力欄コンポーネントでは、ラベルを必須のプロパティにします。ヒントのプロパティは、見えるテキストを表示すると同時に、その`id`と`aria-describedby`を設定するように作ります。`title`はプロパティに含めず、ヒントがツールチップに入らないようにします。

## 修正の確認

1. マウスを使わずにTabキーでフォームを移動し、どの欄にもラベルと形式が、ポインターを重ねなくても言葉で表示されていることを確認する。
2. スマートフォンで各欄をタップし、ラベルと形式がタップの前から表示され、タップ後も残っていることを確認する。
3. ブラウザーのアクセシビリティツリーで、各欄の名前がtitleではなくラベルから取られ、形式が名前か説明に含まれていることを確認する。スクリーンリーダーで、各欄が横に表示された言葉で読まれることを確認する。
4. 200%に拡大し、各ラベルとヒントが欄の横に残っていることを確認する。

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

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。扱うのは、欄に入力するために必要なラベルと説明です。カードのどの番号がPINかのように、どこで情報を見つけるかを教えるヘルプは、レベルAAAの別のトピック「フォームで、説明が必要な入力欄のそばにヘルプがある」で扱いますが、まだガイドはありません。決済用のiframe、外部ウィジェット、コンテンツ編集者が追加した欄も、同じように確認してください。実際に使用する支援技術で、操作全体を確認してください。

## スクリーンリーダーでの動き（EaseWebが実機で確認）

`title (no label)`: ブラウザーがツールチップとして表示する補足のテキストです。ラベルのない入力欄では、ブラウザーはこれを欄の名前にします。

| スクリーンリーダー | ブラウザーとOS | Tabで移動 | 下矢印キー |
| --- | --- | --- | --- |
| NVDA | Chrome, Windows 11 | 未確認 | 未確認 |
| JAWS | Chrome, Windows 11 | 未確認 | 未確認 |
| VoiceOver | Safari, iOS | 未確認 | 未確認 |
| TalkBack | Chrome, Android | 未確認 | 未確認 |

`title (with a label)`: ラベルのある入力欄に付けた同じツールチップのテキストです。ブラウザーはこれを欄の説明にします。

| スクリーンリーダー | ブラウザーとOS | Tabで移動 | 下矢印キー |
| --- | --- | --- | --- |
| NVDA | Chrome, Windows 11 | 未確認 | 未確認 |
| JAWS | Chrome, Windows 11 | 未確認 | 未確認 |
| VoiceOver | Safari, iOS | 未確認 | 未確認 |
| TalkBack | Chrome, Android | 未確認 | 未確認 |

`aria-describedby`: ページ内の別のテキスト（ヒントやエラーなど）を、要素の説明にします。

| スクリーンリーダー | ブラウザーとOS | Tabで移動 | 下矢印キー |
| --- | --- | --- | --- |
| NVDA | Chrome, Windows 11 | 未確認 | 未確認 |
| JAWS | Chrome, Windows 11 | 未確認 | 未確認 |
| VoiceOver | Safari, iOS | 未確認 | 未確認 |
| TalkBack | Chrome, Android | 未確認 | 未確認 |

https://easeweb.dev/ja/learn/screen-reader-support

---

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