Most tab components you find out there ship kilobytes of JavaScript for something the browser already knows how to do: manage a selected state across several options. That is, quite literally, a group of radio buttons.
The idea
Each tab is a <label> tied to a hidden <input type="radio">. When the radio is checked, CSS reacts and reveals the matching panel. Zero JS, and as a bonus you get arrow-key navigation for free, since radio groups bring that out of the box.
<label for="tab1">Tab 1</label>
<input id="tab1" name="tabs" type="radio" class="sr-only peer" checked />
The trick: :has()
The panel restyles based on whether its sibling input is checked:
label:has(+ input:checked) {
color: white;
background: var(--primary);
}
:has(+ input:checked) reads as “this label that has, right after it, a checked input”. It’s CSS looking forward.
Real accessibility
Since the input stays focusable (sr-only, not display:none), the keyboard works. Just remember to add a visible focus ring:
label:has(+ input:focus-visible) {
outline: 2px solid var(--primary);
}
Takeaway
Before reaching for a library, ask whether the browser already solves the problem. Here, one <input> and a modern selector save you the entire runtime.