繰り返し処理と関数を使って、タブUIをつくります。
キーワード:For文、関数
作成例(完成イメージ)
下記の順番で進めます。
- HTMLで基本の文書構造を作る
- CSSでUIを整える
- JavaScriptでイベントの発生条件を設定をする(クリック時)
- 具体的な処理を関数として記述する
【準備】フォルダ: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);
});
});
参考書籍・リンク