Tab Navigation
Tabbed interface using radio inputs and the :checked pseudo-class.
Published May 19, 2026
Demo
HTML
<div class="tabs">
<input type="radio" name="tabs" id="t1" checked>
<input type="radio" name="tabs" id="t2">
<div class="tab-labels">
<label for="t1">Tab One</label>
<label for="t2">Tab Two</label>
</div>
<div class="tab-panels">
<div class="tab-panel" id="p1">Content 1</div>
<div class="tab-panel" id="p2">Content 2</div>
</div>
</div>
CSS
input[type="radio"] { display: none; }
.tab-labels {
display: flex;
border-bottom: 2px solid #e2e2e8;
}
label {
padding: .6rem 1.1rem;
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -2px;
}
.tab-panel { display: none; }
#t1:checked ~ .tab-labels label[for="t1"],
#t2:checked ~ .tab-labels label[for="t2"] {
color: #5b4cdb;
border-bottom-color: #5b4cdb;
}
#t1:checked ~ .tab-panels #p1,
#t2:checked ~ .tab-panels #p2 {
display: block;
}
How it works
Hidden radio inputs store which tab is active. Because only one radio per group can be checked at a time, CSS can target the correct panel and <label> using the sibling combinator. Each <input>, <label>, and panel need matching id/for attributes and sibling relationships in the DOM.