CSS Tabs Generator
Tabs are everywhere: settings panes, documentation sites, product galleries. Native HTML has no dedicated tab element, so developers roll their own. This generator builds a simple tab bar in HTML + CSS: an accent colour for the active tab, a corner radius for the buttons, and a hover state. Paste the markup into your project and wire up the tab switching with your own JavaScript.
How to build tabs
-
1
Pick an accent colour
The background and text colour of the active tab. Choose a colour that matches your brand.
-
2
Set the corner radius
Rounds the top corners of the tab buttons. Higher values give a softer look.
-
3
Edit the labels
The output starts with three buttons, "Overview", "Details" and "Settings": rename them to match your content.
-
4
Copy the code
The tab markup comes with its own <style> block. Paste both into your page.
-
5
Add tab switching
The generator produces the visual part only. Hook the buttons up to your own JavaScript or UI library to show and hide the panels.
Correct accessible markup
<div class="tabs">
<div role="tablist" aria-label="Product info">
<button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1" tabindex="0">Overview</button>
<button role="tab" id="tab-2" aria-selected="false" aria-controls="panel-2" tabindex="-1">Specs</button>
<button role="tab" id="tab-3" aria-selected="false" aria-controls="panel-3" tabindex="-1">Reviews</button>
</div>
<section role="tabpanel" id="panel-1" aria-labelledby="tab-1">...</section>
<section role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>...</section>
<section role="tabpanel" id="panel-3" aria-labelledby="tab-3" hidden>...</section>
</div>
Critical attributes:
role="tablist"wraps the buttons.role="tab"on each button, witharia-selectedandaria-controls.tabindexuses the roving tabindex pattern: only the active tab is0, others are-1. Arrow keys move focus between them.role="tabpanel"on each panel, witharia-labelledbypointing to its tab.hiddenon inactive panels (notdisplay: nonealone, the attribute is what AT uses).
Keyboard contract
| Key | Action |
|---|---|
| Tab | Move into / out of the tablist |
| ArrowLeft | Previous tab (wraps to last) |
| ArrowRight | Next tab (wraps to first) |
| Home | First tab |
| End | Last tab |
| Enter / Space | Activate focused tab (if manual activation) |
Automatic activation (tab switches as focus moves) vs. manual (focus moves, tab activates on Enter), WAI-ARIA allows both. Automatic is easier for sighted users; manual is better when tab content is heavy to render.
Underlined style
[role="tablist"] {
display: flex;
border-bottom: 1px solid #e5e7eb;
}
[role="tab"] {
padding: 0.75rem 1rem;
background: transparent;
border: 0;
color: #6b7280;
position: relative;
cursor: pointer;
}
[role="tab"][aria-selected="true"] {
color: #111827;
}
[role="tab"][aria-selected="true"]::after {
content: "";
position: absolute;
left: 1rem; right: 1rem; bottom: -1px;
height: 2px;
background: #2563eb;
}
Pilled style
[role="tab"] {
padding: 0.5rem 0.9rem;
border-radius: 9999px;
border: 0;
background: transparent;
}
[role="tab"][aria-selected="true"] {
background: #2563eb;
color: #fff;
}
Focus visible
Always draw a focus ring when focus arrives via keyboard:
[role="tab"]:focus-visible {
outline: 2px solid #60a5fa;
outline-offset: 2px;
}
The JavaScript
Roughly:
const tabs = document.querySelectorAll('[role="tab"]');
tabs.forEach(tab => {
tab.addEventListener('click', () => activate(tab));
tab.addEventListener('keydown', e => {
const i = [...tabs].indexOf(tab);
if (e.key === 'ArrowRight') tabs[(i + 1) % tabs.length].focus();
if (e.key === 'ArrowLeft') tabs[(i - 1 + tabs.length) % tabs.length].focus();
if (e.key === 'Home') tabs[0].focus();
if (e.key === 'End') tabs[tabs.length - 1].focus();
});
});
function activate(tab) {
tabs.forEach(t => {
const panel = document.getElementById(t.getAttribute('aria-controls'));
const active = t === tab;
t.setAttribute('aria-selected', active);
t.setAttribute('tabindex', active ? '0' : '-1');
panel.hidden = !active;
});
tab.focus();
}
Thirty lines total, zero dependencies.
Tabs vs. accordions
On narrow screens, tab rows get cramped. Common pattern: tabs on desktop, accordion on mobile. Use a container query or media query to switch visual treatment without changing the ARIA roles.
Frequently Asked Questions
For accessible tabs, yes. Without role="tablist" and role="tab", screen readers treat the buttons as regular buttons and users lose the navigation convention. The alternative is a plain <details> / <summary> accordion, which has built-in semantics.
Automatic (tab activates as focus moves) is fine when each tab’s content is cheap to render. Manual (focus moves, Enter activates) is better when switching tabs triggers heavy work like fetching or rendering a large form.
For content-bearing tabs (documentation, product tabs), yes, use a hash (#specs) or query param so links can deep-link to a specific tab and the active tab persists across reloads. For UI tabs (settings panes) the URL is optional.
Only with the checkbox/radio hack, which lacks arrow-key navigation and ARIA states. For a genuinely accessible implementation, the small JS snippet is worth it. If you need server-rendered fallbacks, link each tab to a unique URL and render the corresponding panel server-side.
Related Tools
ASCII Table Reference
Full ASCII table from 0 to 127 with decimal, hex, octal, binary, standard names and HTML numeric-reference notation, including NUL, LF and DEL.
Color Palette Generator
Generate monochromatic, analogous, complementary, triadic or tetradic color palettes from a base HEX color and export copy-ready CSS variables.
HEX Color Picker
Pick or enter a HEX colour and get RGB, HSL, approximate CMYK, relative luminance and contrast ratios against white and black.
HTML Character Reference
Searchable list of HTML entities, their named and numeric codes, and a one-click copy for special characters and symbols.
JSON Formatter
Paste JSON to pretty-print with 2 or 4 spaces, minify it to compact output, or run a quick syntax check before copying the result.
Phone Validator
Validate phone numbers by country, detect the region and type, and normalize valid numbers to E.164, international, national and RFC 3966 formats.
Tool available in other languages
- CSS Tab Generatörü [TR]
- Generador de Pestañas CSS [ES]
- مولد علامات التبويب CSS [AR]
- Générateur d'onglets CSS [FR]
- CSS Tabs Generator [NL]
- CSS 탭 생성기 [KO]
- Generator Tab CSS [ID]
- Trình tạo tab CSS [VI]
- CSS标签生成器 [ZH]
- CSSタブジェネレーター [JA]
- ตัวสร้างแท็บส์ CSS [TH]
- Gerador de Abas CSS [PT]
- CSS-Tabs-Generator [DE]
- CSS-flikgenerator [SV]
- Generator kart (tabs) CSS [PL]
- Generatore di schede CSS [IT]
- Генератор вкладок CSS [RU]