Blog / Web Dev

Beyond the Checkbox Hack: Building Multi-State Components Without JavaScript Bloat

CSS state machines let you manage complex UI modes with radio inputs. Here's why I'm skeptical it solves everything—and when it actually works.

Juan David Avellaneda April 15, 2026 4 min read 19 views
Beyond the Checkbox Hack: Building Multi-State Components Without JavaScript Bloat

The Checkbox Hack Got Us Here

For years, we've used hidden checkboxes to toggle single states in CSS. Click it, the UI changes. It's clever. It works offline. But the moment you need a component to live in three, four, or seven different modes—a carousel state, a modal overlay, a multi-step form progression—the checkbox approach collapses. You'd need multiple checkboxes, conflicting styles, and eventually you're just writing JavaScript anyway because the CSS becomes unmaintainable.

That's where radio buttons come in, and I'm not entirely convinced this is the revelation everyone thinks it is, but—and this matters—it does solve a real problem I encounter building custom products for clients in Bogotá who specifically request "no build step" solutions.

How Radio State Machines Actually Work

A radio input group enforces a single selection. Only one button in the group can be checked at once. The browser handles this for you. That constraint, that enforcement, is the whole trick. You tie CSS selectors to which radio is active and boom—you get true state management without JavaScript.

  • One checked radio at a time
  • CSS sibling selectors target different styling based on :checked state
  • No conflicts. No race conditions. The DOM enforces the rules.
  • You can have carousel steps, modal variants, accordion panels—basically anything that needs to "be in one state or another"
  • Mobile performance stays clean

I tested this on a client project last March. A real estate platform needed a property filter component that could swap between map view, list view, and grid view. Three states. I built it with radio buttons and CSS Grid transitions. The experience was smooth. But—and here's where I lose confidence—I'm not sure we avoided complexity, we just moved it. The CSS file grew. Debugging state became harder for the next developer because the state isn't explicit in JavaScript.

When This Works. When It Doesn't.

Radio state machines shine when states are visual-only and don't require server communication. A tab component? Perfect. A collapsible section? Great. But if your state machine needs to sync with a database, trigger side effects, or coordinate with third-party APIs, you're lying to yourself if you think CSS alone is the answer.

I've watched teams spend three weeks trying to avoid JavaScript, only to bolt it on anyway when they hit reality. The radio approach is genuinely useful—don't get me wrong—but it's a CSS pattern, not a state management system.

Performance-wise, Shopify reported in 2021 that reducing JavaScript by 10KB could improve conversion rates by measurable percentages, so the appeal is real and data-backed. But shipping 3KB of hidden radio inputs instead of 1KB of vanilla JS isn't always the win it appears to be.

Where I'd Actually Use This

Design systems. Component libraries. Anything where you're building a reusable element that shouldn't carry heavy dependencies.

A pricing table that toggles between annual and monthly billing? Radio state machine, no question. An image gallery where only one photo displays at a time? Lock it in. A wizard form progressing through steps—here's my doubt again—because you'll probably need validation logic anyway, and then you're mixing concerns.

The honest answer is: use radios when your state is purely presentational and doesn't depend on external systems.

The Unresolved Part

What I keep thinking about is accessibility. Screen readers announce radio buttons. Users can navigate them with arrow keys. The semantics are clean. But when you're using radios as a hidden state machine, not as actual form inputs, does that create false expectations for assistive technology users? I'm not entirely sure the pattern is as accessible as we pretend it is, even though technically it uses proper form elements.

The pattern works. The pattern is clever. But I'm still not convinced it's the future of state management, and I'm definitely not convinced every use case needs CSS-only solutions when a few lines of JavaScript would be clearer.

#CSS #state-management #web-performance #UI-patterns #accessibility

Was this helpful?

Juan David Avellaneda

Juan David Avellaneda

Innovation Specialist · Bogotá, Colombia