For years, "the cascade" was the part of CSS we apologized for. It was the thing that made styles leak, specificity wars erupt, and a single stray !important ripple across a codebase like a dropped pebble in a very small pond. Whole methodologies existed mostly to avoid the cascade rather than use it. And then, quietly, the platform grew up. The cascade didn't get weaker — it got controllable.
The single biggest source of CSS pain was never the cascade itself. It was fighting for priority: bumping specificity, nesting selectors deeper, reaching for !important as a last resort that quickly became a first one. Cascade layers dissolve that entire genre of problem by letting you declare order of precedence explicitly, up front.
@layer reset, base, components, utilities;
@layer components {
.card { padding: 1.5rem; border-radius: 12px; }
}
@layer utilities {
.p-0 { padding: 0; }
}Now a utility beats a component not because it's more specific, but because you said it should. Specificity stops being a weapon and becomes an afterthought. That alone would justify the feature; that it shipped alongside two more heavyweights is almost unfair.
The "parent selector" was the most-requested feature in the language's history, and for good reason. :has() lets an element style itself based on what it contains or what follows it — logic that used to require a class toggled by JavaScript on every state change.
.card:has(img) { grid-template-columns: auto 1fr; }
.form-field:has(:invalid) { border-color: crimson; }An entire category of "add a class with JS so CSS can react" glue code simply evaporates. The styling stays in the stylesheet, where it belongs, and stays in sync automatically because it's reading the DOM directly.
For a decade we asked the viewport how wide it was, then hoped that told us something useful about a component that might live in a sidebar, a modal, or a full-bleed hero. It didn't, really. Container queries let a component ask the only question that matters: how much room do I have?
.sidebar { container-type: inline-size; }
@container (min-width: 24rem) {
.widget { display: grid; grid-template-columns: 1fr 1fr; }
}A component becomes genuinely portable. Drop it anywhere and it adapts to its actual context, not to a global guess about the window.
Add these up and a familiar layer of the front-end stack becomes optional:
@layer reset baselines.!important arms race.The cascade was never the villain. We just didn't have the words to speak to it clearly. Now we do.
The quiet power here is subtractive. The newest CSS isn't impressive because of what it adds to your bundle — it's impressive because of how much it lets you take out. Fewer hacks, less glue, less to explain to the next person. That's the kind of progress that doesn't trend, and it's exactly the kind worth building on.