タブ切り替えメニューの実装

このページの目的

複数のコンテンツを、タブをクリックすることで切り替えて表示するUI(ユーザーインターフェース)の実装方法を学びます。
HTMLで骨組みを作り、CSSで見た目を整え、JavaScriptで実際に切り替わる「動き」を制御するのが一連の流れです。

smart_display動作サンプル

まずは、実際に動作するサンプルを触ってみましょう。タブをクリックして、コンテンツが切り替わるのを確認してみてください。

タブ1のコンテンツ

これはタブ1のコンテンツエリアです。クリックで内容が切り替わります。

タブ2のコンテンツ

こちらはタブ2のコンテンツです。画像なども自由に配置できます。

タブ3のコンテンツ

3番目のコンテンツが表示されています。

  • リスト
  • なども
  • OKです

code実装コード解説

このタブ切り替えは、以下の3つの要素を連携させて作ります。

1. HTMLの構造

タブのボタン部分(.tab-list)と、表示するコンテンツ部分(.tab-panels)をセットで用意します。aria属性は、アクセシビリティ向上のための重要な記述です。

<!-- タブ全体のコンテナ -->
<div class="tabs-container">
  <!-- タブボタンのリスト -->
  <div role="tablist" aria-label="タブ切り替え" class="tab-list">
    <button role="tab" aria-selected="true" aria-controls="panel-a" id="tab-a" class="tab-button is-active">タブ1</button>
    <button role="tab" aria-selected="false" aria-controls="panel-b" id="tab-b" class="tab-button">タブ2</button>
    <button role="tab" aria-selected="false" aria-controls="panel-c" id="tab-c" class="tab-button">タブ3</button>
  </div>

  <!-- 表示パネルのコンテナ -->
  <div class="tab-panels">
    <div role="tabpanel" id="panel-a" aria-labelledby="tab-a" class="tab-panel is-active">
      <p>タブ1のコンテンツです。</p>
    </div>
    <div role="tabpanel" id="panel-b" aria-labelledby="tab-b" class="tab-panel">
      <p>タブ2のコンテンツです。</p>
    </div>
    <div role="tabpanel" id="panel-c" aria-labelledby="tab-c" class="tab-panel">
      <p>タブ3のコンテンツです。</p>
    </div>
  </div>
</div>

2. CSSのスタイル

.is-activeクラスが付いているタブボタンとパネルだけが見えるように、スタイリングします。

/* タブボタンのリスト */
.tab-list {
  display: flex;
  gap: 4px;
}
.tab-button {
  padding: 10px 20px;
  border: 1px solid #ccc;
  border-bottom: none;
  background-color: #eee;
  cursor: pointer;
  border-radius: 6px 6px 0 0;
}
/* アクティブなタブボタンのスタイル */
.tab-button.is-active {
  background-color: #fff;
  font-weight: bold;
}

/* 表示パネル */
.tab-panel {
  display: none; /* ★普段は非表示にしておく */
  padding: 20px;
  border: 1px solid #ccc;
}
/* アクティブなパネルだけ表示 */
.tab-panel.is-active {
  display: block; /* ★is-activeクラスが付いたら表示 */
}

3. JavaScriptの処理

タブボタンがクリックされた時の処理を記述します。

function initTabs() {
    const tabContainers = document.querySelectorAll('.tabs-container');

    tabContainers.forEach(container => {
        const tabButtons = container.querySelectorAll('.tab-button');
        const tabPanels = container.querySelectorAll('.tab-panel');

        if (tabButtons.length > 0 && tabPanels.length > 0) {
            tabButtons.forEach(button => {
                button.addEventListener('click', (e) => {
                    const targetPanelId = e.currentTarget.getAttribute('aria-controls');

                    // すべてのボタンとパネルのアクティブ状態を解除
                    tabButtons.forEach(btn => {
                        btn.classList.remove('is-active');
                        btn.setAttribute('aria-selected', 'false');
                    });
                    tabPanels.forEach(panel => {
                        panel.classList.remove('is-active');
                    });

                    // クリックされたボタンと対応するパネルをアクティブに
                    e.currentTarget.classList.add('is-active');
                    e.currentTarget.setAttribute('aria-selected', 'true');
                    const targetPanel = document.getElementById(targetPanelId);
                    if (targetPanel) {
                        targetPanel.classList.add('is-active');
                    }
                });
            });
        }
    });
}

// ページの読み込み完了時に実行
document.addEventListener('DOMContentLoaded', initTabs);

チェックポイント

✅ タブボタンをクリックすると、対応するコンテンツが表示されるか?
✅ アクティブなタブとそうでないタブの見た目が異なっているか?
✅ HTMLにaria属性が正しく設定され、アクセシビリティが確保されているか?