tooltips について
Tooltip を含む画面を実装・レビューする開発者向けのアクセシビリティスキルです。適切なパターンの選択、実装要件、入力方法や支援技術を考慮したテストを扱います。
主な機能
- 01適切な Tooltip パターンの選択
- 02キーボードとポインター操作の規則
- 03ARIA の関連付けとセマンティクス
- 04タッチと視覚デザインの指針
- 05アクセシビリティテスト項目
活用シーン
- 01コンポーネントのキーボード操作を確認
- 02Tooltip の ARIA マークアップを点検
- 03タッチや拡大表示でのアクセスを評価
- 04ホバーコンテンツの表示持続性を検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mgifford/ accessibility-skills --skill tooltipsインストール後、Claude Code で/tooltipsを入力して読み込まれたか確認します。
同梱ファイルSYNC.md
詳細
ツールチップのアクセシビリティスキル
正式な参照元:
mgifford/ACCESSIBILITY.mdのexamples/TOOLTIP_ACCESSIBILITY_BEST_PRACTICES.mdこのスキルはそのファイルをもとにしています。判断に迷った場合は、例を正式な指針としてください。
ツールチップコンポーネントを実装またはレビューする際は、以下のルールを適用してください。 プロジェクトにツールチップが含まれる場合にのみ、このスキルを読み込んでください。
基本方針
ツールチップとは、トリガーにキーボードフォーカスが当たるか、ポインターが重なると自動的に表示される、短く非インタラクティブな説明です。アクセシブルなツールチップは、キーボード、ポインター、タッチ、拡大表示、支援技術の各ユーザーが利用でき、重要な情報を隠したり、インターフェースを妨げたりしないものでなければなりません。
ツールチップが適切な解決策ではないこともよくあります。常時表示されるテキスト、明確なコントロールラベル、開閉式の表示、またはダイアログのほうが、通常は見つけやすく使いやすいものです。このガイドでは作成者が実装するツールチップを扱います。HTML の title 属性は、動作や制約の異なるブラウザー制御のツールチップを生成します(以下を参照)。
評価結果の深刻度と優先度の判定には、プロジェクトの skills/bug-reporting/SKILL.md のフレームワークを使用してください。以下の深刻度スケールは、このスキル内での簡略表現であり、普遍的な標準ではありません。
深刻度スケール(このスキル)
| レベル | 意味 |
|---|---|
| Critical | ツールチップに重要な情報が含まれており、他の方法でアクセスできない |
| Serious | キーボードや AT からツールチップにアクセスできない。または、インタラクティブなコンテンツがツールチップ内に閉じ込められている |
| Moderate | ツールチップにはアクセスできるが、WCAG 1.4.13 の要件を完全には満たしていない |
| Minor | ベストプラクティスからの逸脱。影響はわずか |
まず適切なパターンを選ぶ
小さなポップアップをすべてツールチップと呼ぶと、セマンティクスやキーボード操作を誤る原因になります。ARIA を選ぶ前に、インタラクションを分類してください。
| 必要なこと | 使用するもの |
|---|---|
| コントロールのラベルをより明確にする | 表示ラベルを改善する |
| 短い補足テキストをフォーカス時またはホバー時に自動表示する | ツールチップ |
| タスクを完了するための手順や要件を提示する | 常時表示されるヘルプテキスト |
| ユーザーが短いヘルプの表示・非表示を明示的に求める | ボタンで制御する開閉式の表示 |
| ポップアップにリンク、ボタン、その他のコントロールが含まれる | 非モーダルダイアログ、または適切な別のポップアップパターン |
| 作業を続ける前に判断が必要 | モーダルダイアログまたはアラートダイアログ |
| 操作が完了した、またはプロセスの状態が変化した | ツールチップではなくステータスメッセージ |
| レイアウトの都合でテキストが切り詰められている | 折り返し、展開、または全文を読める別の方法を用意する |
作成者が実装するツールチップは、要素を説明し、フォーカス時またはホバー時に自動的に表示され、非インタラクティブなコンテンツのみを含み、フォーカスを受け取らず、aria-describedby を通じてトリガーと関連付けられます。また、トリガーにフォーカスがある間、またはトリガーやツールチップの上にポインターがある間は表示され続け、Escape キーで閉じられる必要があります。
Critical:重要な情報をツールチップだけに含めてはいけません
ツールチップは定義上、補足情報です。手順、エラー、要件、その他の重要な情報は、常時表示されるテキストに記載してください。重要なコンテンツをホバー時またはフォーカス時にしか表示しないのは Critical です。
エラーメッセージ、法的文言、セキュリティ警告、タスクの要件をツールチップだけに含めてはいけません。無効なコントロールに重要な説明だけを関連付けることも避けてください。無効なネイティブフォームコントロールでは、ツールチップが想定するポインターイベントやフォーカスイベントが発生しないことがあります。
<p id="publish-requirement">Add a page title before publishing.</p>
<button type="button" disabled aria-describedby="publish-requirement">
Publish
</button>
Serious:ツールチップはホバー時とフォーカス時の両方に表示する必要があります
ホバー時にしか表示されないツールチップは Serious です。キーボードユーザーが表示できないためです。フォーカスはトリガーに置いたままにしてください。ツールチップがフォーカスを受け取ることはありません。ツールチップをタブ順序に追加したり、矢印キーでそのテキストを移動したりしてはいけません。
document.querySelectorAll('[data-tooltip]').forEach((container) => {
const trigger = container.querySelector('[data-tooltip-trigger]');
const tooltip = document.getElementById(trigger.dataset.tooltipId);
if (!tooltip || tooltip.getAttribute('role') !== 'tooltip') return;
let pointerWithin = false;
let triggerFocused = false;
let dismissed = false;
function updateTooltip() {
tooltip.hidden = !(!dismissed && (pointerWithin || triggerFocused));
}
container.addEventListener('pointerenter', () => { pointerWithin = true; dismissed = false; updateTooltip(); });
container.addEventListener('pointerleave', () => { pointerWithin = false; updateTooltip(); });
trigger.addEventListener('focus', () => { triggerFocused = true; dismissed = false; updateTooltip(); });
trigger.addEventListener('blur', () => { triggerFocused = false; updateTooltip(); });
trigger.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && !tooltip.hidden) {
dismissed = true;
updateTooltip();
event.stopPropagation();
}
});
});
ポインターの状態とフォーカスの状態は個別に追跡してください。フォーカスがツールチップを表示し続けているのに、ポインターが離れたことでツールチップを閉じてしまうのは、よくある不具合です。位置調整ライブラリを使う場合は、レンダリングされたマークアップ、フォーカス処理、ポータルの配置、衝突時の動作、クリーンアップを確認してください。ライブラリ名だけでは、アクセシビリティが確保されている証拠にはなりません。
重大:ARIA パターンは正しくなければなりません
ツールチップの ARIA が不適切な場合は重大です — 支援技術を利用するユーザーに、誤った補足情報が伝わったり、補足情報がまったく伝わらなかったりします。
<span class="tooltip-container" data-tooltip>
<button type="button" aria-describedby="save-tooltip"
data-tooltip-trigger data-tooltip-id="save-tooltip">
Save
</button>
<span id="save-tooltip" role="tooltip" hidden>
Saves changes to your draft.
</span>
</span>
ルール:
- ツールチップ要素には
role="tooltip"を指定します。トリガーがアクションを実行する場合は、ネイティブのインタラクティブ要素をトリガーとして使用します - トリガーから
aria-describedbyでツールチップを参照します(aria-labelledbyは使用しません)。aria-describedbyにはスペース区切りのリストを指定できます。ツールチップを追加する際は、既存のヘルプ、エラー、説明への参照を維持します - 非表示にするには
hiddenを使用します。有効なツールチップにaria-hidden="true"を指定してはいけません - 繰り返し表示されるコンポーネント間も含め、各ツールチップには一意の
idを指定します。フォーカスがトリガーに移る前に、説明用のノードをレンダリングします - トリガー自体に
role="tooltip"を指定してはいけません - ツールチップにフォーカス可能な要素を含めてはいけません — ツールチップのコンテナーに
tabindexを指定しないでください - ツールチップに
aria-live、role="status"、role="alert"を追加してはいけません - 自動表示されるツールチップに
aria-expandedやaria-haspopupを使用してはいけません — これらはボタンで制御する開示に使用するものであり、ツールチップには使用しません - ツールチップのテキストでアクセシブルな説明を提供します。表示されるツールチップのテキストとは異なる説明を置き換えてしまう
aria-labelは避けます
アイコンのみのトリガーでは、コントロールの名前を個別に指定します。ツールチップは説明であり、アクセシブルな名前の代わりではありません。
<span class="tooltip-container" data-tooltip>
<button type="button"
aria-label="Delete quarterly report"
aria-describedby="delete-tooltip"
data-tooltip-trigger data-tooltip-id="delete-tooltip">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<path d="M5 7h14M9 7V4h6v3m-8 0 1 13h8l1-13"/>
</svg>
</button>
<span id="delete-tooltip" role="tooltip" hidden>
Permanently deletes the report.
</span>
</span>
名前と説明にまったく同じ語句を繰り返し使用しないでください。
重大:ボタンで制御するヘルプはツールチップではありません
ユーザーがボタンを操作してコンテンツを表示する場合は、代わりに開示パターンを使用します。コンテンツに role="tooltip" を指定したり、表示されたというだけでライブリージョンを追加したりしてはいけません。
<button type="button" id="password-help-button"
aria-expanded="false" aria-controls="password-help">
Password requirements
</button>
<div id="password-help" hidden>
Use at least 12 characters. Include a number and a symbol.
</div>
展開状態で変化を伝えます。フォーカスはボタンに残ります。ポップアップにインタラクティブなコントロールが含まれる場合、またはフォーカスを管理する必要がある場合は、適切なダイアログまたはポップアップのパターンを使用します。
中程度:WCAG 1.4.13 — ホバー時またはフォーカス時のコンテンツ
| 要件 | 説明 | 不適合時の重大度 |
|---|---|---|
| 閉じられること | ポインターやフォーカスを移動せずに Escape で閉じられる | 重大 |
| ホバー可能であること | ツールチップが消えずに、ユーザーがその上にポインターを移動できる | 中程度 |
| 表示が持続すること | トリガーまたはツールチップのホバーやフォーカスが失われる、閉じられる、または情報が無効になるまで表示され続ける | 中程度 |
自動的に閉じるまでの時間を独自に設定しないでください。トリガーがアクティブなまま、一定時間後に消えるツールチップは、表示の持続性に関する要件を満たしません。
中程度:タッチと操作
タッチデバイスでは、確実なホバー操作はできません。タッチでのアクセスをツールチップに依存させないでください。次のいずれかを使用します。
- 情報をコントロールの近くに表示したままにする
- コントロールのアクセシブルな名前または既存の説明に含める
- 開示を表示するヘルプボタンを別途用意する(上記を参照)
- 追加コンテンツに構造化された情報やインタラクティブな要素が含まれる場合は、モーダルでないダイアログを使用する
中程度:title 属性に依存しない
ブラウザーが制御する title ツールチップは、その表示が完全にユーザーエージェントによって制御される場合、WCAG 1.4.13 の例外に該当します。ただし、この例外があるからといって、title が信頼できるインターフェースパターンになるわけではありません。作成者は、title のキーボード操作、タッチ操作、拡大表示、表示タイミング、テキストサイズ、閉じる動作を一貫させることができません。次の用途に title のみを使用しないでください。
- コントロールのアクセシブルな名前
- 説明や検証要件の情報源
- アイコンの説明
- 省略されたテキストを表示する方法
- タッチユーザーが情報にアクセスする方法
中程度:ビジュアルデザイン
- 通常サイズのツールチップテキストは、背景に対して少なくとも 4.5:1 のコントラスト比が必要です(WCAG 1.4.3)。大きなテキストでは 3:1 が必要です。
- 境界線、形状、矢印は、隣接する色に対して 3:1 のコントラスト比が必要です(WCAG 1.4.11)。ただし、その視覚情報がコンポーネントや状態を識別するために必要な場合に限ります。装飾的な矢印が自動的に対象になるわけではありません。
- ツールチップとそのトリガーの関連付けに、色だけを頼らないでください。
- 400% ズーム時や幅の狭いビューポートでは、ツールチップをビューポート内に収め、テキストの折り返しを許可し、横スクロールを避け、トリガーや重要なコンテンツを覆わず、閉じる手段を確保してください。
- ビューポートの端を検出して位置を調整してください。ズーム、サイズ変更、コンテンツの変更、テキスト方向の変更後に配置を再計算し、ツールチップを切り取る
overflowを持つ祖先要素の内側に描画しないでください。 - アイコンボタンのトリガーも、WCAG 2.2 のターゲットサイズ(最小)の要件を満たす必要があります。
prefers-reduced-motionを尊重してください。
[role="tooltip"] {
position: absolute;
max-inline-size: min(20rem, calc(100vw - 2rem));
overflow-wrap: anywhere;
}
[role="tooltip"][hidden] { display: none; }
@media (forced-colors: active) {
[role="tooltip"] { color: CanvasText; background: Canvas; border-color: CanvasText; }
}
@media (prefers-reduced-motion: no-preference) {
[role="tooltip"] { transition: opacity 0.15s ease; }
}
コンテンツ要件
- コンテンツは短い語句または文にし、トリガーについて説明してください。無関係なメッセージを追加しないでください。
- トリガーのアクセシブルネームをそのまま繰り返さないでください。
- 見出し、リスト、リンク、ボタン、フィールド、その他のコントロールを含めないでください。
- 平易な言葉を使い、トリガーにフォーカスがある間は、動的な説明が変化しないようにしてください。
- コンテンツに構造や複数の文が必要な場合は、常時表示のヘルプ、
aria-details、開閉式コンテンツ、またはダイアログを使用してください。 - ツールチップを付けるためだけに通常の文章をフォーカス可能にしないでください。Tab 移動の停止位置が増えると、キーボード操作が難しくなります。
ツールチップを使用しない場合
- コントロールのラベルが、それだけで内容を理解できる
- 情報を常に読める必要がある → 常時表示のヘルプテキストを使用する
- タッチ専用のインターフェース → ヘルプボタン、開閉式コンテンツ、または常時表示のヘルプテキストを使用する
- コンテンツが長い、または構造化されている → ポップオーバー、開閉式コンテンツ、またはダイアログを使用する
- コンテンツにインタラクティブ要素(リンク、ボタン)が含まれる → ポップオーバーまたはダイアログを使用する
テスト
- キーボード: Tab/Shift+Tab でトリガーに移動し、フォーカスを移動させずにツールチップが表示されることを確認します。フォーカスがトリガーに残ったまま
Escapeで閉じること、ツールチップに Tab 移動の停止位置がないこと、フォーカスインジケーターが表示されたままであることを確認します。 - ポインター/拡大表示: トリガーにポインターを重ね、ツールチップのすべての部分にポインターを移動しても表示されたままであることを確認します。ホバーもフォーカスも維持されなくなると閉じることを確認し、画面拡大機能を使ってテストします。
- タッチ: ホバー時のコンテンツを先に見つけなくても、すべての操作が使えることを確認します。重要な情報が表示されているか、明示的なコントロールからアクセスできることを確認します。スクリーンリーダーのジェスチャーをテストし、長押しが必要ないことを確認します。
- スクリーンリーダー: ツールチップがなくてもトリガーのアクセシブルネームが正しいこと、ツールチップのテキストが説明として公開されること、名前と説明が不必要に重複しないこと、フォーカスが移動しないこと、繰り返しフォーカスしても古い説明が表示されないことを確認します。サポート対象のブラウザーと支援技術の組み合わせをテストし、バージョンを記録してください。表示は環境によって異なり、すべてに共通する単一の読み上げ方はありません。
- ビジュアル/レスポンシブ: 200%/400% ズーム、幅の狭いビューポート、テキスト間隔の上書き、強制カラーモード、モーション低減、RTL テキスト、ビューポート端での配置
- 自動テスト: ID の欠落/重複、解決されない
aria-describedby参照、無効な ARIA 値、ツールチップ内のフォーカス可能な子孫要素、不十分なコントラスト、非表示のトリガー、コンポーネントテストにおける古いまま開かれたツールチップは検出できます。ただし、ホバー可能性、表示の維持、位置、スクリーンリーダーでの表示を証明することはできません。リリースプロセスには手動テストを含めてください。
よくある失敗
| 失敗 | 修正方法 |
|---|---|
| ホバー時にのみツールチップを表示する | キーボードフォーカス時にも表示します |
| ポインターがトリガーから離れたときに非表示にする | ポインターがトリガーまたはツールチップ上にある間は開いたままにします |
| フォーカスが残っているのに、ポインターが離れたときに非表示にする | ポインターとフォーカスの状態を個別に追跡します |
| 一定時間が経過したら閉じる | トリガーの削除、ユーザーによる閉じる操作、または無効化まで表示したままにします |
| フォーカスをツールチップ内に移動する | フォーカスはトリガーに置いたままにします |
role="tooltip" にリンクやボタンを配置する | 開閉式のコンテンツ、非モーダルダイアログ、または別のポップアップを使用します |
自動表示されるツールチップに aria-expanded/aria-haspopup を使用する | aria-describedby と role="tooltip" を使用します |
コントロールのラベルや説明に title を頼る | 表示されるラベルと、常時表示または作成者が用意したヘルプを提供します |
既存の aria-describedby の ID を上書きする | 関連するすべての参照を追加し、保持します |
| 必須のヘルプを無効なコントロールにのみ関連付ける | 説明を表示します |
完了条件チェックリスト
- ツールチップが適切なパターンである(上記のパターン選択表を参照)
- 重要な情報が、ツールチップを開かなくても表示される
- トリガーが、ツールチップに依存せず完全なアクセシブル名を持つ
- ツールチップ要素に、一意の
idを持つrole="tooltip"が設定されている - トリガーから
aria-describedbyで参照され、他の説明を失わない - ホバー時とキーボードフォーカス時の両方でツールチップが表示される
-
Escapeでフォーカスを移動せずに閉じられ、一定時間で閉じない - ツールチップがホバー可能である(ポインターを移動しても閉じない)
- ツールチップとそのすべての子孫要素がフォーカス可能ではなく、内部にインタラクティブなコンテンツがない
- タッチユーザー向けに、情報が表示されるか、明示的なヘルプコントロールがある
- 無効なコントロールによって説明が隠されない
- テキストのコントラスト比が 4.5:1 で、必要な非テキストのコントラスト比が 3:1 である
- 拡大表示時やテキスト間隔の上書き時に、折り返しやリフローが行われ、操作可能な状態を保つ
- アニメーションで
prefers-reduced-motionを尊重する - キーボード、ポインター、タッチ、拡大表示、およびサポート対象のスクリーンリーダーでテスト済みである
主な WCAG 基準
- 1.3.1 情報及び関係性(A)
- 1.4.3 コントラスト(最低限)(AA)
- 1.4.10 リフロー(AA)
- 1.4.11 非テキストのコントラスト(AA)
- 1.4.12 テキストの間隔(AA)
- 1.4.13 ホバー又はフォーカスで表示されるコンテンツ(AA) — ホバー時にのみ表示される場合、または閉じられない場合は重大
- 2.1.1 キーボード(A) — キーボードでツールチップを表示できない場合は重大
- 2.1.2 キーボードトラップなし(A)
- 2.4.7 フォーカスの可視化(AA)
- 2.4.11 フォーカスが隠れない(最低限)(AA)
- 2.5.8 ターゲットのサイズ(最低限)(AA)
- 4.1.2 名前、役割、値(A)
参考資料
- ベストプラクティスガイド全文
- WCAG 2.2 の解説:1.4.13 ホバー又はフォーカスで表示されるコンテンツ
- WAI-ARIA APG — ツールチップパターン(W3C が作業中と明記 — 有用なガイダンスですが、ユーザーテストの代わりにはなりません)
- テクニック SCR39:ホバー可能、閉じることが可能、かつ表示が持続する
- 失敗 F95:ホバー時に表示されるコンテンツがホバー可能ではない
標準の展望: WCAG 3.0 は策定中です。1.4.13 の要件は 引き継がれる見込みです。 以下で最新情報をご確認ください:https://www.w3.org/TR/wcag-3.0/