コピペで完結!タブ切替 #13【タブの入れ子に対応(ネストタブ)】

html/css/js

タブの入れ子に対応(ネストタブ)

タブの中にさらにタブを持てる「ネストタブ」の実装例です。 外側タブで大きなカテゴリを切り替え、その中にある内側タブで詳細を切り替えることができます。 複数階層を整理して見せたいUIに便利で、ARIA対応済み・コピペですぐ利用できます。

  • 外側タブと内側タブの二重構造に対応
  • カテゴリと詳細の切替に最適
  • ARIA属性でアクセシブルな設計
  • シンプルなJSで複数階層の切替を管理
コードについて 本記事のコードは AI(ChatGPT)による生成をベースに作成・調整しています。ご利用の環境でテストの上ご使用ください。
免責 本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。

デモ

カテゴリAの内容

詳細A-1 のコンテンツです。

コードをコピーして使おう!

/* =========================
   ネスト対応タブUIのCSS(全文コメント)
   -----------------------------------------
   ・このスタイルは #nested-tabs 配下に限定して適用します
   ・外側タブと内側(入れ子)タブは同じクラス名(.tabs / .tab / .tabpanel)
     を使い、スコープで衝突を回避します
   ・ARIA属性(aria-selected / aria-hidden)と連動して視覚状態を切替えます
   ========================= */

/* ===== 全体スコープ(フォント/色/幅) ===== */
#nested-tabs{
  font-family: system-ui,-apple-system,"Segoe UI",Roboto,"Noto Sans JP",sans-serif; /* 可読性が高い汎用フォントスタック */
  color:#0f172a;        /* 基本文字色(濃いネイビー系) */
  max-width: 720px;     /* セクションの最大横幅(レイアウトが横に伸びすぎないよう制限) */
  margin:0 auto;        /* 画面中央に配置(左右オートマージン) */
  padding:0 16px;       /* 画面端で文字がつかないよう左右に余白を確保(任意) */
  box-sizing:border-box;/* パディング込みで幅計算(安全策) */
}

/* ===== タブリスト(外側/内側とも共通) ===== */
#nested-tabs .tabs{
  display:flex;         /* 子要素(.tab)を横並びにする */
  gap:6px;              /* タブ同士の間隔を6px空ける */
  margin:12px 0;        /* タブリストの上下に余白を設ける */
  flex-wrap:wrap;       /* 画面が狭いときは折り返してレイアウト崩れを防止 */
}

/* ===== タブボタン(外側/内側とも共通) ===== */
#nested-tabs .tab{
  appearance:none;                  /* ブラウザ既定のボタン装飾を解除(クロスブラウザ安定) */
  padding:6px 12px;                 /* クリックしやすい内側余白 */
  border:1px solid #e5e7eb;         /* 薄いグレーの枠線 */
  border-radius:8px;                /* 角丸で柔らかい見た目に */
  background:#fff;                  /* 背景は白 */
  color:inherit;                    /* 文字色は親の color を継承 */
  cursor:pointer;                   /* ホバー時にポインターを表示 */
  line-height:1.2;                  /* テキストの行高を少しゆったりに */
  white-space:nowrap;               /* ラベルの折返しを防止(必要に応じて解除) */
  transition:
    background-color .2s ease,
    border-color .2s ease,
    color .2s ease,
    transform .05s ease;            /* 状態変化を滑らかに */
}

/* アクティブ感のある押下フィードバック(任意) */
#nested-tabs .tab:active{
  transform: translateY(1px);       /* クリック中に1px沈む演出 */
}

/* フォーカス可視化(キーボード操作のアクセシビリティ向上) */
#nested-tabs .tab:focus-visible{
  outline:2px solid #0b6bff;        /* アクセント色でアウトライン表示 */
  outline-offset:2px;               /* ボタンから少し離して見やすく */
}

/* ===== 選択状態のタブ(aria-selected="true") =====
   JS 側で選択タブに aria-selected="true" を付与する前提。
   視覚的にも「選ばれている」ことが分かるよう配色を変更。 */
#nested-tabs .tab[aria-selected="true"]{
  background:#0b6bff;               /* アクティブ背景をアクセント色に */
  color:#fff;                        /* 文字は白でコントラスト確保 */
  border-color:#0b6bff;             /* 枠線もアクセント色に揃える */
  font-weight:600;                   /* やや強調 */
}

/* ===== パネル(表示領域)の既定状態 =====
   すべてのパネルを非表示にしておき、表示すべきパネルだけ
   aria-hidden="false" を付与して見せる運用。 */
#nested-tabs .tabpanel{
  display:none;                      /* 既定は非表示 */
}

/* ===== パネル(表示中:aria-hidden="false") =====
   JS 側で対応パネルに aria-hidden="false" を付け替える。 */
#nested-tabs .tabpanel[aria-hidden="false"]{
  display:block;                     /* 表示に切替 */
  border:1px solid #e5e7eb;          /* コンテンツ領域を囲う薄い枠線 */
  border-radius:8px;                 /* 角丸 */
  padding:12px;                      /* 内側余白 */
  margin-bottom:12px;                /* 下に余白(次のブロックと干渉しないように) */
  background:#fff;                   /* 背景を白で読みやすく */
  box-sizing:border-box;             /* 枠線/パディング込みの幅計算 */
}

/* ===== 補助クラス(任意) ===== */
#nested-tabs .panel-outer{ /* 外側パネルの差別化用(必要なら有効化) */ }
#nested-tabs .panel-inner{ /* 内側パネルの差別化用(必要なら有効化) */ }

コメント