Tabs
Category: Navigation · Tags: tabs, tablist, navigation, panels
Billed every month. Cancel anytime from account settings.
Billed once a year. Includes two months free compared to monthly billing.
How to use it
Use to let a user switch between a small, fixed set of related views without leaving the page, such as pricing periods or settings sections. Keep the number of tabs small enough to show without scrolling and give each a short, distinct label.
Accessibility
Follows the WAI-ARIA tabs pattern: role="tablist" on the container, role="tab" on each native <button>, aria-selected tracks the active tab, aria-controls links each tab to its role="tabpanel", and only the active tab is in the Tab key order (tabindex 0 vs -1) while ArrowLeft/ArrowRight move between tabs.
Source (copy-ready)
<div class="dcl-tabs">
<div role="tablist" aria-label="Billing options" class="dcl-tabs__list">
<button type="button" role="tab" id="dcl-tab-monthly" aria-controls="dcl-panel-monthly" aria-selected="true" class="dcl-tabs__tab">Monthly</button>
<button type="button" role="tab" id="dcl-tab-annual" aria-controls="dcl-panel-annual" aria-selected="false" tabindex="-1" class="dcl-tabs__tab">Annual</button>
</div>
<div role="tabpanel" id="dcl-panel-monthly" aria-labelledby="dcl-tab-monthly" class="dcl-tabs__panel">Billed every month. Cancel anytime from account settings.</div>
<div role="tabpanel" id="dcl-panel-annual" aria-labelledby="dcl-tab-annual" class="dcl-tabs__panel" hidden>Billed once a year. Includes two months free compared to monthly billing.</div>
</div>
<style>
.dcl-tabs { font: inherit; max-width: 24rem; }
.dcl-tabs__list { display: flex; gap: 0.25rem; border-bottom: 2px solid #e2e8f0; }
.dcl-tabs__tab { padding: 0.5rem 1rem; border: none; background-color: #ffffff; color: #334155; cursor: pointer; border-bottom: 2px solid transparent; font: inherit; }
.dcl-tabs__tab[aria-selected="true"] { color: #1d4ed8; border-bottom-color: #1d4ed8; font-weight: 600; }
.dcl-tabs__tab:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }
.dcl-tabs__panel { padding: 0.75rem 0.25rem; color: #0f172a; background-color: #ffffff; }
</style>
<script>
(function () {
var tabs = document.querySelectorAll(".dcl-tabs [role=\"tab\"]");
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
tabs.forEach(function (other) {
var panel = document.getElementById(other.getAttribute("aria-controls"));
var selected = other === tab;
other.setAttribute("aria-selected", selected ? "true" : "false");
other.tabIndex = selected ? 0 : -1;
if (panel) { panel.hidden = !selected; }
});
tab.focus();
});
tab.addEventListener("keydown", function (event) {
var list = Array.prototype.slice.call(tabs);
var index = list.indexOf(tab);
if (event.key === "ArrowRight") { list[(index + 1) % list.length].click(); }
if (event.key === "ArrowLeft") { list[(index - 1 + list.length) % list.length].click(); }
});
});
})();
</script>
Was this useful? Send feedback.