CSS features worth adding to your toolkit in 2024
Several CSS features have reached stable support across major browsers this past year. These aren't experimental tricks, but practical, toolbelt-worthy capabilities that can simplify how you write stylesheets today.
:has(): more than a parent selector
By the end of 2023, :has() was supported in all major browsers. While it's often described as a "parent selector," that name undersells its utility. The selector subject can be any element in the tree, not just a parent—this enables content-aware layouts and component logic that previously required JavaScript.
Basic parent-selecting use cases include adding a gap to a button when it contains an icon, or changing a card's orientation when it contains an image:
.button:has(.icon) { gap: 8px; }
.card:has(img) { flex-direction: row; }
Quantity queries were a long-requested pattern, and :has() makes them possible by keeping the container as the selector subject while counting its children:
.container:has(> :last-child:nth-child(4)) { }
It also works at the document level. You can alter styles globally when a specific checkbox is toggled, for instance:
html:has(#dark-mode:checked) { }
The selector can shift its subject further down the tree. For example, you can show a form error message when any input inside the form is invalid:
form:has(:invalid) .error-message { display: block; }
The same principle lets you slide out the main content area when a navigation aside is opened:
main:has(+ aside.--is-open) { transform: translateX(-200px); }
Combined with container queries and quantity queries, :has() enables a single grid layout capable of elegantly handling anywhere from 1 to 12 items in both portrait and landscape orientations.
Creating a subgrid
CSS Grid has been wildly popular, but one gap remained for years: nested grids couldn't align with their parent's tracks. Subgrid closes that gap. It's now supported in all three major browser engines, with the latest of the big three shipping support in 2023.
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
}
.child {
display: grid;
grid-column: span 2;
grid-template-columns: subgrid;
}
Instead of defining its own track sizing, the nested grid inherits the column structure of its parent, aligning child items effortlessly.
CSS nesting: no build step required
Native CSS nesting became available in all major browsers during 2023. This syntax means you no longer need a preprocessor step to nest rules—and shipping raw nesting often results in smaller stylesheets overall.
The syntax is straightforward:
.card {
padding: 1rem;
&:hover {
background: hotpink;
}
.title {
font-size: 1.2rem;
}
}
Browser devtools are ready for it, so you can inspect nested rules in the same familiar way you would any other selector.
Balanced and pretty text wrapping
Manually inserting line-break hints as content is authored guarantees nothing once text is translated, zoomed, or otherwise modified. The CSS text-wrap: balance property delegates this problem to the algorithm in the browser. text-wrap: pretty builds on the same idea for optimizing paragraph breaks across multiple lines.
Container query units
If you haven't yet picked up container queries, container query units are the logical next step after you get comfortable with them. There are six new units to know:
cqi– container inline sizecqw– container widthcqb– container block sizecqh– container heightcqmin– whichever is smallercqmax– whichever is larger
These units are particularly useful for relative, intrinsic animations or typography tied to the size of a component's container. For example, a child element that needs to slide completely out of view can be moved using 100cqi, meaning 100% of the container's inline size.
.child {
transform: translateX(100cqi);
}
You can also use them for container-responsive typography, or let an image adapt its dimensions based on the container's orientation—for instance, halving the image's width when the container is landscape-oriented.



