Demo 02

Nested Tabs

Tabs within tabs. The outer bar switches between sections; inside each section, a second layer of pill tabs switches between detail cards. No frameworks — just data attributes and a few lines of JavaScript.

Two layers, one pattern

Both tab layers use the same markup recipe: a bar of buttons, a stack of panels, and data-* hooks that pair them up. The inner layer is completely independent of the outer one.

Semantic shells. Each layer is a tablist of tab buttons above a stack of tabpanel divs, so screen readers can announce the switches without extra code.
Click delegation. A single listener per layer reads the button's data-tab value, clears the layer's active states, and lights up the matching panel.
No stored state. Tabs reset on reload by design — this demo is about the interaction, not persistence. The active class lives only in the DOM.

Quiet, quick, readable

Panels fade up 10px over 350 milliseconds — fast enough to feel responsive, slow enough to be noticed.

fadeUp keyframe. Incoming panels animate opacity 0 to 1 and translateY 10px to 0, so content feels like it settles into place rather than snapping.
Sliding accent. The active tab gets a 3px bottom border in the accent blue — a low-tech "slider" that reads instantly and costs nothing to render.
Respecting preferences. Users with reduced-motion settings get instant panel swaps; the animation is decorative, never essential.

Nesting with restraint

Two layers is the sweet spot. Any deeper and users lose track of where they are — at that point, split the content into pages.

Settings, docs, comparisons. Nested tabs shine when a section has 2-4 sub-topics that share context, like spec sheets grouped by product line.
Long-form reading. Anything users scroll through shouldn't hide behind a click — hidden panels are invisible to find-as-you-type and printing.
Small screens. The outer bar scrolls horizontally when labels overflow; inner pills wrap. Both stay finger-sized with generous tap targets.

← Back to the playground