• Skip to primary navigation
  • Skip to main content

Nagashima Laboratory

  • Home
  • Lecture
  • Note
  • Index
  • About

タブUI(JavaScript)

繰り返し処理と関数を使って、タブUIをつくります。

キーワード:For文、関数

作成例(完成イメージ)

  • 作成例:https://ngsm-syr.github.io/javascript_tab_a/
  • コード:https://github.com/ngsm-syr/javascript_tab_a/

下記の順番で進めます。

  1. HTMLで基本の文書構造を作る
  2. CSSでUIを整える
  3. JavaScriptでイベントの発生条件を設定をする(クリック時)
  4. 具体的な処理を関数として記述する

【準備】フォルダ:javascript_tab

①JavaScriptを書くための準備で作成したフォルダ(空のHTML、CSS、JavaScriptが入っている)を準備します。GitHubからもダウンロードできます。

②フォルダの名前を「javascript_tab」に変更します

HTMLの準備

まず、コンテンツ部分を用意します。

▼index.html

  <header>
    <h1>tabUI</h1>
  </header>
  <main>
   <div class="tab-container">
        <ul class="tab-buttons">
            <li class="tab-button active" data-id="news">最新記事</li>
            <li class="tab-button" data-id="popular">人気記事</li>
            <li class="tab-button" data-id="category">カテゴリ別</li>
        </ul>

        <div class="tab-contents">
            <div class="tab-content active" id="news">
                <h2>最新記事</h2>
                <p>ここに最新記事の説明が入ります。</p>
            </div>
            <div class="tab-content" id="popular">
                <h2>人気記事</h2>
                <p>ここに人気記事の説明が入ります。</p>
            </div>
            <div class="tab-content" id="category">
                <h2>カテゴリ別</h2>
                <p>ここにカテゴリ別の記事が入ります。</p>
            </div>
        </div>
    </div>

  </main>

li要素についているデータ属性(data-id=" ")と、タブ(class="tab-content")につくid名が一致するようにします。

activeクラスがついた要素が、初回画面で開示されているタブになります。

▼style.css

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  padding: 1rem;
}

h1 {
  text-align: center;
  margin-bottom: 1rem;
}

.tab-container {
  max-width: 600px;
  margin: auto;
}

.tab-buttons {
  list-style: none;
  padding: 0;
  display: flex;
  border-bottom: 2px solid #ddd;
}

.tab-button {
  padding: 0.5rem 1rem;
  margin-right: 0.25rem;
  cursor: pointer;
  border-top-right-radius: 0.5rem;
  border-top-left-radius: 0.5rem;
  background-color: #f0f0f0;
  position: relative;
  z-index: 2;
  border: 2px solid transparent;
  border-bottom: none;
}

.tab-button.active {
  background-color: #fff;
  border: 2px solid #ddd;
  border-bottom: none;
  margin-bottom: -2px;
}

.tab-content {
  display: none;
  padding: 1rem;
  border: 2px solid #ddd;
  border-top: none;
  min-height: 200px;
  border-bottom-right-radius: 0.5rem;
  border-bottom-left-radius: 0.5rem;
  position: relative;
  z-index: 1;
}

.tab-content.active {
  display: block;
}

footer {
  text-align: center;
  margin-top: 2rem;
  padding: 1rem 0;
}

定数を宣言をする(定数を決める)

▼script.js

const allTabButtons = document.querySelectorAll('.tab-button');
const allTabContents = document.querySelectorAll('.tab-content');

console.log('タブボタン数:', allTabButtons.length);
console.log('コンテンツ数:', allTabContents.length);

console.logを記述することで定数の中身を確認します。タブの数、コンテンツの数が正しく取得できていることを確認してください。

イベントの設定(動作のきっかけを作る)

addEventListener()を使って、動作を引き起こすためのきっかけを設定します。きっかけにあたるものを「イベント」と言います。

click は クリックしたときに動作するイベントです。

▼script.js(上記の定数宣言の下に記載)

//←この位置に関数を記載

//イベント
for (let i = 0; i < allTabButtons.length; i++) {
    allTabButtons[i].addEventListener('click', (event) => {
        console.log('タブがクリックされました');

        const clickedTabId = event.currentTarget.dataset.id;
        console.log('クリックされたID:', clickedTabId);

        if (!clickedTabId) return;

        resetAllTabs();
        activateTab(clickedTabId);
    });
}

この段階でブラウザで確認しコンソールを確認します。

タブがクリックされました
クリックされたID: xxxxxxxx

というログが表示されれれば、動作に問題はありません。

resetAllTabs()、activateTab()、2つの関数が未定義ですのでエラーが出ます。この時点では正常な動作です。

【参考】For文

For文とは繰り返し処理をする記述方法です。簡単な例でforの使用例を見ていきます。

▼コンソールに入力

for( let i = 0; i < 5; i++) {
  console.log(i);
}
  • let i = 0; …初期化処理。iに0を代入
  • i < 5; …ループ継続のための条件式
  • i++ …ループごとの最後に実行される式

= 0からスタートして、ループごとに1増えていきます。i が5より小さいとき(4)まで実行されるので、最終的には5回の処理が行われます。

関数を定義する

関数とは一連の動作をひとまとめにしたものです。

今回の例でいうと、機能に関する部分を関数にすることで、イベントリスナーの処理の記述を簡潔にしています。また、同じような処理を他の部分でも使用したい場合に、使い回すことができます。

関数1:リセット処理

▼script.js(最初の定数宣言と、For文の間に記載)

//←この位置に関数を記載

function resetAllTabs() {
    console.log('リセット開始');
    // 全てのタブから .active クラスを削除する
    for (let i = 0; i < allTabButtons.length; i++) {
        allTabButtons[i].classList.remove('active');
    }
    // 全てのコンテンツから .active クラスを削除する
    for (let i = 0; i < allTabContents.length; i++) {
        allTabContents[i].classList.remove('active');
    }
    console.log('リセット完了');
}

//イベント

関数2:タブとコンテンツの有効化

▼script.js(上記関数1の下に記載)

function resetAllTabs() {
//中略
}

function activateTab(tabId) {
    console.log('有効化開始:', tabId);
    const content = document.getElementById(tabId);
    const button = document.querySelector(`.tab-button[data-id="${tabId}"]`);
    
    console.log('見つかったコンテンツ:', content);
    console.log('見つかったボタン:', button);
    
    if (content) content.classList.add('active');
    if (button) button.classList.add('active');
    console.log('有効化完了');
}

//イベント

【参考】テンプレートリテラル

テンプレートリテラルを使うと、変数の値を文字列に挿入することができます。
「``内で変数を${ } で囲う」ことで使用できます。記号` は、バッククォート(逆引用符)です。

// 通常の文字列(シングル/ダブルクォート)
const selector1 = '.tab-button[data-id="' + tabId + '"]';

// テンプレートリテラル(バッククォート)
const selector2 = `.tab-button[data-id="${tabId}"]`;

【参考】forEach文に書き換える

今回のケースでは、同じ処理をforEachでも書くことができます。

▼script.js(関数部分)

function resetAllTabs() {

    allTabButtons.forEach(button => {
        button.classList.remove('active');
    });

    allTabContents.forEach(content => {
        content.classList.remove('active');
    });
}

▼script.js(イベント部分)

allTabButtons.forEach(button => {
    button.addEventListener('click', (event) => {
        const clickedTabId = event.currentTarget.dataset.id;

        if (!clickedTabId) return;

        resetAllTabs();
        activateTab(clickedTabId);
    });
});
  • 作成例:https://ngsm-syr.github.io/javascript_tab_b/
  • コード:https://github.com/ngsm-syr/javascript_tab_b/

参考書籍・リンク

  • 「独習JavaScript」CodeMafia 外村将大, 翔泳社, 2021
  • https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for
  • https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals
  • https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

2025-10-13 (Last Modified: 2025-10-14) Category: 資料 Tags:javascript

Copyright © 2023–2025 · Nagashima Sayuri Laboratory