Modern CSS Features
CSS has evolved dramatically. Container queries, :has(), view transitions, and native nesting are now production-ready.
Learn the features that are changing how we write CSS.
Browser Support Overview (2025)
| Feature | Chrome | Safari | Firefox | Status |
|---|---|---|---|---|
| Container Queries | 105+ | 16+ | 110+ | Stable |
| :has() Selector | 105+ | 15.4+ | 121+ | Stable |
| CSS Nesting | 120+ | 17.2+ | 117+ | Stable |
| View Transitions | 111+ | 18+ | Partial | Partial |
| Subgrid | 117+ | 16+ | 71+ | Stable |
| Scroll-Driven Animations | 115+ | No | No | Chrome Only |
| color-mix() | 111+ | 16.2+ | 113+ | Stable |
| Cascade Layers | 99+ | 15.4+ | 97+ | Stable |
| Anchor Positioning | 125+ | No | No | Chrome Only |
Container Queries
StableStyle elements based on their container's size, not the viewport. Build truly reusable components that adapt to any context.
Modern Selectors & Nesting
StableThe :has() selector lets you style parents based on children. Native nesting means no more preprocessor for nested styles.
Animations & Transitions
View Transitions create smooth page-to-page animations. Scroll-driven animations sync with scroll position without JavaScript.
Layout Features
Subgrid lets nested elements align to parent grid tracks. Anchor positioning places elements relative to other elements without JavaScript.
Color & Architecture
Stablecolor-mix() creates dynamic color variations. Cascade layers give you explicit control over CSS specificity.
Quick Examples
Container Queries
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card { flex-direction: row; }
}:has() Parent Selector
/* Style parent based on child */
.card:has(img) {
padding: 0;
}
.form:has(:invalid) {
border-color: red;
}CSS Nesting
.card {
padding: 1rem;
& h2 { font-size: 1.5rem; }
&:hover { box-shadow: 0 4px 12px; }
@media (width > 768px) {
padding: 2rem;
}
}color-mix()
:root {
--primary: #3b82f6;
--primary-light: color-mix(
in srgb, var(--primary), white 30%
);
--primary-dark: color-mix(
in srgb, var(--primary), black 30%
);
}