ナビゲーション · ナビゲーション

東京メトロ路線図風のサイトナビゲーション

保存した一覧を見る 0 →

このブラウザー内に保存します。別の端末との同期はなく、サイトデータを消すと保存も消えます。

印刷時は見本を静止画にし、プロンプトと解説を出力します。PDF保存はブラウザーの印刷画面から選べます。

Vibehaus · デザイン資料
https://vibe.itlibra.com/design/subway-map-navigation/
完全無料・著作権フリー(CC0)· 料金¥0 · 商用利用・改変自由

プレビュー

画面に合わせる

指定幅で実際に組み替えて表示します。表示領域より広い場合は、この枠の中で横へスクロールできます。

vibe.itlibra.com/preview/subway-map-navigation/

AIへの指示文

大型企業サイトの全体ナビゲーションページを、東京メトロ路線図のフォーマットで作ってください。

要件:
- 配色: 紙白 #f5f1e8 + 墨黒 #0d0d0d ベース。各路線(カテゴリ)を 6 色(赤・橙・緑・青・紫・茶)で識別。
- 上部にタイトル「サイト案内図」+ サブ "Site Map · Lines & Stations"。
- メインに SVG で描いた 4-5 本の「路線」を画面上に走らせる:
  - 各路線は色付きの太い直線(4px)で構成、要所で曲げる(angled break)
  - 路線は SVG path で描く(直線セグメントを連結)
  - 各駅は円アイコン(中央白+色境界)+ 駅名 + 駅ナンバリング(M01・H02 風)
- 路線同士の交差点では大きい黒丸の「乗換駅」マーカーを配置。
- 路線図右下にレジェンド:路線名・色・駅数を一覧。
- 上部に「現在地」インジケータ(点滅する○ + "YOU ARE HERE")。
- 下部にモノスペースで「最終更新 2026-04-26」。
- フォント: 駅名は丸ゴシック / Helvetica、駅ナンバリングは monospace、見出しは Bold。
- JS不要、フルレスポンシブ。スマホでは路線図を縦スクロール可能に。

バリエーション

パリメトロ版

色を Paris RER 風に切替(赤・青・緑・黄・紫)し、駅ナンバリングを廃して駅名のみに。

シンプル4色版

路線数を 4 色までに絞り、駅数も最大化(10駅/路線)して情報密度型に。

このプレビューのコード

HTML・CSS・JavaScriptの1ファイルです。外部依存・広告・解析コードはありません。32駅・5路線で描く架空の案内図です。図を横に送り、駅を選ぶとページ内の説明へ移動します。実際の交通案内・API取得・問い合わせ送信は行いません。動きは停止できます。

CC0 · 改変・商用利用自由 · revision 9f0ca00f1b7e

コードを表示
<!doctype html>
<!-- Vibehaus — CC0。CSS・SVGとページ内操作の1ファイル版。製品・星図・路線とリンク先は架空の表示見本です。 -->
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="robots" content="noindex" />
    <title>東京メトロ路線図風のサイトナビゲーション — Vibehaus プレビュー</title>
    <style>
      :root {
        --paper: #f5f1e8;
        --paper-2: #ebe5d4;
        --ink: #0d0d0d;
        --muted: #4a4a4a;
        --quiet: #8a8580;
        --line-m: #e60012;
        --line-g: #f39700;
        --line-c: #00a16e;
        --line-t: #009bbf;
        --line-y: #c1a470;
      }
      * { box-sizing: border-box; }
      html, body { margin: 0; padding: 0; }
      body {
        font-family: "Hiragino Sans", "Helvetica Neue", "Noto Sans JP",
          "Yu Gothic", sans-serif;
        background: var(--paper);
        color: var(--ink);
        line-height: 1.6;
        -webkit-font-smoothing: antialiased;
        font-feature-settings: "palt", "kern";
        min-height: 100dvh;
      }

      header.bar {
        padding: 1.25rem clamp(1rem, 4vw, 2.5rem);
        border-bottom: 3px solid var(--ink);
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-wrap: wrap;
        gap: 1rem;
      }
      .brand {
        display: inline-flex;
        align-items: center;
        gap: 0.6rem;
        font-weight: 800;
        font-size: 1.05rem;
        letter-spacing: -0.02em;
      }
      .brand::before {
        content: "M";
        display: inline-grid;
        place-items: center;
        width: 28px; height: 28px;
        background: var(--line-m);
        color: white;
        border-radius: 50%;
        font-family: "Helvetica Neue", sans-serif;
        font-weight: 800;
        font-size: 0.95rem;
      }
      .top-meta {
        font-family: "JetBrains Mono", monospace;
        font-size: 0.72rem;
        letter-spacing: 0.16em;
        color: var(--muted);
        text-transform: uppercase;
      }
      .top-meta b { color: var(--line-m); }

      .stage {
        max-width: 1280px;
        margin: 0 auto;
        padding: clamp(1.5rem, 4vw, 3rem) clamp(1rem, 4vw, 2.5rem);
      }

      .head {
        text-align: center;
        margin-bottom: 2rem;
      }
      .head h1 {
        margin: 0 0 0.4rem;
        font-size: clamp(2rem, 4vw, 3rem);
        font-weight: 800;
        letter-spacing: 0;
      }
      .head h1 :lang(ja) { letter-spacing: 0; }
      .head .sub {
        font-family: "Helvetica Neue", "Inter", sans-serif;
        font-size: 0.95rem;
        letter-spacing: 0.04em;
        color: var(--muted);
        font-style: italic;
      }

      /* "You are here" indicator */
      .here {
        display: inline-flex;
        align-items: center;
        gap: 0.55rem;
        margin-top: 0.85rem;
        padding: 0.4rem 0.9rem;
        background: white;
        border: 2px solid var(--ink);
        font-family: "JetBrains Mono", monospace;
        font-size: 0.74rem;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        font-weight: 700;
      }
      .here::before {
        content: "";
        width: 10px; height: 10px;
        border-radius: 50%;
        background: var(--line-m);
        animation: pulse-here 1.5s ease-in-out infinite;
      }
      @keyframes pulse-here {
        0%, 100% { box-shadow: 0 0 0 0 rgba(230, 0, 18, 0.7); }
        50% { box-shadow: 0 0 0 10px rgba(230, 0, 18, 0); }
      }
      @media (prefers-reduced-motion: reduce) { .here::before { animation: none; } }

      /* Map area */
      .map-wrap {
        background: var(--paper-2);
        border: 2px solid var(--ink);
        position: relative;
        overflow: auto;
        padding: 1rem;
      }
      .map-svg {
        display: block;
        width: 100%;
        min-width: 760px;
        height: auto;
      }

      /* Legend */
      .legend {
        margin-top: 1.5rem;
        padding: 1.25rem 1.5rem;
        background: white;
        border: 2px solid var(--ink);
        display: grid;
        grid-template-columns: 1fr;
        gap: 0.85rem;
      }
      @media (min-width: 720px) {
        .legend { grid-template-columns: repeat(5, 1fr); }
      }
      .leg-line {
        display: flex;
        align-items: flex-start;
        gap: 0.65rem;
      }
      .leg-line .pin {
        width: 28px; height: 28px;
        border-radius: 50%;
        display: grid;
        place-items: center;
        color: white;
        font-family: "Helvetica Neue", sans-serif;
        font-weight: 800;
        font-size: 0.8rem;
        flex: none;
      }
      .leg-line .desc { font-size: 0.85rem; line-height: 1.5; }
      .leg-line .desc b { display: block; font-weight: 800; font-size: 0.95rem; }
      .leg-line .desc small { color: var(--muted); font-family: "JetBrains Mono", monospace; font-size: 0.7rem; letter-spacing: 0.06em; }

      /* SVG station styles */
      .map-svg .station-name {
        font-family: "Hiragino Sans", "Helvetica Neue", sans-serif;
        font-size: 11px;
        font-weight: 700;
        fill: var(--ink);
      }
      .map-svg .station-num {
        font-family: "Helvetica Neue", "JetBrains Mono", sans-serif;
        font-size: 9px;
        font-weight: 800;
        fill: white;
      }
      .map-svg .station {
        cursor: pointer;
      }
      .map-svg .station:hover circle { r: 11; }
      .map-svg .transfer {
        fill: var(--ink);
      }
      .map-svg .terminal {
        font-family: "Helvetica Neue", sans-serif;
        font-size: 13px;
        font-weight: 800;
        fill: var(--ink);
      }
      .map-svg .here-marker { animation: here-pulse 1.5s ease-in-out infinite; }
      @keyframes here-pulse {
        0%, 100% { opacity: 1; r: 14; }
        50% { opacity: 0.3; r: 22; }
      }

      footer.foot {
        margin-top: 1.5rem;
        font-family: "JetBrains Mono", monospace;
        font-size: 0.72rem;
        letter-spacing: 0;
        color: var(--muted);
        text-transform: uppercase;
        text-align: center;
      }
    [hidden] { display: none !important; }
      .motion-toggle { min-height: 44px; padding: 0.6rem 1rem; margin: 1rem 0; font: inherit; line-height: 1.7; letter-spacing: 0; color: inherit; border: 1px solid currentColor; background: transparent; border-radius: 8px; cursor: pointer; }
      [data-demo-scroll] { overflow: auto; max-width: 100%; }
      a:focus-visible, button:focus-visible, [data-demo-scroll]:focus-visible { outline: 3px solid currentColor; outline-offset: 3px; }
      .demo-note { max-width: 1160px; margin-left: auto; margin-right: auto; padding: 1rem; font-size: 0.9rem; line-height: 1.8; letter-spacing: 0; margin-top: 2rem; padding-top: 1rem; border-top: 1px solid currentColor; }
      .demo-note h2 { font-size: 1.1rem; line-height: 1.4; letter-spacing: 0; }
      .demo-note p { scroll-margin-top: 2rem; }
      .map-help { font-size: 0.9rem; line-height: 1.8; letter-spacing: 0; }
      :root { --line-m: #c60010; }
      .map-svg { min-width: 1100px; }
      .map-svg .station-name { font-size: 13px; }
      .station-hit { stroke: transparent; stroke-width: 2px; rx: 5px; }
      .station:hover .station-hit, .station:focus-visible .station-hit { stroke: var(--ink); }
      .map-svg .station-num[fill] { fill: var(--line-m); }
      .leg-line:not(:first-child) .pin { color: var(--ink); }
      body[data-paused="true"] .here::before, body[data-paused="true"] .here-marker { animation: none; }
      @media (prefers-reduced-motion: reduce) { .here::before, .here-marker { animation: none !important; } }
    </style>
  </head>
  <body>
    <header class="bar">
      <div class="brand">VIBEHAUS LINES</div>
      <span class="top-meta">最終更新 <b>2026·10·18</b> · 32 駅 · 5 路線 · 全線 ¥0</span>
    </header>

    <div class="stage">
      <div class="head">
        <h1>サイト案内図</h1>
        <p class="sub">— Site Map · Lines &amp; Stations · Tokyo —</p>
        <div class="here" aria-label="現在地">YOU ARE HERE — DESIGN-CENTRAL</div>
      </div>

      <button type="button" class="motion-toggle" data-motion-toggle aria-pressed="false" hidden>動きを止める</button><p class="map-help" id="map-help">図は横にスクロールできます。Tabで駅を選び、Enterで説明を開けます。駅名・路線・ページ名は架空の表示見本です。</p><div class="map-wrap" data-demo-scroll tabindex="0" role="region" aria-label="サイト路線図" aria-describedby="map-help">
        <svg class="map-svg" viewBox="0 0 1100 580" xmlns="http://www.w3.org/2000/svg" role="group" aria-labelledby="map-title"><title id="map-title">32駅から説明へ移動できる架空のサイト案内図</title>
          <!-- M Line (red) — Hero / Pricing / etc — horizontal across top -->
          <path d="M 80 100 L 980 100" stroke="var(--line-m)" stroke-width="6" fill="none" stroke-linecap="round"/>
          <!-- G Line (orange) — diagonal upper -->
          <path d="M 200 60 L 350 60 L 500 200 L 700 200 L 850 350" stroke="var(--line-g)" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
          <!-- C Line (green) — main horizontal middle -->
          <path d="M 60 290 L 1020 290" stroke="var(--line-c)" stroke-width="6" fill="none" stroke-linecap="round"/>
          <!-- T Line (blue) — diagonal lower -->
          <path d="M 100 480 L 350 480 L 550 380 L 800 380 L 980 460" stroke="var(--line-t)" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
          <!-- Y Line (brown) — vertical left -->
          <path d="M 280 60 L 280 530" stroke="var(--line-y)" stroke-width="6" fill="none" stroke-linecap="round"/>

          <!-- M Line stations (top horizontal) -->
          <text class="terminal" x="80" y="80" text-anchor="middle">渋谷</text>
          <a class="station" href="#demo-category" aria-label="/heroの説明"><rect class="station-hit" x="50" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="80" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-num" x="80" y="103" text-anchor="middle" fill="var(--line-m)">M1</text>
            <text class="station-name" x="80" y="135" text-anchor="middle">/hero</text>
          </a>

          <a class="station" href="#demo-category" aria-label="/pricingの説明"><rect class="station-hit" x="170" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="200" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-name" x="200" y="135" text-anchor="middle">/pricing</text>
          </a>

          <!-- M / G / Y transfer at 280, 100 -->
          <a class="station" href="#demo-category" aria-label="/featureの説明"><rect class="station-hit" x="250" y="76" width="60" height="64" fill="transparent"/>
            <rect class="transfer" x="265" y="85" width="30" height="30" rx="4"/>
            <text class="station-num" x="280" y="105" text-anchor="middle">乗</text>
            <text class="station-name" x="280" y="138" text-anchor="middle">/feature</text>
          </a>

          <a class="station" href="#demo-category" aria-label="/ctaの説明"><rect class="station-hit" x="350" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="380" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-name" x="380" y="135" text-anchor="middle">/cta</text>
          </a>

          <a class="station" href="#demo-category" aria-label="/testimonialの説明"><rect class="station-hit" x="470" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="500" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-name" x="500" y="135" text-anchor="middle">/testimonial</text>
          </a>

          <!-- HERE - on M, at 620, 100 -->
          <a class="station" href="#demo-category" aria-label="/design (現在地)の説明"><rect class="station-hit" x="590" y="76" width="60" height="64" fill="transparent"/>
            <circle class="here-marker" cx="620" cy="100" r="14" fill="var(--line-m)" opacity="0.4"/>
            <circle cx="620" cy="100" r="11" fill="var(--line-m)" stroke="var(--ink)" stroke-width="3"/>
            <text class="station-num" x="620" y="103" text-anchor="middle">●</text>
            <text class="station-name" x="620" y="138" text-anchor="middle" font-size="12" font-weight="800">/design (現在地)</text>
          </a>

          <a class="station" href="#demo-category" aria-label="/dashboardの説明"><rect class="station-hit" x="710" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="740" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-name" x="740" y="135" text-anchor="middle">/dashboard</text>
          </a>

          <a class="station" href="#demo-category" aria-label="/blogの説明"><rect class="station-hit" x="830" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="860" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-name" x="860" y="135" text-anchor="middle">/blog</text>
          </a>

          <text class="terminal" x="980" y="80" text-anchor="middle">新宿</text>
          <a class="station" href="#demo-category" aria-label="/portfolioの説明"><rect class="station-hit" x="950" y="76" width="60" height="64" fill="transparent"/>
            <circle cx="980" cy="100" r="9" fill="white" stroke="var(--line-m)" stroke-width="4"/>
            <text class="station-num" x="980" y="103" text-anchor="middle" fill="var(--line-m)">M9</text>
            <text class="station-name" x="980" y="135" text-anchor="middle">/portfolio</text>
          </a>

          <!-- G Line stations (orange diagonal) -->
          <text class="terminal" x="200" y="40" text-anchor="middle">原宿</text>
          <a class="station" href="#demo-feature" aria-label="原宿・機能線の入口の説明"><rect class="station-hit" x="170" y="16" width="60" height="44" fill="transparent"/>
            <circle cx="200" cy="60" r="9" fill="white" stroke="var(--line-g)" stroke-width="4"/>
          </a>
          <a class="station" href="#demo-feature" aria-label="/footerの説明"><rect class="station-hit" x="320" y="16" width="60" height="44" fill="transparent"/>
            <circle cx="350" cy="60" r="9" fill="white" stroke="var(--line-g)" stroke-width="4"/>
            <text class="station-name" x="350" y="50" text-anchor="middle">/footer</text>
          </a>
          <!-- transfer at 500, 200 with C? (visual only) -->
          <a class="station" href="#demo-feature" aria-label="/navigationの説明"><rect class="station-hit" x="470" y="176" width="60" height="64" fill="transparent"/>
            <circle cx="500" cy="200" r="9" fill="white" stroke="var(--line-g)" stroke-width="4"/>
            <text class="station-name" x="500" y="187" text-anchor="middle">/navigation</text>
          </a>
          <a class="station" href="#demo-feature" aria-label="/authの説明"><rect class="station-hit" x="670" y="176" width="60" height="64" fill="transparent"/>
            <circle cx="700" cy="200" r="9" fill="white" stroke="var(--line-g)" stroke-width="4"/>
            <text class="station-name" x="700" y="187" text-anchor="middle">/auth</text>
          </a>
          <text class="terminal" x="850" y="370" text-anchor="middle">六本木</text>
          <a class="station" href="#demo-feature" aria-label="/empty-stateの説明"><rect class="station-hit" x="832" y="332" width="44" height="44" fill="transparent"/>
            <circle cx="850" cy="350" r="9" fill="white" stroke="var(--line-g)" stroke-width="4"/>
            <text class="station-name" x="880" y="355" text-anchor="start">/empty-state</text>
          </a>

          <!-- C Line stations (green middle horizontal) -->
          <text class="terminal" x="60" y="270" text-anchor="middle">代々木</text>
          <a class="station" href="#demo-style" aria-label="代々木・スタイル線の入口の説明"><rect class="station-hit" x="30" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="60" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
          </a>
          <a class="station" href="#demo-style" aria-label="/style/minimalの説明"><rect class="station-hit" x="150" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="180" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="180" y="320" text-anchor="middle">/style/minimal</text>
          </a>

          <!-- C / Y transfer at 280, 290 -->
          <a class="station" href="#demo-style" aria-label="/style/swissの説明"><rect class="station-hit" x="250" y="266" width="60" height="64" fill="transparent"/>
            <rect class="transfer" x="265" y="275" width="30" height="30" rx="4"/>
            <text class="station-num" x="280" y="295" text-anchor="middle">乗</text>
            <text class="station-name" x="280" y="325" text-anchor="middle">/style/swiss</text>
          </a>

          <a class="station" href="#demo-style" aria-label="/style/cyberの説明"><rect class="station-hit" x="390" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="420" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="420" y="320" text-anchor="middle">/style/cyber</text>
          </a>
          <a class="station" href="#demo-style" aria-label="/style/retroの説明"><rect class="station-hit" x="510" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="540" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="540" y="320" text-anchor="middle">/style/retro</text>
          </a>
          <a class="station" href="#demo-style" aria-label="/style/luxuryの説明"><rect class="station-hit" x="630" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="660" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="660" y="320" text-anchor="middle">/style/luxury</text>
          </a>
          <a class="station" href="#demo-style" aria-label="/style/neonの説明"><rect class="station-hit" x="750" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="780" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="780" y="320" text-anchor="middle">/style/neon</text>
          </a>
          <a class="station" href="#demo-style" aria-label="/style/playfulの説明"><rect class="station-hit" x="870" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="900" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
            <text class="station-name" x="900" y="320" text-anchor="middle">/style/playful</text>
          </a>
          <text class="terminal" x="1020" y="270" text-anchor="middle">下北沢</text>
          <a class="station" href="#demo-style" aria-label="下北沢・スタイル線の終点の説明"><rect class="station-hit" x="990" y="266" width="60" height="64" fill="transparent"/>
            <circle cx="1020" cy="290" r="9" fill="white" stroke="var(--line-c)" stroke-width="4"/>
          </a>

          <!-- T Line (blue diagonal lower) -->
          <text class="terminal" x="100" y="510" text-anchor="middle">浅草</text>
          <a class="station" href="#demo-data" aria-label="浅草・データ線の入口の説明"><rect class="station-hit" x="70" y="456" width="60" height="64" fill="transparent"/>
            <circle cx="100" cy="480" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
          </a>
          <a class="station" href="#demo-data" aria-label="/llms.txtの説明"><rect class="station-hit" x="190" y="456" width="60" height="64" fill="transparent"/>
            <circle cx="220" cy="480" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
            <text class="station-name" x="216" y="510" text-anchor="middle">/llms.txt</text>
          </a>
          <!-- C / T transfer NOT in this layout but Y / T at 280, 480 -->
          <a class="station" href="#demo-data" aria-label="/rss.xmlの説明"><rect class="station-hit" x="250" y="456" width="60" height="64" fill="transparent"/>
            <rect class="transfer" x="265" y="465" width="30" height="30" rx="4"/>
            <text class="station-num" x="280" y="485" text-anchor="middle">乗</text>
            <text class="station-name" x="300" y="515" text-anchor="start">/rss.xml</text>
          </a>
          <a class="station" href="#demo-data" aria-label="/sitemapの説明"><rect class="station-hit" x="420" y="406" width="60" height="64" fill="transparent"/>
            <circle cx="450" cy="430" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
            <text class="station-name" x="450" y="420" text-anchor="middle">/sitemap</text>
          </a>
          <a class="station" href="#demo-data" aria-label="/categoryの説明"><rect class="station-hit" x="620" y="356" width="60" height="64" fill="transparent"/>
            <circle cx="650" cy="380" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
            <text class="station-name" x="650" y="368" text-anchor="middle">/category</text>
          </a>
          <a class="station" href="#demo-data" aria-label="/styleの説明"><rect class="station-hit" x="770" y="356" width="60" height="64" fill="transparent"/>
            <circle cx="800" cy="380" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
            <text class="station-name" x="800" y="368" text-anchor="middle">/style</text>
          </a>
          <text class="terminal" x="980" y="490" text-anchor="middle">秋葉原</text>
          <a class="station" href="#demo-data" aria-label="秋葉原・データ線の終点の説明"><rect class="station-hit" x="950" y="436" width="60" height="64" fill="transparent"/>
            <circle cx="980" cy="460" r="9" fill="white" stroke="var(--line-t)" stroke-width="4"/>
          </a>

          <!-- Y Line stations (brown vertical) -->
          <text class="terminal" x="280" y="40" text-anchor="middle">北千住</text>
          <text class="terminal" x="280" y="555" text-anchor="middle">中目黒</text>
          <a class="station" href="#demo-company" aria-label="/aboutの説明"><rect class="station-hit" x="250" y="156" width="60" height="64" fill="transparent"/>
            <circle cx="280" cy="180" r="9" fill="white" stroke="var(--line-y)" stroke-width="4"/>
            <text class="station-name" x="305" y="184" text-anchor="start">/about</text>
          </a>
          <a class="station" href="#demo-company" aria-label="/contactの説明"><rect class="station-hit" x="250" y="356" width="60" height="64" fill="transparent"/>
            <circle cx="280" cy="380" r="9" fill="white" stroke="var(--line-y)" stroke-width="4"/>
            <text class="station-name" x="305" y="384" text-anchor="start">/contact</text>
          </a>
        </svg>
      </div>

      <div class="legend">
        <div class="leg-line">
          <span class="pin" style="background: var(--line-m);">M</span>
          <div class="desc">
            <b>カテゴリ線</b>
            <small>9 駅 · 渋谷 → 新宿</small>
          </div>
        </div>
        <div class="leg-line">
          <span class="pin" style="background: var(--line-g);">G</span>
          <div class="desc">
            <b>機能線</b>
            <small>5 駅 · 原宿 → 六本木</small>
          </div>
        </div>
        <div class="leg-line">
          <span class="pin" style="background: var(--line-c);">C</span>
          <div class="desc">
            <b>スタイル線</b>
            <small>9 駅 · 代々木 → 下北沢</small>
          </div>
        </div>
        <div class="leg-line">
          <span class="pin" style="background: var(--line-t);">T</span>
          <div class="desc">
            <b>API・データ線</b>
            <small>7 駅 · 浅草 → 秋葉原</small>
          </div>
        </div>
        <div class="leg-line">
          <span class="pin" style="background: var(--line-y);">Y</span>
          <div class="desc">
            <b>会社情報線</b>
            <small>5 駅 · 北千住 → 中目黒</small>
          </div>
        </div>
      </div>

      <footer class="foot">
        ※ 全線 <b style="color:var(--line-m);">¥0</b>(無料) · 架空の路線・ページの表示見本 · 路線図 v1.0
      </footer>
    </div>
  <noscript><style>.here::before, .here-marker { animation: none !important; }</style></noscript><script>
      document.querySelectorAll('[data-demo-scroll]').forEach(region => {
        region.addEventListener('focusin', event => {
          const link = event.target.closest('a');
          if (link) link.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: 'instant' });
        });
        region.addEventListener('keydown', event => {
          if (event.target !== region || !['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return;
          event.preventDefault();
          const step = Math.max(80, region.clientWidth * 0.75);
          const left = event.key === 'Home' ? 0 : event.key === 'End' ? region.scrollWidth : region.scrollLeft + (event.key === 'ArrowRight' ? step : -step);
          region.scrollTo({ left, behavior: 'instant' });
        });
      });
      const toggle = document.querySelector('[data-motion-toggle]');
      const preference = matchMedia('(prefers-reduced-motion: reduce)');
      let paused = false;
      const update = () => {
        const stopped = paused || preference.matches;
        document.body.dataset.paused = String(stopped);
        toggle.disabled = preference.matches;
        toggle.setAttribute('aria-pressed', String(stopped));
        toggle.textContent = preference.matches ? '動きを減らす設定で停止中' : paused ? '動きを再開する' : '動きを止める';
      };
      toggle.hidden = false;
      toggle.addEventListener('click', () => { paused = !paused; update(); });
      preference.addEventListener('change', update);
      update();
    </script>
<aside class="demo-note" aria-labelledby="demo-title"><h2 id="demo-title">リンク先の説明(表示見本)</h2><p>架空のサイトの案内例です。リンクはこのページ内の説明へ移動し、外部への移動・送信・登録は行いません。配布HTMLはCC0・利用料¥0です。</p><p id="demo-category" tabindex="-1"><strong>カテゴリの案内</strong> — ヒーロー・料金表・機能紹介などを駅として置く構成例です。路線や駅名は架空で、実際の交通案内ではありません。</p><p id="demo-feature" tabindex="-1"><strong>機能の案内</strong> — フッター・ナビ・認証・空の状態をまとめる入口の例です。認証や他のページの機能は実装していません。</p><p id="demo-style" tabindex="-1"><strong>スタイルの案内</strong> — ミニマル・レトロ・ネオンなどを駅で整理する構成例です。</p><p id="demo-data" tabindex="-1"><strong>データと一覧の案内</strong> — RSS・サイトマップ・分類一覧などを案内する路線です。このHTMLからAPI・RSS・外部ファイルは取得しません。</p><p id="demo-company" tabindex="-1"><strong>運営とお問い合わせ</strong> — 運営情報とお問い合わせをまとめる路線です。実在する所在地や連絡先・送信機能は含みません。</p></aside>
</body>
</html>

2026年10月14日、Chromiumで320・390・768・1280pxの描画とキーボードのフォーカス表示を確認しました。他のブラウザは未確認です。利用先のブラウザと実データでも確認してください。

概要

路線図は、複雑な都市交通を一枚の紙で「読める」ものに変えた、20世紀屈指の情報デザインです。1933年、ハリー・ベックがロンドン地下鉄図を地理的正確さから解放し、線の角度を45度刻みに単純化したとき、地図は「正確な絵」から「理解のための図」へと進化しました。このナビゲーションは、その発明をサイト構造の可視化に応用します。

大型サイトの「全体が見えない」問題

階層メニューやドロップダウンは、今いる枝しか見せません。ユーザーはサイトの全体像を一度も俯瞰できないまま、手探りで回遊することになる。路線図ナビは逆に、サイトのすべてを一画面に広げます。カテゴリを路線、ページを駅、複数カテゴリにまたがるページを乗換駅として描くと、情報の構造そのものが地理になります。ユーザーは「自分が今どこにいて、目的地までどう行くか」を、路線図を読むのと同じ直感で把握できます。

駅ナンバリングの実利

各駅に「C-12」のようなナンバリングを振るのは、見た目の演出だけが理由ではありません。初見のユーザーや海外からの訪問者にとって、記号は言語に依存しない道標になる。さらにその ID を URL の末尾に対応させれば、ブックマークや共有の手がかりにもなります。装飾が実用を兼ねる好例です。

仕上げの判断軸

視認性の限界は「5路線 × 10〜15駅 = 50〜75ページ」程度。これを超えると路線図は過密になり、メタファの利点である一覧性が崩れます。それ以上の規模では「急行停車駅」のようなフィルタ階層が必要です。

5路線視認性の限界。超えると過密になり一覧性が崩れる
10〜15駅1路線あたり。合計50〜75ページが上限の目安
C-12駅ナンバリング。言語に依存しない道標として効く

路線は SVG path で描き、レスポンシブには viewBox を設定。モバイルでは縦スクロールで読ませる構成に切り替えます。

ナビゲーションの構成要素

ナビゲーションの構成要素 ロゴ 現在地 ── aria-current="page" CTA 狭い画面 ── 畳む境界を1つ決める 畳んだ側にも現在地と CTA を残す 開閉ボタンには aria-expanded と aria-controls を必ず付ける
ナビは現在地が分かることが最優先です。色を変えるだけでは読み上げに伝わらないので、aria-current を併記します。

使いどころ

  • 大型コーポレートサイトの全体マップ
  • 行政・自治体・公共機関の施設案内
  • 大学・教育機関のサイトインデックス
  • 観光・旅行サイトの全体紹介
  • 多階層ナビが必要な情報密度型サイト

このデザインの分類

カテゴリ
ナビゲーション
スタイル
エディトリアル / ボールド / モノクロ / ミニマル / レトロ

背景と狙いどころ

よくある質問

路線図はSVGで全部描く?
はい。SVG path で線を繋ぎ、駅は circle / text で配置します。レスポンシブには viewBox を設定。
駅ナンバリングを使う必然性は?
海外ユーザー・初見ユーザーに対する案内性。サイトナビでも "C-12" のような ID をURL末尾に付けるとブックマークしやすい副次効果あり。
大量のページがある場合の上限は?
路線図は 5 路線 × 10-15 駅 = 50-75 ページが視認性の限界。それ以上は階層化(「特急停車駅」「急行」等のフィルタ)が必要です。

この画面を実装する

動くサンプルとコピペできるコードを、技術別にまとめています。