How To Create Tabs
Learn how to build tabs: a row of buttons where each one shows its own panel of content.
Step 1: The HTML
Each tab button has a data-tab attribute with the id of the panel it opens. The first tab and panel start as active.
Example
<div class="tabs">
<button class="tab active" data-tab="morning">Morning</button>
<button class="tab" data-tab="evening">Evening</button>
<button class="tab" data-tab="weekend">Weekend</button>
</div>
<div class="panel active" id="morning">Classes from 9 am to 12 pm.</div>
<div class="panel" id="evening">Classes from 5 pm to 8 pm.</div>
<div class="panel" id="weekend">Saturday and Sunday, 10 am to 2 pm.</div>Attributes that start with data- are your own custom attributes. JavaScript reads them with element.dataset, so data-tab becomes dataset.tab.
Step 2: The CSS
All panels are hidden except the active one. The active tab gets a coloured bottom border.
Example
.tab { background: none; border: none; padding: 12px 18px; cursor: pointer; border-bottom: 3px solid transparent; }
.tab.active { border-bottom-color: #059669; color: #059669; font-weight: bold; }
.panel { display: none; padding: 16px; }
.panel.active { display: block; }Step 3: The JavaScript
When a tab is clicked: remove active from every tab and panel, then add it to the clicked tab and its panel.
Example
const tabs = document.querySelectorAll(".tab");
const panels = document.querySelectorAll(".panel");
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
tabs.forEach(function (t) { t.classList.remove("active"); });
panels.forEach(function (p) { p.classList.remove("active"); });
tab.classList.add("active");
document.getElementById(tab.dataset.tab).classList.add("active");
});
});querySelectorAll returns a list of all matching elements, and forEach runs the code once for each.
The Complete Example
Example
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
.tabs { border-bottom: 1px solid #ddd; }
.tab { background: none; border: none; padding: 12px 18px; font-size: 16px; cursor: pointer; border-bottom: 3px solid transparent; }
.tab:hover { background: #f3f4f6; }
.tab.active { border-bottom-color: #059669; color: #059669; font-weight: bold; }
.panel { display: none; padding: 16px; }
.panel.active { display: block; }
</style>
</head>
<body>
<h2>Class Timings</h2>
<div class="tabs">
<button class="tab active" data-tab="morning">Morning</button>
<button class="tab" data-tab="evening">Evening</button>
<button class="tab" data-tab="weekend">Weekend</button>
</div>
<div class="panel active" id="morning"><h3>Morning Batch</h3><p>Classes from 9 am to 12 pm, Monday to Friday.</p></div>
<div class="panel" id="evening"><h3>Evening Batch</h3><p>Classes from 5 pm to 8 pm, Monday to Friday.</p></div>
<div class="panel" id="weekend"><h3>Weekend Batch</h3><p>Saturday and Sunday, 10 am to 2 pm.</p></div>
<script>
const tabs = document.querySelectorAll(".tab");
const panels = document.querySelectorAll(".panel");
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
tabs.forEach(function (t) { t.classList.remove("active"); });
panels.forEach(function (p) { p.classList.remove("active"); });
tab.classList.add("active");
document.getElementById(tab.dataset.tab).classList.add("active");
});
});
</script>
</body>
</html>Try it Yourself »Adding a New Tab
Because the script loops over every .tab, adding a tab needs no new JavaScript:
- Add a button:
<button class="tab" data-tab="online">Online</button> - Add a panel:
<div class="panel" id="online">Live classes on Zoom.</div>
Summary
| Part | Role |
|---|---|
data-tab | Links a button to its panel |
.active class | Marks the visible tab and panel |
querySelectorAll + forEach | Handles any number of tabs |
Exercise
Exercise
A button has data-tab="fees". How does the script read that value?
