コピペで完結!タブ切替 #14【スクロールで自動タブ切替できるタブ】

html/css/js

スクロールで自動タブ切替できるタブ

ページをスクロールすると、表示中のセクションに応じてタブが自動で切り替わるナビゲーションです。 ヘッダー内に配置したタブバーは常に固定表示され、クリックで該当セクションへスムーズスクロール。 読み進めるだけで現在地がハイライトされるので、メガメニューや長文ページに最適です。

  • Stickyタブ:ヘッダー内で固定され、常に操作可能
  • 自動連動:スクロール位置に応じてタブが切替わる
  • 双方向ナビ:クリックでジャンプ/スクロールで自動同期
  • アクセシビリティ対応:ARIA属性を正しく付与
  • 依存ライブラリなし:CSS/HTML/JSのみで完結
コードについて 本記事のコードは AI(ChatGPT)による生成をベースに作成・調整しています。ご利用の環境でテストの上ご使用ください。
免責 本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。

デモ

概要

Stickyタブの概要説明。常に画面上部に残り、どの位置でもナビゲーション可能です。

仕様

  • IntersectionObserverで表示中セクションを検出(センター判定)
  • タブクリックで該当セクションへスムーズスクロール
  • ARIA属性(aria-selected)更新でアクセシブル

FAQ

よくある質問を記載。ライブラリは不要です。

事例

実際の導入事例を紹介。

導入方法

設置方法と基本コードを解説。

応用

カスタマイズや応用例を紹介。

注意点

実装上の注意点や推奨事項。

まとめ

記事全体のまとめとポイント。

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

/* =========================================
   固定(Sticky)タブ+「見出しが画面の上端に来たら」同期:CSS
   -----------------------------------------
   ・監視対象は .panel 内の h3(見出し)
   ・h3 が Stickyタブ直下の帯に触れたら該当タブをアクティブに
   ・h3 に scroll-margin-top を付与してアンカーで隠れないように
   ========================================= */

/* =========================================
   ルートエリアのスタイル
   -----------------------------------------
   ・カラートークンを定義(色や高さはJSからも利用)
   ・全体のレイアウトやフォントを設定
   ========================================= */
#sticky-section{
  --ink:#0f172a;           /* 文字色(本文の基本) */
  --muted:#64748b;         /* 補助文字色(説明やサブテキスト用) */
  --accent:#0b6bff;        /* 強調色(アクティブタブや強調箇所に使用) */
  --border:#e5e7eb;        /* 枠線色(ボーダー用) */
  --panel:#ffffff;         /* パネルの背景色 */
  --sticky-bg:#f8fafc;     /* Sticky部分の下地色(タブバー背景) */
  --sticky-h:52px;         /* ★固定タブの高さ(JSでも参照される値) */

  color:var(--ink);        /* 全体の文字色を指定 */
  font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans JP","Yu Gothic UI",sans-serif;
                           /* システムに依存しない読みやすいフォント */
  max-width:960px;         /* 横幅を最大960pxに制限(読みやすさ重視) */
  margin:0 auto;           /* セクションを中央寄せ */
  padding:0 16px 64px;     /* 左右16px/下64pxの余白を確保 */
  box-sizing:border-box;   /* パディングやボーダーを幅に含める */
  scroll-behavior:smooth;  /* アンカー移動時にスムーズスクロール */
}

/* =========================================
   Stickyタブバー(常に上部に固定される)
   ========================================= */
#sticky-section .sticky-tabs{
  position:sticky;             /* スクロールしても上部に貼り付く */
  top:0;                       /* ページ最上部に固定 */
  z-index:20;                  /* 他の要素より前面に表示 */
  background:var(--sticky-bg); /* 背景色(下のコンテンツが透けないように) */
  border-bottom:1px solid var(--border); /* 下に仕切り線 */
}

/* =========================================
   タブリスト(タブの並び)
   ========================================= */
#sticky-section .tabs{
  display:flex;                /* 横並び配置 */
  flex-wrap:wrap;              /* 幅が足りないとき折り返し */
  gap:8px;                     /* タブ同士の隙間 */
  padding:8px 0;               /* 上下の余白 */
  min-height:var(--sticky-h);  /* ★タブバーの高さを明示(JS基準にもなる) */
  align-content:center;        /* 複数行のとき中央揃え */
}

/* =========================================
   タブボタン(個々のタブ)
   ========================================= */
#sticky-section .tab{
  appearance:none;             /* ブラウザデフォルトの装飾を無効化 */
  border:1px solid var(--border); /* 通常時は薄い枠線 */
  border-radius:999px;         /* 丸みを最大にしてピル型に */
  background:#fff;             /* 背景は白 */
  color:var(--ink);            /* 通常文字色 */
  font-size:13px;              /* 小さめの文字サイズ */
  padding:8px 12px;            /* 内側余白 */
  cursor:pointer;              /* カーソルをポインターに */
  transition:background .2s, border-color .2s, color .2s;
                               /* ホバーやアクティブ時の色変化を滑らかに */
  font-weight:500;             /* やや太字 */
}

/* アクティブなタブの見た目 */
#sticky-section .tab[aria-selected="true"]{
  background:var(--accent);    /* 強調色の背景 */
  border-color:var(--accent);  /* 枠線も強調色に */
  color:#fff;                  /* 文字を白に */
  font-weight:600;             /* 少し太くして強調 */
}

/* フォーカス時(キーボード操作対応) */
#sticky-section .tab:focus-visible{
  outline:2px solid var(--accent); /* アクセント色でアウトライン表示 */
  outline-offset:2px;              /* 少し外側にずらす */
}

/* =========================================
   本文パネル(タブに対応するコンテンツ領域)
   ========================================= */
#sticky-section .panel{
  padding:24px;                  /* 内側余白を広めに */
  border:1px solid var(--border);/* 薄い枠線で囲む */
  border-radius:12px;            /* 柔らかい角丸 */
  background:var(--panel);       /* 白背景 */
  margin:24px 0 48px;            /* 上下の余白(下は広め) */
  line-height:1.9;               /* 読みやすい行間 */
}

/* パネル内の見出し(監視対象になる要素) */
#sticky-section .panel h3{
  margin:0 0 12px;               /* 下に余白 */
  font-size:18px;                /* 少し大きめ */
  scroll-margin-top:calc(var(--sticky-h) + 8px);
                                 /* ★アンカー移動時にStickyタブに隠れないよう補正 */
}

/* =========================================
   補助テキスト(注釈や説明用)
   ========================================= */
#sticky-section .muted{
  color:var(--muted);            /* 補助文字色で控えめに */
  font-size:13px;                /* 小さめサイズ */
}

コメント