Tab Bar — Free HTML CSS JS Tabbed Interface Snippet
Tab Bar · Navigation · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="tabs">
<button class="tab active" onclick="switchTab(this,'p1')">Overview</button>
<button class="tab" onclick="switchTab(this,'p2')">Details</button>
<button class="tab" onclick="switchTab(this,'p3')">Reviews</button>
</div>
<div class="panels">
<div class="panel active" id="p1">
<h3>Overview</h3>
<p>High-level summary of the product or feature.</p>
</div>
<div class="panel" id="p2">
<h3>Details</h3>
<p>Specifications, dimensions, and technical info.</p>
</div>
<div class="panel" id="p3">
<h3>Reviews</h3>
<p>Customer ratings and feedback go here.</p>
</div>
</div>* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #f8fafc; padding: 24px; }
.tabs {
display: flex;
gap: 2px;
border-bottom: 2px solid #e2e8f0;
margin-bottom: 20px;
}
.tab {
padding: 8px 18px;
font-size: 14px;
font-weight: 500;
color: #64748b;
background: none;
border: none;
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -2px;
transition: color 0.15s, border-color 0.15s;
border-radius: 4px 4px 0 0;
}
.tab:hover { color: #1e293b; background: #f1f5f9; }
.tab.active { color: #6366f1; border-bottom-color: #6366f1; font-weight: 600; }
.panel { display: none; }
.panel.active { display: block; }
.panel h3 { font-size: 16px; font-weight: 700; color: #1e293b; margin-bottom: 8px; }
.panel p { font-size: 14px; color: #64748b; line-height: 1.6; }function switchTab(btn, panelId) {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));
btn.classList.add('active');
document.getElementById(panelId).classList.add('active');
}Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Tab Bar Navigation — HTML, CSS & JavaScript Tabbed Interface

A tab bar is one of the most common UI patterns on the web. Product pages use it to switch between Overview, Details, and Reviews. Dashboards use it to toggle between Analytics, Settings, and Reports. Web apps use it to organise content without navigating to a new page. Every time you need to show multiple panels of content in the same space, a tab bar is the right pattern — see also the sliding-indicator animated tabs and the vertical tabs variant.
This snippet gives you a complete, production-ready tab bar in plain HTML, CSS, and vanilla JavaScript. Three tab buttons switch three content panels. The active tab shows a coloured bottom border indicator. Clicking any tab instantly hides the previous panel and shows the new one. No libraries, no npm, no build step.
How the active underline indicator works
The underline technique used here is a classic CSS trick. The .tabs container has border-bottom: 2px solid #e2e8f0 — a light grey line across the full width. Each .tab button sits on top of that line with margin-bottom: -2px, which means the button overlaps the container border by exactly 2px. The active tab has border-bottom: 2px solid #6366f1 — a coloured border the same thickness as the container line. This coloured border sits exactly on top of the grey container line, visually replacing it for the active tab. The inactive tabs have border-bottom: 2px solid transparent, so they sit over the grey line without covering it.
How the panel switching works
The JavaScript uses a single switchTab(btn, panelId) function. When a tab is clicked, querySelectorAll('.tab').forEach(t => t.classList.remove('active')) removes the active class from all tabs, and querySelectorAll('.panel').forEach(p => p.classList.remove('active')) hides all panels. Then btn.classList.add('active') and document.getElementById(panelId).classList.add('active') highlight the clicked tab and show the matching panel. The panels use display: none and display: block — simple and reliable.
Adding more tabs
To add a fourth tab, add a new <button class="tab" onclick="switchTab(this,'p4')"> in the HTML and a matching <div class="panel" id="p4"> in the panels section. The CSS handles any number of tabs automatically — no changes needed.
Customising the active colour
The active indicator colour is #6366f1 (indigo). To change it, find .tab.active in the CSS panel and update both color and border-bottom-color to your brand colour. Change .tabs { border-bottom-color } if you want to update the inactive line colour too.
Accessibility improvements
For a production site, add role="tablist" to the .tabs container and role="tab" to each button. Add aria-selected="true" to the active tab and aria-selected="false" to the others — update these in the switchTab function alongside the classList changes. Add role="tabpanel" to each panel div. These additions make the tab bar fully usable with keyboard navigation and screen readers.
Saving your customised version
After editing the snippet to match your project, click "Save as" in the editor header, type a name, and press Enter. The version saves to your browser's IndexedDB and appears in the Saved tab in the sidebar. Connect GitHub Gist via the GitHub button to back it up and restore it on any device.
Step by step
How to Use
- 1Load the snippetClick "Tab Bar" in the sidebar Library tab. The HTML, CSS, and JS panels load instantly and the preview shows the three-tab interface.
- 2Click the tabs in the previewClick Overview, Details, and Reviews in the preview to see the panel switching in action and verify the active underline indicator.
- 3Add or rename tabsIn the HTML panel, update the button text and add new tab/panel pairs. Each button needs a matching panel id. The JS and CSS handle any number of tabs automatically.
- 4Change the active colourIn the CSS panel, update the colour value in .tab.active to match your brand. Change both color and border-bottom-color. The preview updates as you type.
- 5Export in your formatClick "HTML" to download a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind CSS version. "Copy all" copies the full code to clipboard.
- 6Save your versionClick "Save as", type a name, and press Enter. Your tab bar saves to IndexedDB and appears in the Saved tab for future sessions.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
A tab bar is a UI pattern that lets users switch between multiple content panels without navigating to a new page. One tab is active at a time, its panel is visible, and all other panels are hidden. Tab bars are used on product pages, dashboards, settings screens, and profile pages.
The .tabs container has a 2px grey border-bottom across its full width. Each tab button has margin-bottom: -2px, overlapping the container line. The active tab has a 2px coloured border-bottom that sits exactly on top of the grey line, visually replacing it. Inactive tabs have a transparent border-bottom, so the grey line shows through beneath them.
Add a new button element with class="tab" and onclick="switchTab(this,'p4')" in the .tabs div. Add a matching div with class="panel" and id="p4" in the .panels div. Fill in the content. No CSS or JS changes are needed — both scale to any number of tabs.
Find .tab.active in the CSS panel and update the color and border-bottom-color values to your brand hex. To change the inactive line colour, update border-bottom-color on the .tabs selector.
Yes. Replace display: none / display: block with opacity and a CSS transition. Set .panel { opacity: 0; transition: opacity 0.2s; pointer-events: none; } and .panel.active { opacity: 1; pointer-events: auto; }. The panels will fade in and out instead of snapping.
Add role="tablist" to the .tabs div, role="tab" to each button, and aria-selected="true/false" on each tab. Add role="tabpanel" to each panel div. In the switchTab function, update aria-selected alongside classList. This makes the component fully usable with keyboard navigation and screen readers.
Yes. Click "JSX" to download a React component, or "Tailwind" for a React + Tailwind version. For Vue or Svelte, the HTML pastes directly into a template block. Replace the inline onclick with a component method and manage the active state with reactive data.
No — the panel switching requires JavaScript to toggle the active class. If you need a zero-JS solution, you can use the CSS :checked hack with hidden radio inputs and sibling selectors, but that approach is more complex and harder to style consistently across browsers.
Yes. While the Tab Bar snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.