ネイティブのJavaScript(脱jQuery)でタブ切り替えを実装するサンプル
javascript

ネイティブのJavaScript(脱jQuery)でタブ切り替えを実装するサンプル

by pranktone
サンプルコード

この記事は2020年3月4日に書かれたもので、内容が古く現在では推奨されていない方法の可能性もありますのでご注意ください。

ネイティブのJavaScript(脱jQuery)、アロー関数も使ってタブ切り替えを実装するサンプルを作ってみました。jQueryを使えない、使いたくない時の参考にしていただければと思います。

別記事のCSSとhtmlのradioボタンを使ってタブ切り替えを実装するサンプルと、jQueryを使ってタブ切り替えを実装するサンプルとの比較も兼ねて作ったので、htmlは似た構成にしています。

html

<ul class="tab-menu">
  <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger is-active" data-id="tab01">タブ1</span></li>
  <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab02">タブ2</span></li>
  <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab03">タブ3</span></li>
</ul><!-- .tab-menu -->

<div class="tab-content">
  <div class="tab-content__item js-tab-target is-active" id="tab01">
    <p>タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。</p>
  </div><!-- .tab-content__item -->
  <div class="tab-content__item js-tab-target" id="tab02">
    <p>タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。</p>
  </div><!-- .tab-content__item -->
  <div class="tab-content__item js-tab-target" id="tab03">
    <p>タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。</p>
  </div><!-- .tab-content__item -->
</div><!-- .tab-content -->

jQueryを使ってタブ切り替えを実装するサンプルと同様のhtmlです。
タブを切り替えるボタン要素(トリガーになる要素)は’.tab-trigger’、タブのコンテンツ(表示を切り替える要素)はここでは’.tab-content__item’という構成です。
タブ切り替えの要素はaタグにして、hrefでコンテンツ要素のIDを指定する方法も考えましたが、今回はspanタグにしてdata-idというdata属性を使用することで対応しました。

それぞれ、JavaScriptを使用して動かす要素になるので、JavaScriptでの操作のために ‘js-‘ というプレフィックスをつけた’.js-tab-trigger’, ‘.js-tab-target’というクラスをそれぞれにつけています。

CSS

/* タブメニュー */
.tab-menu {
  display: flex;
  margin: 0 -5px;
}

.tab-menu__item {
  box-sizing: border-box;
  padding: 0 5px;
}


.tab-trigger { /* label */
  text-align: left;
  cursor: pointer;
  display: block;
  padding: 10px;
  border: 1px solid #ccc;
  border-bottom: 0;
  border-radius: 5px 5px 0 0;
  overflow: hidden;
  background-color: lightgray;
  position: relative;
}

.tab-trigger.is-active {
  background-color: lightblue;
}


/* タブコンテンツ */
.tab-content {
  border: 1px solid #ccc;
}
.tab-content__item {
  box-sizing: border-box;
  padding: 20px;
  display: none;
  text-align: left;
}
.tab-content__item.is-active {
  display: block;
  animation: fade 0.5s ease;
}

@keyframes fade {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

CSSもjQueryを使ってタブ切り替えを実装するサンプルと同様の内容です。トリガー要素がaタグではないためcursor: pointerを付与。アニメーションをCSSでつけているので、タブコンテンツ要素のアクティブ時のクラス’.is-active’に@keyframesで作成したフェードアニメーションを付加しています。

JavaScript

document.addEventListener('DOMContentLoaded', () => {
    // タブメニュークラス'.js-tab-trigger'を持つ要素を取得
    const tabTriggers = document.querySelectorAll('.js-tab-trigger');
    // タブコンテンツクラス'.js-tab-target'を持つ要素を取得
    const tabTargets = document.querySelectorAll('.js-tab-target');

    // 要素の数の分だけループ処理をして値を取り出す
    for (let i = 0; i < tabTriggers.length; i++) {
        // タブメニュークリック時
        tabTriggers[i].addEventListener('click', (e) => {
            // クリックされた要素(メニュー要素[トリガー要素])を取得
            let currentMenu = e.currentTarget;
            // ターゲットとなる要素(タブメニューdata属性値と等しいid値を持つコンテンツ要素[ターゲット要素])を取得
            let currentContent = document.getElementById(currentMenu.dataset.id);

            // すべてのタブメニューの'is-active'クラスを削除
            for (let i = 0; i < tabTriggers.length; i++) {
                tabTriggers[i].classList.remove('is-active');
            }
            // クリックしたタブメニューに'is-active'クラスを追加
            currentMenu.classList.add('is-active');

            // タブコンテンツを非アクティブにする
            for (let i = 0; i < tabTargets.length; i++) {
                tabTargets[i].classList.remove('is-active');
            }
            // 対象コンテンツ(指定したIDの要素があったら)を表示させる
            if(currentContent !== null) {
                currentContent.classList.add('is-active');
            }
        });
    }
});

はじめにタブメニュークラス’.js-tab-trigger’を持つ要素をdocument.querySelectorAllで取得し、配列としてtabTriggersに格納します。
同様にタブコンテンツクラス’.js-tab-target’を持つ要素をdocument.querySelectorAllで取得し、配列としてtabTargetsに格納します。

トリガーの数だけfor分でループ処理を行い、値を取り出します。

トリガー要素の’.js-tab-trigger’がクリックされたら、クリックされた要素を特定するために変数currentMenuに格納、その変数から指定のターゲット要素をdata-id属性から取得して、変数currentContentとして保持します。

タブメニュー全てのアクティブクラスの’.is-active’をトリガーの数だけfor分でループさせて削除、クリックされた要素(currentMenu)にのみ’.is-active’を付加します。

コンテンツ要素も一度、全ての要素から’.is-active’を削除し、クリックしたトリガー要素から取得したIDを元に、要素があったら’.is-active’を付加し、表示する形にしました。

デモ GitHub

タブ切り替え実装に関する記事

feedly

コメント

まだ、コメントはありません。

トラックバックURL

https://blog.pranktone.net/web/javascript/20200304150200.html/trackback
ありきたりな日常と
それとない非日常を
紡ぐ記録
SKIP