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, and tabpanel roles 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.