Tabs
Last updated:
Practical patterns for accessible tab semantics, keyboard behaviour, mobile layouts, and when not to use tabs at all.
01 — Foundation
Tabs are a navigation pattern
Used well, tabs reduce complexity. Used badly, they hide content users never discover.
Tabs organise related content into manageable sections. They are not decorative UI furniture — they are navigation. Broken tab systems create hidden content, keyboard traps, and mobile usability problems quickly.
This pattern defines practical expectations for accessible, maintainable tab interfaces — real usability, not component-library theatre.
02 — When
When tabs help — and when they do not
Tabs should simplify the interface, not bury important information.
Use tabs when sections are
- strongly related and similar in structure
- equal in importance and switched between often
- good fits for account areas, settings, specs, or comparison views
Avoid tabs when
- content is sequential, very long, or rarely switched
- users must open every tab to understand something critical
- a normal page, accordion, or stacked layout would be clearer — especially on mobile
03 — Semantics
Semantics and keyboard support
Do not fake tabs with generic div chaos.
- use
tablist,tab, andtabpanelroles with correct relationships - arrow keys move between tabs; activation behaviour stays predictable
- Tab moves into the list and into panel content logically
- visible focus at all times — never remove outlines without a replacement
<div role="tablist" aria-label="Account settings">
<button
type="button"
role="tab"
id="tab-billing"
aria-selected="true"
aria-controls="panel-billing">
Billing
</button>
<button
type="button"
role="tab"
id="tab-security"
aria-selected="false"
aria-controls="panel-security"
tabindex="-1">
Security
</button>
</div>
<div
role="tabpanel"
id="panel-billing"
aria-labelledby="tab-billing">
<!-- billing content -->
</div>04 — States
Active state and discoverability
Users should never wonder which tab is open or whether hidden content exists.
- active tab obvious through contrast, underline, border, or background — not subtle colour alone
- inactive panels hidden correctly without making critical information undiscoverable
- short, specific labels — Billing, Security — not Information, Details, Misc
05 — Mobile
Mobile behaviour
Tabs often break on small screens — use judgement, not component loyalty.
- enough touch target size; labels that do not wrap into confusion
- horizontal scrolling acceptable when overflow is obvious and focus stays correct
- consider accordions or stacked sections when many tabs fight for space
06 — Enhancement
Deep linking, loading, and progressive enhancement
Tabs are still navigation — bookmarks and fallbacks matter.
- support deep links for settings, docs, and dashboards where users share URLs
- lazy-load panels carefully — avoid blank panels and repeated layout shift
- critical content reachable without JavaScript; stacked fallback is often fine
- do not bury important SEO content in inaccessible JS-only tab systems
Keep tab systems lightweight. Respect reduced motion — transitions should orient, not perform.
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}07 — Anti-patterns
What to avoid
Familiar tab mistakes that still ship in production.
- huge hidden sections users forget exist
- hover-only tabs — touch and keyboard users exist
- tabs used as primary site navigation
- carousel-style animated tab transitions nobody asked for
08 — Review
Before you approve
A short checklist for tabs in code review.
- tabs are genuinely the right pattern for related, switchable content
- keyboard support and visible focus are complete
- active state is obvious; labels are clear
- mobile behaviour remains usable
- content stays discoverable; progressive enhancement works
- a simpler layout would not serve users better
When in doubt, ask: Do these tabs reduce complexity, or merely hide it? If the answer is “hide it”, the pattern is not helping.