Skip to content
Carl Victor Fontanos
Carl Victor Fontanos

Carl Victor Fontanos

Software Engineer

I build web applications and share what I learn along the way.

© 2026

Theme Every Checkbox and Radio with One CSS Line

C
Carlo Fontanos
· 2 min read

An entire generation of frontend developers learned the checkbox hack: visually hide the real input, draw a fake box with a pseudo-element, hand-craft a checkmark, then spend an afternoon on the focus states you broke. All of that, for brand colors on a checkbox.

Here is the current solution, complete:

:root {
    accent-color: #7c3aed;
}

Checkboxes, radio buttons, range sliders and progress bars all adopt the color. The browser keeps everything else it does well: keyboard behavior, focus rings, hit targets, high-contrast mode, the works. You restyled the paint, not the machinery.

It cascades like any property

.danger-zone { accent-color: crimson; }     /* destructive settings section */
.newsletter  { accent-color: seagreen; }    /* different context, different accent */

Because it inherits, one declaration on :root themes the whole app, and local overrides are just more specific rules. Try doing that with the pseudo-element hack.

Contrast is handled for you

The subtle detail that sold me: the browser picks the checkmark color (white or black) based on the contrast against your accent. Set a pale yellow accent and the tick renders dark automatically. That's an accessibility calculation you no longer own.

Dark mode plays along

:root {
    accent-color: var(--brand);   /* custom properties work, naturally */
    color-scheme: light dark;     /* tells the browser both modes are supported */
}

Pair accent-color with the color-scheme property and native controls (including scrollbars and date pickers) render dark-appropriate chrome in dark mode, with your accent on top. Two lines, and forms stop looking pasted-in from a light website.

Where the limits are

accent-color themes the accent, not the geometry. If the design demands a custom size, border radius or animation on the control itself, you're back to real custom styling - but do it the modern way: appearance: none on the input and style the element directly, keeping it focusable and real. The hidden-input hack should stay dead either way.

Support: every browser since early 2022. This is my favorite kind of platform feature - it deletes a folder of CSS, an accessibility risk, and a category of code review comments simultaneously. If you enjoy that feeling, the dialog element does the same thing to modal libraries.

C
Written by Carlo Fontanos

Full-stack web developer sharing practical tutorials and building tools that ship.

Got something on your mind?

My inbox is open - no forms disappearing into the void here.

  • Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
  • Hire me for a project Have something custom in mind? Let's talk scope and timelines.
  • Product support Bought something here? I'll help you get it running.

I usually reply within 1-2 business days.

Message sent!

Your details are only used to reply to you.

Keep reading