画面左端にアイコン(+オプションのラベル)を縦並びで配置した省スペースナビゲーション。Material Design では "Navigation Rail" とも呼ばれる。フルサイドバーほど幅を取らず、ボトムナビほど画面下を占有しない——タブレット・大画面スマートフォン・コンパクトなWebアプリに最適なポジションのコンポーネント。
この記事を読むと、App railとSidebar・Bottom navの使い分け・アイコン+ラベルの設計基準・Active状態の表現・モバイル〜デスクトップのレスポンシブ切替戦略が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
画面左端に縦並びするアイコン(+オプションのラベル)主体のナビゲーションコンポーネント。Material Design の "Navigation Rail" に相当。Sidebarより幅が狭く(56〜80px)、Bottom navより上部に位置するため、タブレット・大きめのスマートフォン・コンパクトなWebアプリに適している。
Sidebar との違い:Sidebarはアイコン+ラベルを横並びで常時表示し幅が広い(200〜280px)。App railはアイコン中心で幅が狭く省スペース。階層構造の表示はSidebarに任せ、App railはトップレベルのみ担当する。
Bottom nav との違い:Bottom navは画面下部に水平配置。App railは画面左端に垂直配置。タブレット以上の画面ではBottom navより App railの方が親指リーチと画面利用効率が優れる。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- タブレット・大画面スマートフォン(幅600px〜840px)での主要ナビゲーション
- デスクトップでSidebarほどの幅が不要なコンパクトなWebアプリ
- トップレベルのセクションが3〜7個あり、常時表示したい場合
3.2 When NOT to use
- スマートフォン(幅600px未満)→ Bottom nav の方が親指リーチが良い
- メニュー項目に階層構造がある場合 → Sidebar の方が適している
- 項目数が2個以下または8個以上 → 少なすぎても多すぎても App rail の意味が薄れる
3.3 代替UI(Alternatives)
- スマートフォン →
Bottom nav(画面下部の水平ナビゲーション) - デスクトップで階層あり →
Sidebar(アイコン+ラベルの横並び・折りたたみ対応) - デスクトップで項目が少ない →
Top nav(水平ナビゲーションバー)
4. 設計判断の核(Decision Principles)
App rail のアイコンは単体で意味が伝わるものを選ぶか、ラベルを添えること——アイコンは「飾り」ではなく「唯一のラベル」になる。
判断の優先順位:① アイコンの認識可能性 → ② Active状態の明示 → ③ バッジの設計 → ④ レスポンシブ切替戦略
- アイコン+ラベルを基本とする:アイコンのみにする場合、そのアイコンが世界的に認知されているもの(ホーム・検索・設定など)に限定する。ドメイン固有のアイコンは必ずラベルを付ける
- Active状態は色・ピル・インジケーターで明示:Active項目の背景にピル形状のハイライトを置くパターン(Material Design準拠)が視認性が高い
- バッジは「未読数」に限定する:バッジの乱用は注意疲れを引き起こす。通知・メッセージの未読数など、ユーザーが自分でコントロールできる数値にのみ使う
- レスポンシブ戦略:
sm:(600px未満) → Bottom nav、md:(600px〜840px) → App rail、lg:(840px以上) → Sidebar という3段階の切り替えが Material Design ガイドラインの推奨
5. 状態設計(States)
5.1 必須状態(Required)
- Default:全項目が同じスタイルで表示。Active項目のみ強調
- Active(現在地):背景ピル+テキスト色変化で強調。
aria-current="page"を付与 - Hover:ホバー時に背景色変化でクリッカブルを示す
- Focus:フォーカスリングを表示(省略不可)
5.2 条件付き状態(Conditional)
- Badge:未読数・通知数をアイコン右上に表示。9件以上は "9+" に省略
- Tooltip:アイコンのみモードでホバー時にラベルを表示
- Disabled:権限がなく選択できない項目。グレーアウトで表示
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Default | ✅ | 全ナビゲーション項目の一覧 |
| Active | ✅ | 今どのセクションにいるかを常時表示 |
| Hover | ✅ | この項目でナビゲートできることを示す |
| Focus | ✅ | キーボードユーザーに今どの項目にいるかを示す |
| Badge | — | 未処理の通知・メッセージ数を示す |
| Tooltip | — | アイコンのみモードでラベルを補完する |
6. バリエーション設計(Variants)
App railのバリアントは「ラベルの有無」と「Activeインジケーターのスタイル」で決まる。
| バリアント | 目的 |
|---|---|
| Icon + Label | アイコン下にラベルを表示。最も認識しやすい標準スタイル |
| Icon only | アイコンのみ。ホバーでTooltip表示。幅を最小化したい場合 |
| With Badge | 未読数・通知数をアイコン右上に表示 |
| Pill indicator | Activeピル(横長のハイライト)で現在地を強調するMaterial Design準拠スタイル |
禁止パターン:ドメイン固有アイコンをラベルなしで使う → 「このアイコンが何を意味するか」ユーザーが解釈できない。
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- アイコンのみ+aria-label なし:スクリーンリーダーが「ボタン」としか読み上げられず、何の操作かが伝わらない
- Active状態が分からない:全項目が同じ見た目でどのセクションにいるか把握できない
- バッジの乱用:全ナビ項目にバッジを付けると、すべてが「緊急」に見えユーザーが麻痺する
7.1 Bad(典型3つ)
- アイコンのみ表示で
aria-labelもtitleもなく、スクリーンリーダーに意味が伝わらない - Active項目と非Active項目が色だけで区別されており、グレースケール環境では判別できない
- 5つ全項目にバッジが付いており、どれが本当に重要か分からない
7.2 Good(対になる3つ)
- アイコン下にラベルを表示するか、アイコンのみの場合は
aria-labelとtitleを付与する - Activeピル(背景色)+テキスト色変化の2つの視覚的手がかりで現在地を示す
- バッジは「ユーザーが未処理で放置している項目(通知・メッセージ)」にのみ使い、1〜2項目に限定する
7.3 How to fix(手順)
- ラベルが非表示の場合、
aria-label={item.label}とtitle={item.label}を各ボタンに付与する - Active項目に背景ピル(
bg-blue-100などのハイライト)とテキスト色変化を組み合わせる aria-current="page"を現在地のボタンに付与する- バッジは
aria-label="3件の未読メッセージ"で読み上げ内容を明示する
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Tabで各ボタンにフォーカスでき、Enter/Spaceでアクティベートできること
Focus
- フォーカスリングはApp railの背景色と4.5:1以上のコントラストを持つこと
Screen Reader
<nav aria-label="アプリナビゲーション">でランドマーク登録する- Active項目に
aria-current="page"を付与する - アイコンのみ表示の場合は
aria-labelでラベルを補完する - バッジには
aria-label="N件の未読"を付与する(数字だけでは文脈が伝わらない)
<!-- 基本パターン(アイコン+ラベル) -->
<nav aria-label="アプリナビゲーション">
<a href="/home" aria-current="page">
<span aria-hidden="true">🏠</span>
<span>ホーム</span>
</a>
<a href="/messages">
<span aria-hidden="true">💬</span>
<span class="badge" aria-label="3件の未読">3</span>
<span>メッセージ</span>
</a>
</nav>
<!-- アイコンのみモード -->
<a href="/search" aria-label="検索" title="検索">
<span aria-hidden="true">🔍</span>
</a>
Touch / Pointer
- 各ボタンの高さを44px以上確保する
- タップ時の視覚フィードバック(背景色変化)を確保する
Contrast / Readability
- Active項目のアイコン・ラベルは背景色と4.5:1以上のコントラスト比を確保する
- 非Active項目も3:1以上のコントラストを維持する
10. 実装メモ(Implementation Notes)
- Material Design の Navigation Rail コンポーネントの設計原則を参考にすると、Active状態・バッジ・ラベルの扱いが体系的に整理されている
- レスポンシブ切替は Tailwind の
hidden sm:flex(Bottom nav)/hidden md:flex lg:hidden(App rail)/hidden lg:flex(Sidebar)のクラスの組み合わせで実現できる - バッジのカウントが10以上になる場合は "9+" など上限付きの表示にしてレイアウト崩れを防ぐ。
Math.min(count, 9)+ "+" の組み合わせで実装する
11. 関連リンク
- 関連するUIデザイン原則: ナビゲーション設計 (Navigation Design), 情報設計 (Information Architecture), Fittsの法則 (Fitts's Law)
- 用語集(定義): ナビゲーション・ファティーグ (Navigation Fatigue), タッチターゲット (Touch Target)
- 関連するUIコンポーネント(横): Sidebar / Side nav(サイドバー), Tabs(タブ), Breadcrumb(パンくずリスト)
12. まとめ
App railの設計は「アイコンの認識可能性」と「Active状態の明示」の2点が最低ラインです。迷ったら 4. 設計判断の核 に戻り、アイコン+ラベルの組み合わせ・Activeピルの実装・aria-current の付与を確認してください。デバイス幅に応じてBottom nav(モバイル)→ App rail(タブレット)→ Sidebar(デスクトップ)と切り替える3段階レスポンシブ戦略が、最も幅広いデバイスに対応できる設計方針です。