こんにちは、Ryohei(@ityryohei)です!

本記事では、JavaScriptでタブ切り替えメニューの作り方をご紹介しています。単数・複数の両方の作り方に対応しています。

JavaScriptでタブ切り替えメニューを作りたいんだけど、どうすればいいんだろう?

上記の疑問にお答えします。

では、解説していきます。

本記事で作成するタブ切り替えメニュー

本記事で作成するタブ切り替えメニューです。単数設置の場合と、複数設置の場合で処理内容を変更しています。

タブ切り替えメニュー(単数)

See the Pen Untitled by ryohei (@intotheprogram) on CodePen.

タブ切り替えメニュー(複数)

See the Pen 8191-2 by ryohei (@intotheprogram) on CodePen.

単数・複数で少し記述を変えていますが、使いやすい方を選択して実装していただければと思います。

タブ切り替えメニュー(単数)

一つのタブ切り替えメニューをページ内に作成します。すべてのスタイル情報を掲載すると記事が長くなってしまうので、一部を省略して掲載しています。JavaScriptの処理については、適宜コメントを入れてありますので、処理内容についてはコメントをご確認いただければと思います。

HTML

<!-- tab -->
<div class="tab">
    
    <!-- tab-menu -->
    <div class="tab-menu">
        <div class="tab-menu__item tab-menu__item--active" data-tab-menu-item="0">Tab Menu1</div>
        <div class="tab-menu__item" data-tab-menu-item="1">Tab Menu2</div>
        <div class="tab-menu__item" data-tab-menu-item="2">Tab Menu3</div>
        <div class="tab-menu__item" data-tab-menu-item="3">Tab Menu4</div>
    </div><!-- /tab-menu -->
    
    <!-- tab-content -->
    <div class="tab-content">
        <div class="tab-content__item tab-content__item--active">Tab Content1</div>
        <div class="tab-content__item">Tab Content2</div>
        <div class="tab-content__item">Tab Content3</div>
        <div class="tab-content__item">Tab Content4</div>
    </div><!-- /tab-content -->
    
</div><!-- /tab -->

SCSS

// _tab-menu.scss
.tab-menu {
    display: flex;
    
    &__item {
        flex: 1;
        
        &--active {
            color: #fff;
            background-color: #000;
        }
    }
}

// _tab-content.scss
.tab-content {
    
    &__item {
        display: none;
        
        &--active {
            display: flex
        }
    }
}

JavaScript(Vanilla JS)

const tab = ()=>{
    
    // 要素取得(引数の値をセレクターに使用)
    let tabMenuItems = document.querySelectorAll('.tab-menu__item');
    let tabContentItems = document.querySelectorAll('.tab-content__item');
    
    // アクティブクラス名を指定
    let tabMenuItemActiveClass = 'tab-menu__item--active';
    let tabContentItemActiveClass = 'tab-content__item--active';
    
    // タブメニューアイテム、タブコンテンツアイテムの全アクティブクラスを削除する関数
    let removeAllActiveClass = ()=>{
        tabMenuItems.forEach(item => item.classList.remove(tabMenuItemActiveClass));
        tabContentItems.forEach(item => item.classList.remove(tabContentItemActiveClass));
    };

    // タブメニューアイテム分ループする
    tabMenuItems.forEach((item)=>{
        
        // 各タブメニューアイテムにクリックイベントを設定する
        item.addEventListener('click', (e)=>{
            
            // 関数実行
            removeAllActiveClass();
            
            // クリックされたタブメニューアイテムにアクティブクラスを付加する
            e.target.classList.add(tabMenuItemActiveClass);
            
            // クリックされたタブメニューアイテムのdata属性の値の順番にあるタブコンテンツアイテムにアクティブクラスを付加する
            tabContentItems[e.target.dataset.tabMenuItem].classList.add(tabContentItemActiveClass);
            
        });
    });
}

// 関数実行
tab();

実行結果

See the Pen Untitled by ryohei (@intotheprogram) on CodePen.

タブ切り替えメニュー(複数)


前項でご紹介したタブ切り替えメニュー(単数)を必要な数だけ複製し、複数のタブ切り替えメニューを作成することは可能ですが、冗長になる可能性があるため、より汎用的に再利用しやすくするために少し手を加えます。

HTML

<!-- tab -->
<div class="tab">
    
    <!-- tab-menu -->
    <div class="tab-menu js-tab-menu1">
        <div class="tab-menu__item _active" data-tab-menu-item="0">Tab Menu1</div>
        <div class="tab-menu__item" data-tab-menu-item="1">Tab Menu2</div>
        <div class="tab-menu__item" data-tab-menu-item="2">Tab Menu3</div>
        <div class="tab-menu__item" data-tab-menu-item="3">Tab Menu4</div>
    </div><!-- /tab-menu -->
    
    <!-- tab-content -->
    <div class="tab-content js-tab-content1">
        <div class="tab-content__item _active">Tab Content1</div>
        <div class="tab-content__item">Tab Content2</div>
        <div class="tab-content__item">Tab Content3</div>
        <div class="tab-content__item">Tab Content4</div>
    </div><!-- /tab-content -->
    
</div><!-- /tab -->


<!-- tab -->
<div class="tab">
    
    <!-- tab-menu -->
    <div class="tab-menu js-tab-menu2">
        <div class="tab-menu__item _active" data-tab-menu-item="0">Tab Menu1</div>
        <div class="tab-menu__item" data-tab-menu-item="1">Tab Menu2</div>
        <div class="tab-menu__item" data-tab-menu-item="2">Tab Menu3</div>
        <div class="tab-menu__item" data-tab-menu-item="3">Tab Menu4</div>
    </div><!-- /tab-menu -->
    
    <!-- tab-content -->
    <div class="tab-content js-tab-content2">
        <div class="tab-content__item _active">Tab Content1</div>
        <div class="tab-content__item">Tab Content2</div>
        <div class="tab-content__item">Tab Content3</div>
        <div class="tab-content__item">Tab Content4</div>
    </div><!-- /tab-content -->
    
</div><!-- /tab -->

SCSS

// _tab-menu.scss
.tab-menu {
    display: flex;
    
    &__item {
        flex: 1;
        
        &._active {
            color: #fff;
            background-color: #000;
        }
    }
}

// _tab-content.scss
.tab-content {
    
    &__item {
        display: none;
        
        &._active {
            display: flex
        }
    }
}

JavaScript(Vanilla JS)

const tab = (menu, content)=>{
    
    // 要素取得(引数の値をセレクターに使用)
    let tabMenu = document.querySelector(menu);
    let tabContent = document.querySelector(content);
    let tabMenuItems = [...tabMenu.children];
    let tabContentItems = [...tabContent.children];
    
    // アクティブクラス名を指定
    let activeClass = '_active';
    
    // タブメニューアイテム、タブコンテンツアイテムの全アクティブクラスを削除する関数
    let removeAllActiveClass = ()=>{
        tabMenuItems.forEach(item => item.classList.remove(activeClass));
        tabContentItems.forEach(item => item.classList.remove(activeClass));
    };

    // タブメニューアイテム分ループする
    tabMenuItems.forEach((item)=>{
        
        // 各タブメニューアイテムにクリックイベントを設定する
        item.addEventListener('click', (e)=>{
            
            // 関数実行
            removeAllActiveClass();
            
            // クリックされたタブメニューアイテムにアクティブクラスを付加する
            e.target.classList.add(activeClass);
            
            // クリックされたタブメニューアイテムのdata属性の値の順番にあるタブコンテンツアイテムにアクティブクラスを付加する
            tabContentItems[e.target.dataset.tabMenuItem].classList.add(activeClass);
            
        });
    });
}

// 関数実行
tab('.js-tab-menu1', '.js-tab-content1');
tab('.js-tab-menu2', '.js-tab-content2');

実行結果

See the Pen 8191-2 by ryohei (@intotheprogram) on CodePen.

これで複数のタブ切り替えメニューを同一ページ内に設置することが可能です。

最後に

先日の案件にて久しぶりにタブ切り替えメニューを実装する機会があり、過去に私が作成したスクリプトを参考にしようとブログ内を検索したところ、記事にまとめていなかったことに気づき、今回一から新しく作り直したものを整理してまとめてみました。タブメニュー以外にもアコーディオンメニューも記事にしていなかったようなので、近日中にアコーディオンメニューの作り方についてもご紹介できればと思います。

以上、JavaScriptのタブ切り替えメニューの作り方のご紹介でした!

この記事を書いた人

Ryohei

Webエンジニア / ブロガー

福岡のWeb制作会社に務めるWebエンジニアです。エンジニア歴は10年程で、好きな言語はPHPとJavaScriptです。本サイトは私がインプットしたWebに関する知識を整理し、共有することを目的に2015年から運営しています。Webに関するご相談があれば気軽にお問い合わせください。

JavaScriptを基礎からしっかりと学びたい方へ

下記の参考書がおすすめです。私がJavaScript入門時に購入した書籍で、基礎から応用まで多様なサンプルを用いて解説されています。ページ数は多いですが、内容が伴っているのですらすら読めます。腰を据えて学びたい方に最良の一冊となっています。