【JavaScript】タブ切り替え徹底解説
JavaScript でタブ切り替えを作る時コピペで作りがちなので、勉強を兼ねて詳しい解説を書きました。
こんな方におすすめです。
- タブ切り替えはコピペで済ませがち
- class のつけ外し操作がふんわりしかわかっていない
- 使いやすいタブの元コードが欲しい
コード
結論のコードです。
<div class="tabs">
<ul class="tab-list">
<li class="tab-item active" tabindex="0">タブ1</li>
<li class="tab-item" tabindex="0">タブ2</li>
<li class="tab-item" tabindex="0">タブ3</li>
</ul>
<div class="tab-content">
<div class="tab-panel active">
<h2>タブ1の内容</h2>
<p>ここはタブ1の内容が入ります</p>
</div>
<div class="tab-panel">
<h2>タブ2の内容</h2>
<p>ここはタブ2の内容が入ります</p>
</div>
<div class="tab-panel">
<h2>タブ3の内容</h2>
<p>ここはタブ3の内容が入ります</p>
</div>
</div>
</div>
.tabs {
max-width: 500px;
margin: 10% auto;
}
.tab-list {
display: flex;
}
.tab-item {
border-radius: 5px 5px 0 0;
background-color: #fff;
border: solid 1px skyblue;
padding: 0.5em 1.2em;
cursor: pointer;
}
.tab-content {
background-color: #f5f5f5;
}
.tab-panel {
display: none;
}
.tab-item.active {
background-color: skyblue;
color: #fff;
font-weight: bold;
}
.tab-panel.active {
display: block;
padding: 3%;
}
.tab-panel.active h2 {
font-size: 20px;
font-weight: bold;
}
// タブの見出し(tab-item)を取得
const tabItems = document.querySelectorAll(".tab-item");
tabItems.forEach((tabItem) => {
tabItem.addEventListener("click", () => {
// すべてのタブを非アクティブにする
tabItems.forEach((t) => {
t.classList.remove("active");
});
// すべてのコンテンツを非表示にする
const tabPanels = document.querySelectorAll(".tab-panel");
tabPanels.forEach((tabPanel) => {
tabPanel.classList.remove("active");
});
// クリックされたタブをアクティブにする
tabItem.classList.add("active");
// 対応するコンテンツを表示
const tabIndex = Array.from(tabItems).indexOf(tabItem);
tabPanels[tabIndex].classList.add("active");
});
});
コードの解説
HTML と CSS の説明は薄めです。
HTML
最初から表示させておきたい要素(タブ 1 の見出しとタブ 1 の中身)にactive
クラスをつけておきます。
<!-- 省略 -->
<ul class="tab-list">
<li class="tab-item active" tabindex="0">タブ1</li>
<li class="tab-item" tabindex="0">タブ2</li>
<li class="tab-item" tabindex="0">タブ3</li>
</ul>
<div class="tab-content">
<div class="tab-panel active"></div>
</div>
<!-- 省略 -->
CSS
開いているタブの見出し(active)をわかりやすくするために、背景色を水色にしています。
.tab-item.active {
background-color: skyblue;
color: #fff;
font-weight: bold;
}
開いていないタブの中身は見せたくないので、display:none;
で非表示にしておきます。
見せたいタブの中身に対してactive
をつけているので、いまのところタブ 1 の中身だけが見えています。
.tab-panel {
display: none;
}
見せたいタブにactive
がついているので、このときはdisplay: none;
を解除したいです。
display: block;
で要素が見えるようにします。
.tab-panel.active {
display: block;
padding: 3%;
}
JS
JS でどのようにタブを操作しているのか、詳しく解説します。
操作に必要な要素を指定する
タブの見出しをconst
で定義します。
const tabItems = document.querySelectorAll(".tab-item");
タブたちをまとめてtabItems
とします、そのうちのひとつがtabItem
となり、これにaddEventListener
をします。
addEventListener
で操作したいのは、タブの見出し(tab-item
)とタブの中身(tab-panel
)です。
先ほどはtabItems
のうちひとつのものをtabItem
としました。同じ名前は使えないので、ここではタブの見出し単体のことをt
としましょう。
3つあるタブ(tabPanels
)の中身のうちひとつを、tabPanel
とします。
クリックされたものがtabPanel
になるので、タブ2の中身やタブ3の中身がtabPanel
になるシーンもあります。
クリックされたら
addEventListener
は「クリックされたら」の動きを含んでいます。もし見出しのどれかがクリックされたら、classList.remove
で見出し・中身からactive
を削除します。
直後に見出しと中身に対してclassList.add("active");
をすることで、クリックされた要素だけにactive
クラスが追加される(不要なactive
クラスが削除される)仕組みです。
中身を表示させるために、tabItems
の個数(配列)を取得します。
tabIndex
は、tabItem
がtabItems
の中でいくつめなのかを調べています。
tabIndex
が0ならひとつめの要素(タブ1)、tabIndex
が1ならふたつめの要素(タブ2)にactive
クラスを追加して、と命令しています。
このスクショは、見出しを1から順番に押してconsole.log
で何個目なのかをわかりやすく表したものです。
console.log(`${tabIndex}個め`);
まとめ
JavaScriptで要素を操作する時のコツは以下の通りです。
- 操作したい要素をまず定義(const、letなど)
- もし○○したら…は
addEventListener
で表せる - 複数ある要素のうち、ひとつがクリックされたら何かしたいときは、forEachが便利
- 複数ある要素の命名時は末尾にsをつけて、クリックされたひとつの要素と名前を別にすることでわかりやすさUP
- 配列の操作(Array)にはインデックス(添え字)の活用が便利。
- 何を操作しているのかわからない、要素が取得できたか不安な時はとにかく
console.log
Discussion