Modern CSS — Container Queries, Nesting & :has()
Container Queries — Components That Adapt to Their Box
Media queries ask “how wide is the screen?” — but a card in a sidebar has less room than the same card full-width. Container queries ask “how wide is my container?”:
.card-wrapper {
container-type: inline-size; /* make this a measurable container */
container-name: card;
}
.card { display: flex; flex-direction: column; }
@container card (min-width: 420px) {
.card { flex-direction: row; } /* horizontal when ITS space allows */
}The same component now lays itself out correctly in a sidebar, a modal, or a full-width section — without knowing where it lives. This is the biggest shift in CSS architecture since grid.
Container units size things relative to the container: font-size: clamp(1rem, 4cqi, 1.5rem); (cqi = 1% of container inline size).
Native Nesting
What Sass popularised is now built in:
.card {
background: var(--surface);
padding: 1.5rem;
&:hover {
border-color: var(--accent);
}
.title { /* .card .title */
font-weight: 700;
}
@media (min-width: 768px) { /* media queries nest too! */
padding: 2rem;
}
}Keep nesting shallow (2 levels max) — deep nesting recreates the specificity problems you learned to avoid.
:has() Recap — Logic in Selectors
/* a form whose submit should light up when valid */
form:has(input:valid) .submit { opacity: 1; }
/* layout that adapts to its own content */
.gallery:has(> :nth-child(5)) { /* 5+ items? tighter grid */
grid-template-columns: repeat(4, 1fr);
}Logical Properties
Write direction-aware CSS (works for RTL languages automatically):
/* instead of margin-left / margin-right */
margin-inline-start: 1rem;
padding-inline: 2rem; /* left+right in one */
padding-block: 3rem; /* top+bottom in one */
inset: 0; /* top/right/bottom/left: 0 */
margin-inline: auto; /* the new centering idiom */Small Powerhouses
/* aspect-ratio — no more padding-top hacks */
.video { aspect-ratio: 16 / 9; }
/* accent-color — native checkboxes/radios in your brand color */
:root { accent-color: #6366F1; }
/* scroll-snapping — carousel physics in pure CSS */
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
}
.carousel > * { scroll-snap-align: start; }
/* smooth anchor scrolling */
html { scroll-behavior: smooth; }
/* color-mix — derive hover shades from tokens */
.btn:hover {
background: color-mix(in oklch, var(--accent), black 15%);
}
/* text-wrap — typographic polish */
h1 { text-wrap: balance; } /* even-length heading lines */
p { text-wrap: pretty; } /* no single-word last lines */All of the above ships in every modern browser. Check caniuse.com when in doubt, and use @supports for progressive enhancement:
@supports (container-type: inline-size) {
/* container-query layout here */
}