CSS Has Changed
If you learned CSS a few years ago and have not kept up with new features, you might be surprised by how much the language has evolved. Many problems that used to require JavaScript or complex workarounds now have clean CSS-only solutions. Browser support for modern features has improved rapidly, and most of these can be used in production today.
Container Queries
Container queries allow you to style elements based on the size of their container rather than the viewport. This is a fundamental shift for component-based design, because components can now adapt to whatever space they are placed in.
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
With container queries, a card component can switch from a stacked layout to a horizontal layout based on its container width, regardless of the viewport size. This makes components truly reusable across different page regions.
The :has() Selector
The :has() selector, sometimes called the parent selector, lets you style an element based on its descendants. This was one of the most requested CSS features for over a decade.
/* Style a card differently when it contains an image */
.card:has(img) {
padding: 0;
}
/* Style a form group when its input is invalid */
.form-group:has(input:invalid) {
border-color: var(--color-error);
}
This eliminates the need for JavaScript-driven class toggling in many common scenarios.
Cascade Layers
Cascade layers give you explicit control over the order of precedence in your stylesheets. You define named layers and their order, and the cascade respects that order regardless of selector specificity.
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer utilities {
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; }
}
This solves specificity wars in large codebases by making the cascade predictable and intentional.
Native Nesting
CSS nesting, inspired by preprocessors like Sass, is now supported natively. You can write nested selectors directly in your stylesheets without any build step.
.nav {
display: flex;
gap: 1rem;
& a {
text-decoration: none;
color: var(--color-text);
&:hover {
color: var(--color-primary);
}
}
}
Other Features Worth Knowing
Several other modern CSS features deserve attention:
- Subgrid lets nested grids align to their parent grid's tracks
- View Transitions API enables animated transitions between page states
- Scroll-driven animations let you create animations that respond to scroll position without JavaScript
- Color functions like
oklch()andcolor-mix()provide better color manipulation - Logical properties like
margin-inlineandpadding-blockmake layouts that adapt to different writing modes
The pace of CSS development has accelerated, and keeping up with new features gives you simpler, more maintainable solutions to common design problems.