Skip to content
Tech News
← Back to articles

I spent years trying to make CSS states predictable

read original get CSS State Management Book → more articles
Why This Matters

This article highlights the complexities and unpredictability of managing component states in CSS, especially as designs grow more intricate with multiple overlapping states. It introduces a declarative approach through the Tasty system, which aims to simplify state management by allowing developers to specify states explicitly, letting the compiler handle the resolution. This innovation promises to improve maintainability and predictability in web component design, benefiting both developers and end-users.

Key Takeaways

Apr 23, 2026 · 8 min read

css webdev frontend designsystem

Have you ever changed the order of two CSS rules and broken a component without changing the logic?

.btn:hover { background : dodgerblue; } .btn [ disabled ] { background : gray; }

Both selectors have specificity (0, 1, 1) . When a button is both hovered and disabled, the browser falls back to source order. If the :hover rule comes last, the disabled button turns blue. If the [disabled] rule comes last, it stays gray.

That sounds small, but it points to a bigger problem: component state in CSS often works by overlap.

As long as a component has only one or two states, that overlap feels manageable. Once you add :hover , :active , disabled , dark mode, breakpoints, data attributes, container queries, and overrides, it stops feeling manageable very quickly. You are no longer just writing styles. You are maintaining a resolution system in your head.

And that showed up not only as accidental conflicts, but as a growing difficulty in customizing existing components safely as real requirements piled up.

That was the problem I kept running into while building component systems. Not on toy examples, but on real buttons, inputs, panels, dropdowns, and design-system primitives. The hardest part was not writing the first version of a component. It was extending it later without reopening the entire state-resolution problem.

At some point I stopped asking, “How do I write this selector?” and started asking a better question:

... continue reading