ボタン・アイコン・テキストなどの要素にホバー(またはフォーカス)した時に、その要素の補足情報を小さなフローティングパネルで表示するUIコンポーネント。「保存」アイコンにホバーすると「変更を保存(⌘S)」と表示されるのが典型例。
この記事を読むと、TooltipとPopover・Hover Cardの使い分け・モバイルでのTooltipの限界・role="tooltip" + aria-describedby の実装・アイコンボタンのTooltipによる補足が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
要素にホバー(またはフォーカス)した時に、その要素を補足する短いテキストをフローティングパネルで表示するUIコンポーネント。WAI-ARIAでは role="tooltip" として定義され、トリガー要素に aria-describedby でTooltipのIDを紐付ける。
TooltipとPopoverの違い:Tooltipはホバー/フォーカスで自動表示される受動的な補足情報(テキストのみ・インタラクション不可)。Popoverはクリックで明示的に開く能動的なパネル(リンク・フォーム・リッチコンテンツを含める)。
TooltipとHover Cardの違い:Tooltipは短いテキスト(1〜2行)のみ。Hover Cardはアバター・リンク・詳細情報を含むリッチなカード形式。コンテンツの量と複雑さで区別する。
重要な制約:Tooltipにしか存在しない必須情報を書いてはならない。モバイルユーザーはホバーできず、タッチデバイスでTooltipにアクセスする手段がない。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- アイコンのみのボタンの名前を補足する(
aria-labelと組み合わせる) - キーボードショートカットを表示する(「保存 ⌘S」)
- 省略されたテキストや専門用語の補足説明
- 入力フィールドのフォーマットヒント(ただし常時表示の方が多くの場合優れる)
3.2 When NOT to use
- 操作を完了するために必要な情報を格納する → 常時表示するかPopoverを使う
- モバイルが主要なプラットフォーム → タッチデバイスでホバーできない
- リンク・ボタン・フォームなどインタラクティブな要素を含める → Popoverを使う
- 長文(3行以上)の説明 → Popoverまたはモーダルを使う
3.3 代替UI(Alternatives)
- インタラクティブなコンテンツ →
Popover - リッチなプレビュー →
Hover Card - 常に表示すべき補足 → インラインテキスト・ヘルパーテキスト
- 重要な警告・説明 →
Alert/Dialog
4. 設計判断の核(Decision Principles)
Tooltipの核は「補足性」——Tooltipが消えてもユーザーが操作を完了できる内容だけを書く。必須情報をTooltipに入れた瞬間に、モバイルユーザーとキーボードユーザーの一部が情報にアクセスできなくなる。
判断の優先順位:① 補足情報のみ(必須情報を入れない)→ ② aria-describedby で紐付け → ③ 表示遅延(即時表示しない)→ ④ 表示位置の自動調整
- 表示遅延(300〜500ms)を設ける:ユーザーがUI上をマウスで移動する際に次々とTooltipが表示されると煩わしい。意図的にホバーしたと判断できる程度の遅延を設ける
- Tooltipは
role="tooltip"+ トリガーにaria-describedby:スクリーンリーダーはTooltipが表示された時にテキストをアナウンスする。aria-describedbyがないとスクリーンリーダーに補足情報が伝わらない - アイコンボタンは
aria-labelを必ず付与する:Tooltipはあくまで視覚的補足。スクリーンリーダーはTooltipではなくaria-labelを読み上げる。aria-labelがないとアクセシビリティが担保されない - テキストは短く(最大2行):長い説明が必要なら Popover を使う。Tooltipは「名前の補足」「ショートカット」「短い説明」に限定する
5. 状態設計(States)
5.1 必須状態(Required)
- Hidden(非表示):デフォルト状態
- Visible(表示中):ホバーまたはフォーカス時に表示
5.2 条件付き状態(Conditional)
- Delayed(表示遅延中):ホバー開始から表示まで300〜500msの遅延
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Hidden | ✅ | 通常状態(Tooltipは非表示) |
| Visible | ✅ | 補足情報を表示中 |
6. バリエーション設計(Variants)
コンテンツの種類によって使い分ける。
| バリアント | コンテンツ | 使用例 |
|---|---|---|
| テキストのみ | 1〜2行の短いテキスト | アイコンの名前・専門用語の説明 |
| ショートカット付き | テキスト + <kbd> | ツールバーのボタン |
| 表示位置: top | デフォルト | ほとんどの場面 |
| 表示位置: 自動 | 画面端で自動反転 | 画面端に近い要素 |
禁止パターン:Tooltipにリンク・ボタン・フォームを含める → ホバーで開くTooltipにカーソルを移動しようとするとTooltipが閉じてしまい、インタラクティブな要素に到達できない(Popoverを使う)。
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- 必須情報をTooltipにのみ書く:「このボタンを押す前に必ず確認してください」という注意書きをTooltipだけに書き、モバイルユーザーが気づかずに操作する
aria-describedbyがない:スクリーンリーダーがTooltipの補足テキストを読み上げず、アイコンボタンが「ボタン」としか認識されない- 即時表示(遅延なし):UIの上をマウスで移動するたびにTooltipが次々と表示されて画面が騒がしくなる
7.1 Bad(典型3つ)
- パスワードの要件(「8文字以上・英数字含む」)をTooltipにのみ書き、モバイルユーザーがエラーになるまで気づかない
<button>💾</button>のみでTooltipもaria-labelもなく、スクリーンリーダーが「ボタン」しか読み上げないonMouseEnter={() => setVisible(true)}で遅延なしの即時表示になり、マウス移動のたびにTooltipが乱立する
7.2 Good(対になる3つ)
- パスワード要件はフォームの下にヘルパーテキストとして常時表示し、Tooltipには「?」アイコンの補足のみを置く
<button aria-label="保存(⌘S)">💾</button>+aria-describedby="tooltip-save"でアクセシビリティを完全に担保するsetTimeout(timer, 400)で400msの遅延を設け、onMouseLeaveでタイマーをクリアして意図的なホバーのみTooltipを表示する
7.3 How to fix(手順)
- Tooltipのコンテナに
role="tooltip"とidを付与する - トリガー要素に
aria-describedby="[tooltip-id]"を追加する(Tooltipが表示されている時のみ付与するか、常時付与するかはどちらも可) setTimeoutで表示遅延を実装し、onMouseLeave/onBlurでタイマーをクリアする- Tooltipのコンテンツが「なくても操作できる補足か」を確認し、必須情報であればインラインに移す
7.4 GUNJO 実装で見る(Bad / Good)
同じ「補足の伝え方」を、hover 限定の崩れた使い方と、GUNJO Tooltip の正しい使い方で対比。
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Tabでトリガー要素にフォーカスした時にTooltipを表示するEscapeでTooltipを閉じる(フォーカスはトリガーに留まる)- フォーカスがトリガーから外れたらTooltipを閉じる
Focus
- Tooltipはフォーカスを受け取らない(
pointer-events: none) - トリガーへのフォーカス = Tooltipの表示トリガー
Screen Reader
<!-- トリガーボタン -->
<button
aria-label="保存"
aria-describedby="tooltip-save"
>
💾
</button>
<!-- Tooltip -->
<div
id="tooltip-save"
role="tooltip"
>
変更を保存(⌘S)
</div>
スクリーンリーダーはフォーカス時に aria-label(「保存」)を読み上げ、その後 aria-describedby の補足(「変更を保存 ⌘S」)を読み上げる。
Touch / Pointer
- タッチデバイスではホバーが機能しないため、Tooltipのコンテンツはアイコンに
aria-labelとして必ず付与する - モバイルではTooltipを省略し、
aria-labelのみで対応することも選択肢 - どうしてもモバイルでTooltipを表示したい場合は
onTouchStartで短時間(2〜3秒)表示する
Contrast / Readability
- Tooltipの背景と文字のコントラストは4.5:1以上(通常は暗い背景色+白文字で確保)
- テキストサイズは最低12px(推奨14px)
10. 実装メモ(Implementation Notes)
- shadcn/ui の
Tooltipは@radix-ui/react-tooltipベースで、role="tooltip"+aria-describedby・表示遅延(delayDuration)・Floating UI による位置計算がすべて実装済み。新規実装よりTooltipを使うのが最速 - Floating UI(
@floating-ui/react)のuseFloating+useHover+useFocus+useRoleを組み合わせると、フォーカス対応・位置計算・ARIA を含む完全なTooltipが実装できる - CSS Transitions でTooltipをフェードイン/アウトする場合、
visibility: hidden+opacity: 0を使う。display: noneだけだとトランジションが効かない pointer-events: noneをTooltipに付与することで、Tooltipの上にカーソルが乗ってもTooltipが閉じないようにする(ただしpointer-events: autoにするとTooltip内がホバー可能になり、Popoverの領域になる)
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), 段階的開示 (Progressive Disclosure)
- 用語集(定義): アクセシビリティ (Accessibility)
- 関連するUIコンポーネント(横): Popover(ポップオーバー), Hover Card(ホバーカード), Button(ボタン)
12. まとめ
Tooltipの設計で最重要なのは「補足性の徹底」と role="tooltip" + aria-describedby の実装です。迷ったら 4. 設計判断の核 に戻り、「そのコンテンツはなくても操作できるか」「aria-describedby は付いているか」「アイコンボタンに aria-label はあるか」の3点を確認してください。shadcn/ui の Tooltip を使えばARIA・遅延・位置計算はすべて解決されます。「Tooltipに入れるかPopoverにすべきか」の判断基準はコンテンツにインタラクション(リンク・ボタン)が必要かどうか——必要なら Popover、不要な短いテキストなら Tooltip です。