JavaScriptでのタブ切り替えの実装方法:UIをもっと便利に

投稿日

JavaScriptでのタブ切り替えの実装方法:UIをもっと便利に
投稿者:ブンタ ブンタ

タブ切り替えは、コンテンツを一つの画面に収めながら複数の情報を整理して見せることができる便利なインターフェースです。この記事では、JavaScriptでタブ切り替えを実装する方法を紹介します。ぜひ最後までお付き合いください。

完成イメージ

まずは完成イメージをご覧ください。

この動画のように、押したタブのコンテンツが表示される機能を作っていきます。

HTMLの記述

まずはHTMLで、タブの押す部分を記述します。

buttonタグで三つのボタンを作成し、divタグでそれらを囲んでいます。
アクセシビリティに配慮して、role属性でそれぞれにtabとtablistを記述しています。また、buttonタグにはaria-selectedとarea-controlsも記述しています。
aria-selectedは初期状態で選択しているものをtrueに、それ以外はfalseにします。
aria-controlsにはそれぞれの名前を記述しています。

<div class="tabs" role="tablist">
  <button
    class="tabButton"
    role="tab"
    aria-selected="true"
    aria-controls="tab1">tab1</button
  >
  <button
    class="tabButton"
    role="tab"
    aria-selected="false"
    aria-controls="tab2">tab2</button
  >
  <button
    class="tabButton"
    role="tab"
    aria-selected="false"
    aria-controls="tab3">tab3</button
  >
</div>

次はボタンを押した時に表示されるパネルの部分です。

divタグで3つのtabPanelというクラス名をつけたパネルを作り、それらをpanelsというクラス名をつけたdivタグで囲みます。
roleにはtabpanelを、idにはbuttonのaria-controlsでつけた名前と同じものを記述します。
また、初期状態で非表示のものにはhiddenをつけています。

<div class="panels">
  <div class="tabPanel" role="tabpanel" id="tab1">tab_panel1</div>
  <div class="tabPanel" role="tabpanel" id="tab2" hidden>tab_panel2</div>
  <div class="tabPanel" role="tabpanel" id="tab3" hidden>tab_panel3</div>
</div>

これらをまとめると以下のようになります。

<div class="tabBox">
  <div class="tabs" role="tablist">
    <button
      class="tabButton"
      role="tab"
      aria-selected="true"
      aria-controls="tab1">tab1</button
    >
    <button
      class="tabButton"
      role="tab"
      aria-selected="false"
      aria-controls="tab2">tab2</button
    >
    <button
      class="tabButton"
      role="tab"
      aria-selected="false"
      aria-controls="tab3">tab3</button
    >
  </div>
  <div class="panels">
    <div class="tabPanel" role="tabpanel" id="tab1">tab_panel1</div>
    <div class="tabPanel" role="tabpanel" id="tab2" hidden>tab_panel2</div>
    <div class="tabPanel" role="tabpanel" id="tab3" hidden>tab_panel3</div>
  </div>
</div>

これでHTMLは完成です。

JavaScriptの記述

まずはすべてのtabButton要素を取得します。そして、forEachでそれぞれのボタンをクリックした時の処理を記述します。

 document.querySelectorAll(".tabButton").forEach((button) => {
    button.addEventListener("click", () => {
    
    });
  });

クリックした時の処理は四つです。

まずはボタンの処理です。
現在、aria-selected属性がtrueになっている要素を取得し、falseにします。

document
  .querySelector('.tabButton[aria-selected="true"]')
  .setAttribute("aria-selected", "false");

そして、クリックしたボタンのaria-selectedをtrueにします。

button.setAttribute("aria-selected", "true");

次は、tabPanelのhiddenがついていないものを取得し、hiddenをつけます。表示から非表示に切り替えています。

document
  .querySelector(".tabPanel:not([hidden])")
  .setAttribute("hidden", true);

そして、クリックしたタブのパネルを表示させます。aria-controlsと同じIDのものを取得し、hiddenを消しています。

 document
  .getElementById(button.getAttribute("aria-controls"))
  .removeAttribute("hidden");

これらをまとめると以下のようになります。

document.querySelectorAll(".tabButton").forEach((button) => {
  button.addEventListener("click", () => {
    document
      .querySelector('.tabButton[aria-selected="true"]')
      .setAttribute("aria-selected", "false");
    button.setAttribute("aria-selected", "true");
    document
      .querySelector(".tabPanel:not([hidden])")
      .setAttribute("hidden", true);
    document
      .getElementById(button.getAttribute("aria-controls"))
      .removeAttribute("hidden");
  });
});

CSSの記述

CSSでは以下の点がポイントです。
ボタンにcursor: pointerを指定し、aria-selected属性がtrueの要素の場合(開いているタブのボタン)は、クリックしても反応しないようにしています。

.tabButton {
  cursor: pointer;
  &[aria-selected="true"] {
    pointer-events: none;
  }
}

これ以外は特に変わったことはしていないので、他のCSSの解説は省略します。

完成版

以下が完成版です。

See the Pen tabSwitching by Bunta (@bbunta) on CodePen.

タブをクリックするとパネルが切り替わっているのが確認できます。

まとめ

今回は、JavaScriptでのタブ切り替えの実装方法の解説をしました。

このサイトで紹介しているコードは、アクセシビリティを意識しながら最低限のコード量で実装しています。以前のブログも同じように書いていますので、ぜひ参考にしてみてください。

アコーディオンメニューの実装(JavaScriptありorなし)

JavaScriptを使ったモーダルウィンドウの実装方法:コード例と解説付き