webdevpuneet.com

Tab Bar — Free HTML CSS JS Tabbed Interface Snippet

Tab Bar · Navigation · Plain HTML, CSS & JS · Live preview

CategoryNavigation

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>

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.

· Become a supporter

What's included

Features

Active tab underline using the negative margin border overlap trick — pure CSS
Instant panel switching with querySelectorAll — no animation library needed
display: none / display: block panel toggle — simple and reliable
Add any number of tabs — CSS and JS scale automatically
Live split-pane editor — preview updates as you type, no run button
Export as HTML file, React JSX component, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Save custom versions to IndexedDB via "Save as"
GitHub Gist sync — restore saved snippets on any device
No framework, no npm, no build step required

About this UI Snippet

Tab Bar Navigation — HTML, CSS & JavaScript Tabbed Interface

Screenshot of the Tab Bar snippet rendered live

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

  1. 1
    Load 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.
  2. 2
    Click 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.
  3. 3
    Add 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.
  4. 4
    Change 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.
  5. 5
    Export 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.
  6. 6
    Save 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

Product and content pages
Organise product details, specs, and reviews into tabs without a page reload. Works in any HTML template, CMS, or web app.
Learn the CSS border overlap trick
The active underline uses a margin-bottom: -2px technique. Edit the values in the CSS panel and watch the preview to understand exactly how the indicator works.
Prototype tabbed dashboards
Drop the tab bar into a dashboard prototype to switch between Analytics, Settings, and Reports sections. Test on mobile before committing to a framework.
Match your brand colours
Update the active indicator colour in .tab.active to your brand hex. Save under a custom name to reuse across multiple projects.
Add ARIA tab roles
Practice adding role="tablist", role="tab", and aria-selected to the markup. The JavaScript switchTab function is the right place to toggle aria-selected alongside classList.
Migrate to a React component
Use the JSX export as a starting point. Replace the inline onclick with useState for the active tab index and map over a tabs array to render panels dynamically.

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.