CSS in 2026: What Actually Changed and What Still Bites You

CSS in 2026 is mostly native: container queries, :has(), nesting, cascade layers, and oklch color all ship in every browser your customers use. The real gap is habit, not support. What still bites is subgrid, anchor positioning, and older Safari quirks.
Part of the complete web design guide.
On this page
- Container queries are the biggest shift
- :has() finally killed a whole category of JavaScript
- Native nesting is fine now, with one caveat
- What I’d stop doing in 2026
- Color, units, and math got genuinely nicer
- Does any of this matter for a small business site?
- Browser support in 2026
- FAQ
- Do I still need Sass or Less?
- Is it safe to use :has() on a site with older visitors?
- How much does modernizing a stylesheet actually save?
CSS has changed more in the last four years than in the previous fifteen. The stuff I used to reach for a preprocessor or a JavaScript library to do is now native, and it works in every browser your customers actually use. Here’s what I’d tell a developer or business owner who hasn’t touched stylesheets since flexbox was the hot new thing.
I’ve been building sites for clients around Commack and across Long Island for a long time, and the practical gap between “what’s supported” and “what people still write” is wider than it’s ever been. So let’s close it.
Container queries are the biggest shift
Media queries ask “how wide is the viewport?” Container queries ask “how wide is the box I’m sitting in?” That sounds minor. It isn’t. It means a card component can restyle itself based on whether it’s in a sidebar, a three-across grid, or a full-width hero, without you writing three separate variants or passing breakpoints through props.
.card-wrap {
container-type: inline-size;
}
.card {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@container (min-width: 30rem) {
.card {
grid-template-columns: 12rem 1fr;
align-items: center;
}
}
If you’re still maintaining a pile of .card--narrow and .card--wide modifiers, this replaces almost all of it. Support is universal now, so there’s no reason to hold back.
:has() finally killed a whole category of JavaScript
The parent selector shipped and it’s been stable for a while. You can now style an element based on what’s inside it. The classic example is a form field that should turn red when its input is invalid:
.field:has(input:invalid) {
border-color: #c0392b;
}
.field:has(input:invalid) .hint {
display: block;
}
/* Card with an image gets different padding */
article:has(img) {
padding: 0 0 1.5rem;
}
/* Nav that contains an active link */
nav:has(a[aria-current="page"]) {
border-bottom: 2px solid currentColor;
}
Before this, every one of those patterns meant a MutationObserver, an event listener, or a class toggled in a framework. Now it’s a selector. I’ve pulled real weight off several codebases just by deleting that plumbing.
Native nesting is fine now, with one caveat
CSS nesting is standardized and supported. The syntax that bit people early on was the ambiguity around element selectors, so the spec settled on requiring & when a nested selector starts with a type selector:
.menu {
display: flex;
gap: 1rem;
}
.menu a {
color: inherit;
}
/* or nested */
.menu {
& a {
color: inherit;
}
&:hover {
background: #f4f4f4;
}
}
Note the leading & on & a. You can omit it for class and pseudo selectors, but keeping it everywhere is the habit I’d recommend. It reads the same and you never get surprised.
What I’d stop doing in 2026
- Stop reaching for a preprocessor for variables. Custom properties do more, cascade properly, and can be changed at runtime from JavaScript or a media query.
- Stop using float for layout. It hasn’t been the right tool since grid landed.
- Stop shipping a reset you don’t understand. A short modern reset plus
box-sizing: border-boxcovers nearly everything. - Stop writing vendor prefixes by hand. Autoprefixer and the browserslist config handle it, and most of the old prefixes are dead anyway.
- Stop fighting the cascade with !important. If you need it, your specificity is the actual bug.
Color, units, and math got genuinely nicer
oklch() is the color space I default to now. It’s perceptually uniform, which means lightening a color by a fixed amount actually looks like the same amount of lightening across hues. That was never true with HSL.
:root {
--brand: oklch(62% 0.19 250);
--brand-light: oklch(82% 0.09 250);
--brand-dark: oklch(42% 0.17 250);
}
.button {
background: var(--brand);
color: white;
padding: 0.75rem 1.25rem;
border-radius: 0.5rem;
}
.button:hover {
background: var(--brand-dark);
}
And clamp() for fluid type means you can drop a lot of breakpoint-specific font sizing:
h1 {
font-size: clamp(1.75rem, 1rem + 3vw, 3.5rem);
line-height: 1.1;
}
That single line replaces three media queries and behaves better on the awkward widths in between.
Does any of this matter for a small business site?
Yes, but indirectly. Cleaner CSS means fewer bytes, fewer layout bugs, and less time billed when you want a change. If you’re paying someone to maintain a site, modern CSS is the difference between “swap the card layout” being a five minute edit and being a refactor. That’s real money either way.
If you’re weighing a rebuild versus patching what you have, it’s usually worth having someone look at the stylesheet before you commit to either. I do that kind of work as a Long Island web design developer, and the honest answer is often “your CSS is fine, here’s the three things to fix.”
Browser support in 2026
Container queries, :has(), nesting, oklch(), and clamp() are all baseline available. You do not need a fallback for any of them for a normal commercial site. The one thing I’d still check before using is anything tied to the newest view transitions and scroll-driven animations, which are shipping but with enough variation that I test per project rather than assume.
FAQ
Do I still need Sass or Less?
For most projects, no. Variables, nesting, and color functions are native now. The remaining reasons are large legacy codebases and teams that rely on Sass mixins heavily. New projects generally don’t need it.
Is it safe to use :has() on a site with older visitors?
Yes. It’s been supported across all major browsers for years. If a browser doesn’t understand the selector, it just ignores that rule, so nothing breaks, you only lose the enhancement.
How much does modernizing a stylesheet actually save?
It depends entirely on the starting point. I’ve seen files shrink by half after removing reset cruft and dead media queries, and I’ve seen files where the only win was readability. Anyone quoting you a percentage before looking at the code is guessing.


