Container queries are finally stable
After a decade as the most-requested CSS feature, container queries for width are now stable across all major browsers. The syntax is straightforward: declare a containment context on a parent with the container property, then use the @container at-rule to apply styles when that context meets a size condition.
.panel {
container: layers-panel / inline-size;
}
.card {
padding: 1rem;
}
@container layers-panel (min-width: 20rem) {
.card {
padding: 2rem;
}
}
Scroll snap: intentional stopping points
Scroll snap lets you align scroll positions to meaningful points in your layout, which improves UX for carousels, image galleries, and paginated content. The core properties are scroll-snap-type on the container and scroll-snap-align on the children. Pair these with scroll-snap-stop to prevent users from skipping past an item, and overscroll-behavior to control what happens when the snap container reaches its boundary.
.snaps {
overflow-x: scroll;
scroll-snap-type: x mandatory;
overscroll-behavior-x: contain;
}
.snap-target {
scroll-snap-align: center;
}
.snap-force-stop {
scroll-snap-stop: always;
}
For a wider range of scroll-snap demos, see this Codepen collection of around 25 examples.
Grid piles instead of absolute positioning
You can avoid position: absolute entirely by placing elements in the same grid cell. Once stacked, use justify and align properties to fine-tune placement. This approach is cleaner and simpler to reason about, especially when items need to overlap responsively.
.pile {
display: grid;
place-content: center;
}
.pile > * {
grid-area: 1/1;
}
Circles without extra markup
Creating a perfect circle requires no pseudo-elements or wrapper divs. Combine aspect-ratio: 1 with a fixed width and border-radius: 50%, and you're done—no hacks, no extra HTML.
.circle {
inline-size: 25ch;
aspect-ratio: 1;
border-radius: 50%;
}
Cascade layers keep variant order sane
CSS cascade layers solve a real problem: when you add new variants to a component after the initial CSS has shipped, it's hard to slot them into the right place in the cascade without fights over specificity. Layer the styles up front with @layer for a button's variants:
/* file buttons.css */
@layer components.buttons {
.btn.primary {
…
}
}
Later, in a separate file loaded at any time, you can append a new variant to the very same layer—as if it had always been there:
/* file video-player.css */
@layer components.buttons {
.btn.player-icon {
…
}
}
This keeps the variant ordering consistent across files, independent of load order.
Logical properties: one mental model for writing modes
The box model you already know is physical: margin-left, padding-right, and so on. That works fine for left-to-right, horizontal writing modes, but not for vertical or right-to-left layouts. By switching to logical properties like padding-inline, margin-inline, and inset-inline, you stop needing to swap sides per language direction—the browser handles it. One rule fits every writing mode and document direction.
button {
padding-inline: 2ch;
padding-block: 1ch;
}
article > p {
text-align: start;
margin-block: 2ch;
}
.something::before {
inset-inline: auto 0;
}


