32 CSS Tab Designs04 / 32
Chromatic
Four color-coded tabs each with a dedicated tint, border, and active-state glow. Violet, rose, cyan, lime — each tab keeps its identity whether active or inactive. Pure CSS.
Published
The code
<div class="tt24">
<nav class="tt24n">
<input type="radio" name="tt24" id="tt24-r1" checked />
<label class="tt24b tt24-v" for="tt24-r1">Violet</label>
<input type="radio" name="tt24" id="tt24-r2" />
<label class="tt24b tt24-r" for="tt24-r2">Rose</label>
<input type="radio" name="tt24" id="tt24-r3" />
<label class="tt24b tt24-c" for="tt24-r3">Cyan</label>
<input type="radio" name="tt24" id="tt24-r4" />
<label class="tt24b tt24-l" for="tt24-r4">Lime</label>
</nav>
<div class="tt24p">Violet — deep, contemplative.</div>
<div class="tt24p">Rose — warm, inviting.</div>
<div class="tt24p">Cyan — crisp, technical.</div>
<div class="tt24p">Lime — fresh, urgent.</div>
</div><div class="tt24">
<nav class="tt24n">
<input type="radio" name="tt24" id="tt24-r1" checked />
<label class="tt24b tt24-v" for="tt24-r1">Violet</label>
<input type="radio" name="tt24" id="tt24-r2" />
<label class="tt24b tt24-r" for="tt24-r2">Rose</label>
<input type="radio" name="tt24" id="tt24-r3" />
<label class="tt24b tt24-c" for="tt24-r3">Cyan</label>
<input type="radio" name="tt24" id="tt24-r4" />
<label class="tt24b tt24-l" for="tt24-r4">Lime</label>
</nav>
<div class="tt24p">Violet — deep, contemplative.</div>
<div class="tt24p">Rose — warm, inviting.</div>
<div class="tt24p">Cyan — crisp, technical.</div>
<div class="tt24p">Lime — fresh, urgent.</div>
</div>.tt24 {
background: #0f0f17;
padding: 24px 20px;
font-family: ui-sans-serif, system-ui, sans-serif;
min-height: 100vh;
box-sizing: border-box;
width: 100%;
}
.tt24n {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-width: 0;
}
.tt24n input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.tt24b {
flex: 1;
min-width: 0;
padding: 11px 14px;
border-radius: 8px;
font: 700 12px/1 ui-sans-serif, system-ui;
letter-spacing: 0.06em;
cursor: pointer;
text-align: center;
transition: background 0.25s, border-color 0.25s, box-shadow 0.3s;
white-space: nowrap;
border: 1px solid;
}
.tt24-v {
color: #c4b5fd;
border-color: rgba(196, 181, 253, 0.3);
background: rgba(196, 181, 253, 0.06);
}
.tt24-r {
color: #fda4af;
border-color: rgba(253, 164, 175, 0.3);
background: rgba(253, 164, 175, 0.06);
}
.tt24-c {
color: #67e8f9;
border-color: rgba(103, 232, 249, 0.3);
background: rgba(103, 232, 249, 0.06);
}
.tt24-l {
color: #bef264;
border-color: rgba(190, 242, 100, 0.3);
background: rgba(190, 242, 100, 0.06);
}
.tt24n input:checked + .tt24-v {
background: rgba(196, 181, 253, 0.18);
border-color: #c4b5fd;
box-shadow: 0 0 18px rgba(196, 181, 253, 0.35);
}
.tt24n input:checked + .tt24-r {
background: rgba(253, 164, 175, 0.18);
border-color: #fda4af;
box-shadow: 0 0 18px rgba(253, 164, 175, 0.35);
}
.tt24n input:checked + .tt24-c {
background: rgba(103, 232, 249, 0.18);
border-color: #67e8f9;
box-shadow: 0 0 18px rgba(103, 232, 249, 0.35);
}
.tt24n input:checked + .tt24-l {
background: rgba(190, 242, 100, 0.18);
border-color: #bef264;
box-shadow: 0 0 18px rgba(190, 242, 100, 0.35);
}
.tt24n input:focus-visible + .tt24b {
outline: 2px dashed currentColor;
outline-offset: 3px;
}
.tt24p {
display: none;
padding-top: 20px;
font: 13px/1.55 ui-sans-serif, system-ui;
color: rgba(255, 255, 255, 0.7);
}
.tt24:has(#tt24-r1:checked) .tt24p:nth-of-type(1),
.tt24:has(#tt24-r2:checked) .tt24p:nth-of-type(2),
.tt24:has(#tt24-r3:checked) .tt24p:nth-of-type(3),
.tt24:has(#tt24-r4:checked) .tt24p:nth-of-type(4) {
display: block;
}.tt24 {
background: #0f0f17;
padding: 24px 20px;
font-family: ui-sans-serif, system-ui, sans-serif;
min-height: 100vh;
box-sizing: border-box;
width: 100%;
}
.tt24n {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-width: 0;
}
.tt24n input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.tt24b {
flex: 1;
min-width: 0;
padding: 11px 14px;
border-radius: 8px;
font: 700 12px/1 ui-sans-serif, system-ui;
letter-spacing: 0.06em;
cursor: pointer;
text-align: center;
transition: background 0.25s, border-color 0.25s, box-shadow 0.3s;
white-space: nowrap;
border: 1px solid;
}
.tt24-v {
color: #c4b5fd;
border-color: rgba(196, 181, 253, 0.3);
background: rgba(196, 181, 253, 0.06);
}
.tt24-r {
color: #fda4af;
border-color: rgba(253, 164, 175, 0.3);
background: rgba(253, 164, 175, 0.06);
}
.tt24-c {
color: #67e8f9;
border-color: rgba(103, 232, 249, 0.3);
background: rgba(103, 232, 249, 0.06);
}
.tt24-l {
color: #bef264;
border-color: rgba(190, 242, 100, 0.3);
background: rgba(190, 242, 100, 0.06);
}
.tt24n input:checked + .tt24-v {
background: rgba(196, 181, 253, 0.18);
border-color: #c4b5fd;
box-shadow: 0 0 18px rgba(196, 181, 253, 0.35);
}
.tt24n input:checked + .tt24-r {
background: rgba(253, 164, 175, 0.18);
border-color: #fda4af;
box-shadow: 0 0 18px rgba(253, 164, 175, 0.35);
}
.tt24n input:checked + .tt24-c {
background: rgba(103, 232, 249, 0.18);
border-color: #67e8f9;
box-shadow: 0 0 18px rgba(103, 232, 249, 0.35);
}
.tt24n input:checked + .tt24-l {
background: rgba(190, 242, 100, 0.18);
border-color: #bef264;
box-shadow: 0 0 18px rgba(190, 242, 100, 0.35);
}
.tt24n input:focus-visible + .tt24b {
outline: 2px dashed currentColor;
outline-offset: 3px;
}
.tt24p {
display: none;
padding-top: 20px;
font: 13px/1.55 ui-sans-serif, system-ui;
color: rgba(255, 255, 255, 0.7);
}
.tt24:has(#tt24-r1:checked) .tt24p:nth-of-type(1),
.tt24:has(#tt24-r2:checked) .tt24p:nth-of-type(2),
.tt24:has(#tt24-r3:checked) .tt24p:nth-of-type(3),
.tt24:has(#tt24-r4:checked) .tt24p:nth-of-type(4) {
display: block;
}Here's a working CSS Tab Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Chromatic
Source: https://codefronts.com/navigation/css-tabs/chromatic/
Four color-coded tabs each with a dedicated tint, border, and active-state glow. Violet, rose, cyan, lime — each tab keeps its identity whether active or inactive. Pure CSS.
## HTML
```html
<div class="tt24">
<nav class="tt24n">
<input type="radio" name="tt24" id="tt24-r1" checked />
<label class="tt24b tt24-v" for="tt24-r1">Violet</label>
<input type="radio" name="tt24" id="tt24-r2" />
<label class="tt24b tt24-r" for="tt24-r2">Rose</label>
<input type="radio" name="tt24" id="tt24-r3" />
<label class="tt24b tt24-c" for="tt24-r3">Cyan</label>
<input type="radio" name="tt24" id="tt24-r4" />
<label class="tt24b tt24-l" for="tt24-r4">Lime</label>
</nav>
<div class="tt24p">Violet — deep, contemplative.</div>
<div class="tt24p">Rose — warm, inviting.</div>
<div class="tt24p">Cyan — crisp, technical.</div>
<div class="tt24p">Lime — fresh, urgent.</div>
</div>
```
## CSS
```css
.tt24 {
background: #0f0f17;
padding: 24px 20px;
font-family: ui-sans-serif, system-ui, sans-serif;
min-height: 100vh;
box-sizing: border-box;
width: 100%;
}
.tt24n {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-width: 0;
}
.tt24n input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.tt24b {
flex: 1;
min-width: 0;
padding: 11px 14px;
border-radius: 8px;
font: 700 12px/1 ui-sans-serif, system-ui;
letter-spacing: 0.06em;
cursor: pointer;
text-align: center;
transition: background 0.25s, border-color 0.25s, box-shadow 0.3s;
white-space: nowrap;
border: 1px solid;
}
.tt24-v {
color: #c4b5fd;
border-color: rgba(196, 181, 253, 0.3);
background: rgba(196, 181, 253, 0.06);
}
.tt24-r {
color: #fda4af;
border-color: rgba(253, 164, 175, 0.3);
background: rgba(253, 164, 175, 0.06);
}
.tt24-c {
color: #67e8f9;
border-color: rgba(103, 232, 249, 0.3);
background: rgba(103, 232, 249, 0.06);
}
.tt24-l {
color: #bef264;
border-color: rgba(190, 242, 100, 0.3);
background: rgba(190, 242, 100, 0.06);
}
.tt24n input:checked + .tt24-v {
background: rgba(196, 181, 253, 0.18);
border-color: #c4b5fd;
box-shadow: 0 0 18px rgba(196, 181, 253, 0.35);
}
.tt24n input:checked + .tt24-r {
background: rgba(253, 164, 175, 0.18);
border-color: #fda4af;
box-shadow: 0 0 18px rgba(253, 164, 175, 0.35);
}
.tt24n input:checked + .tt24-c {
background: rgba(103, 232, 249, 0.18);
border-color: #67e8f9;
box-shadow: 0 0 18px rgba(103, 232, 249, 0.35);
}
.tt24n input:checked + .tt24-l {
background: rgba(190, 242, 100, 0.18);
border-color: #bef264;
box-shadow: 0 0 18px rgba(190, 242, 100, 0.35);
}
.tt24n input:focus-visible + .tt24b {
outline: 2px dashed currentColor;
outline-offset: 3px;
}
.tt24p {
display: none;
padding-top: 20px;
font: 13px/1.55 ui-sans-serif, system-ui;
color: rgba(255, 255, 255, 0.7);
}
.tt24:has(#tt24-r1:checked) .tt24p:nth-of-type(1),
.tt24:has(#tt24-r2:checked) .tt24p:nth-of-type(2),
.tt24:has(#tt24-r3:checked) .tt24p:nth-of-type(3),
.tt24:has(#tt24-r4:checked) .tt24p:nth-of-type(4) {
display: block;
}
```Here's a working CSS Tab Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Chromatic
Source: https://codefronts.com/navigation/css-tabs/chromatic/
Four color-coded tabs each with a dedicated tint, border, and active-state glow. Violet, rose, cyan, lime — each tab keeps its identity whether active or inactive. Pure CSS.
## HTML
```html
<div class="tt24">
<nav class="tt24n">
<input type="radio" name="tt24" id="tt24-r1" checked />
<label class="tt24b tt24-v" for="tt24-r1">Violet</label>
<input type="radio" name="tt24" id="tt24-r2" />
<label class="tt24b tt24-r" for="tt24-r2">Rose</label>
<input type="radio" name="tt24" id="tt24-r3" />
<label class="tt24b tt24-c" for="tt24-r3">Cyan</label>
<input type="radio" name="tt24" id="tt24-r4" />
<label class="tt24b tt24-l" for="tt24-r4">Lime</label>
</nav>
<div class="tt24p">Violet — deep, contemplative.</div>
<div class="tt24p">Rose — warm, inviting.</div>
<div class="tt24p">Cyan — crisp, technical.</div>
<div class="tt24p">Lime — fresh, urgent.</div>
</div>
```
## CSS
```css
.tt24 {
background: #0f0f17;
padding: 24px 20px;
font-family: ui-sans-serif, system-ui, sans-serif;
min-height: 100vh;
box-sizing: border-box;
width: 100%;
}
.tt24n {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-width: 0;
}
.tt24n input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.tt24b {
flex: 1;
min-width: 0;
padding: 11px 14px;
border-radius: 8px;
font: 700 12px/1 ui-sans-serif, system-ui;
letter-spacing: 0.06em;
cursor: pointer;
text-align: center;
transition: background 0.25s, border-color 0.25s, box-shadow 0.3s;
white-space: nowrap;
border: 1px solid;
}
.tt24-v {
color: #c4b5fd;
border-color: rgba(196, 181, 253, 0.3);
background: rgba(196, 181, 253, 0.06);
}
.tt24-r {
color: #fda4af;
border-color: rgba(253, 164, 175, 0.3);
background: rgba(253, 164, 175, 0.06);
}
.tt24-c {
color: #67e8f9;
border-color: rgba(103, 232, 249, 0.3);
background: rgba(103, 232, 249, 0.06);
}
.tt24-l {
color: #bef264;
border-color: rgba(190, 242, 100, 0.3);
background: rgba(190, 242, 100, 0.06);
}
.tt24n input:checked + .tt24-v {
background: rgba(196, 181, 253, 0.18);
border-color: #c4b5fd;
box-shadow: 0 0 18px rgba(196, 181, 253, 0.35);
}
.tt24n input:checked + .tt24-r {
background: rgba(253, 164, 175, 0.18);
border-color: #fda4af;
box-shadow: 0 0 18px rgba(253, 164, 175, 0.35);
}
.tt24n input:checked + .tt24-c {
background: rgba(103, 232, 249, 0.18);
border-color: #67e8f9;
box-shadow: 0 0 18px rgba(103, 232, 249, 0.35);
}
.tt24n input:checked + .tt24-l {
background: rgba(190, 242, 100, 0.18);
border-color: #bef264;
box-shadow: 0 0 18px rgba(190, 242, 100, 0.35);
}
.tt24n input:focus-visible + .tt24b {
outline: 2px dashed currentColor;
outline-offset: 3px;
}
.tt24p {
display: none;
padding-top: 20px;
font: 13px/1.55 ui-sans-serif, system-ui;
color: rgba(255, 255, 255, 0.7);
}
.tt24:has(#tt24-r1:checked) .tt24p:nth-of-type(1),
.tt24:has(#tt24-r2:checked) .tt24p:nth-of-type(2),
.tt24:has(#tt24-r3:checked) .tt24p:nth-of-type(3),
.tt24:has(#tt24-r4:checked) .tt24p:nth-of-type(4) {
display: block;
}
```How this works
The .tt24 shell paints a near-black #0f0f17 register and lays out .tt24n as a flex row with gap: 8px and flex-wrap: wrap. Each label carries a modifier class — .tt24-v, .tt24-r, .tt24-c, .tt24-l — that owns its own resting color, border, and background tint. Violet #c4b5fd ink sits on a rgba(196, 181, 253, 0.06) ground with a 0.3 alpha border; rose #fda4af, cyan #67e8f9, and lime #bef264 follow the same recipe. Checked state pushes tint alpha to 0.18, solidifies the border, and adds an 0 0 18px outer glow at 0.35 alpha — a chromatic aberration read that lives close to a print-broadcast palette.
The palette rationale is identity-preserving: unlike a slider that borrows the accent from the active tab, each tab keeps its own hue whether active or inactive. That works because the resting alpha is low enough (0.06 tint, 0.3 border) that the four labels read as a coherent chromatic strip, and the checked state simply cranks intensity. Typography is a copy-paste ui-sans-serif, system-ui stack at 700 12px/1 with letter-spacing: 0.06em, which sits between marketing and product chrome.
Because each state is :checked + .tt24-*, the pattern is pure CSS — no JS, no measurement, no hydration cost. Focus uses outline: 2px dashed currentColor so the ring inherits the tab's own color for WCAG 2.4.7 and reads as a keyboard-only affordance. The box-shadow 0.3s transition is subtle but still motion, so a @media (prefers-reduced-motion: reduce) override is required for WCAG 2.3.3. Panels swap through :has() selectors, so INP stays a single paint and CLS is zero. For the ARIA tabs pattern, add role="tablist", role="tab", aria-selected, and roving arrow-key handling.
Make it yours
- Recolor the quartet by editing the four modifier blocks. Any chromatic set works — swap violet for a brand blue #60a5fa or lime for a warmer amber #fbbf24. Keep the resting alpha at 0.06 and checked at 0.18 so the intensity story stays consistent.
- Typography swap: change the font shorthand on .tt24b to 600 13px/1 Inter, ui-sans-serif for a softer product register, or drop to 700 11px/1 uppercase with letter-spacing: 0.12em for broadcast chrome.
- Shape: bump .tt24b border-radius from 8px to 999px for full pills, or drop to 0 for a hard chromatic-strip register. The glow scales cleanly at any radius.
- Light-mode variant: flip .tt24 background to #f8fafc, deepen each color's resting ink (violet becomes #6d28d9, cyan #0e7490), and drop the checked box-shadow alpha from 0.35 to 0.2 so the glow reads on paper.
- Tailwind arbitrary values: base text and border tokens via arbitrary rgba; checked variant with peer-checked box-shadow tokens per hue.
Gotchas — read before shipping
- Resting violet #c4b5fd on #0f0f17 passes WCAG 1.4.3; rose and lime are close but pass at 12px 700; cyan #67e8f9 is the strongest. Run each color through a checker if you localise sizes or weights — 11px 400 will fail for lime.
- outline: dashed currentColor inherits the label's own tone, which reads well but can vanish against certain wallpaper composites when devtools re-parent nodes. Test with a system high-contrast theme and fall back to a solid 2px solid var(--accent) if the dashed edge disappears.
- Radio inputs form a native radiogroup. Add the ARIA tabs pattern for WCAG 4.1.2 — role="tablist", role="tab", aria-selected, role="tabpanel", and Left/Right arrow-key navigation with roving tabindex — otherwise the pattern reads as a form control instead of tabs.
- The 18px checked glow is motion when animated over 0.3s. Add @media (prefers-reduced-motion: reduce) so users who opt out per WCAG 2.3.3 get instant chromatic swaps.
- Vue Suspense hydrates the panel region after the shell, so :has(#tt24-r1:checked) can resolve on client before the panel exists in the DOM, leaving a beat of no visible content. Render all four panels at SSR and let CSS display: none hide the inactive ones.
- The rgba() alpha values assume sRGB. On P3 displays, Safari 15.4 upshifts the tint slightly and the checked glow can bloom past the intended intensity. If P3 fidelity matters, switch to color(display-p3 ...) tokens and verify each hue on hardware.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 105+ | 15.4+ | 121+ | 105+ |
Uses :has() for panel switching, which needs Firefox 121; the tab visuals themselves work back to Chrome 90 and Safari 15.