Modern CSS
Native nesting, :has(), :is/:where, logical properties, @layer.
Updated
What "modern CSS" means
In recent years CSS gained features that used to require Sass or JavaScript. Everything below works today in all major browsers — worth using, not just knowing.
Nesting — nested rules, natively
.card {
padding: 1rem;
& h3 { font-weight: 600; } /* .card h3 */
&:hover { border-color: gray; } /* .card:hover */
.dark & { background: black; } /* .dark .card */
@media (min-width: 48rem) {
padding: 2rem;
}
}& = the parent selector. Like in Sass, but without a build step. Don't nest more than 2–3 levels — specificity grows and the CSS becomes hard to read.
:has() — "the parent selector"
For the first time, you can style an element by what it contains or by what happens after it:
.card:has(img) { padding-top: 0; } /* cards with an image */
.field:has(input:invalid) label { color: var(--danger); } /* the label of an invalid field */
form:has(:focus-visible) { outline: 2px solid; } /* the form that has focus */
body:has(dialog[open]) { overflow: hidden; } /* lock scrolling while a modal is open */Many things that used to need state in React (a class on the parent) are now solved with CSS alone.
:is() and :where() — selector lists
:is(h1, h2, h3):hover { color: var(--accent); }
:where(ul, ol) { padding-left: 1rem; }:is() |
:where() |
|
|---|---|---|
| Specificity | that of the most specific argument | zero |
| When | shortening repeated selectors | base styles / resets, easy to override |
Logical properties
Instead of left / right / top / bottom, you describe the direction relative to the text. The layout then works automatically in right-to-left languages too (Arabic, Hebrew).
| Physical | Logical |
|---|---|
margin-left / margin-right |
margin-inline-start / margin-inline-end |
padding-left + padding-right |
padding-inline |
padding-top + padding-bottom |
padding-block |
width / height |
inline-size / block-size |
top/right/bottom/left: 0 |
inset: 0 |
Tailwind has them: ps-4, pe-4, ms-auto, px-4 = padding-inline.
@layer — the cascade order, made explicit
@layer reset, base, components, utilities;
@layer components {
.btn { padding: 1rem; }
}Layers declared later win, regardless of specificity — see The cascade. Tailwind v4 is built on them (theme, base, components, utilities).
Other useful features
| Feature | What it does |
|---|---|
clamp(), min(), max() |
fluid values without media queries |
color-mix(in oklab, var(--c) 20%, transparent) |
colors derived from tokens |
oklch() |
perceptually uniform colors — better palettes |
| container queries | responsive by parent — Responsive |
aspect-ratio |
a fixed ratio |
text-wrap: balance / pretty |
balanced headings, no orphan words |
accent-color |
the color of native checkboxes and radios |
Summary
- Native nesting with
&;:has()styles by content;:where()= zero specificity. - Logical properties (
padding-inline,inset) instead of left / right. @layercontrols the cascade;color-mix,oklch,text-wrap: balancefor modern details.