Two CSS rules with equal specificity can produce different results depending on source order when multiple states apply, such as :hover and [disabled]. This reveals a larger issue: component state styling often relies on overlapping selectors, which becomes hard to manage as more states and conditions are added, including active, dark mode, breakpoints, data attributes, container queries, and overrides. Maintaining the correct resolution order becomes a mental “resolution system.” Extending components later becomes difficult because the state-resolution problem must be reopened and re-solved. A better approach is to express component state declaratively as a priority-ordered map, letting a compiler generate deterministic selectors that cannot overlap.
"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."
"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."
"What if component state could be expressed declaratively, while the compiler handled the selector logic needed to make it deterministic? That question eventually became Tasty. Instead of writing selectors that compete through cascade and specificity, I wanted to describe a property's possible states as a map: Applied in order of priority, this means: when disabled use #surface; otherwise, on active use #primary-pressed; otherwise, on hover use #primary-hover; otherwise use #primary."
#css-specificity #component-state-styling #cascade-and-source-order #design-systems #declarative-ui-styling
Read at tenphi.me
Unable to calculate read time
Collection
[
|
...
]