Skip to main content

Modern CSS Features (2024–2025)

This page covers the newest CSS capabilities that are now production-ready. These are the features AI tools generate, modern browsers support, and that will shape how CSS is written going forward.

1. CSS Nesting (Native &)

CSS nesting — like Sass, but built into the browser. No preprocessor needed. ~96% browser support.

/* ❌ Before: Repetitive flat selectors */
.card { background: var(--color-surface); }
.card:hover { box-shadow: var(--shadow-lg); }
.card .card__title { font-size: 1.5rem; }
.card .card__title:hover { color: var(--color-primary); }

/* ✅ After: Nested CSS */
.card {
background: var(--color-surface);

&:hover { box-shadow: var(--shadow-lg); }

.card__title {
font-size: 1.5rem;
&:hover { color: var(--color-primary); }
}

.card__body { padding: var(--space-6); }
}

Nesting with Pseudo-Classes

.btn {
padding: 0.75rem 1.5rem;

&:hover { background: var(--color-primary-dark); }
&:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 3px; }
&:disabled { opacity: 0.5; cursor: not-allowed; }

&.btn--outline {
background: transparent;
border: 2px solid var(--color-primary);

&:hover { background: var(--color-primary); color: white; }
}
}

Nesting Media Queries

.hero {
padding: 4rem 1rem;

@media (min-width: 768px) {
padding: 6rem 2rem;
}

@media (min-width: 1024px) {
padding: 8rem 4rem;
}

h1 {
font-size: clamp(2rem, 5vw, 5rem);
}
}

2. :has() — The Parent Selector

:has() lets you style a parent based on its children — the long-awaited "parent selector". ~88% support.

/* Style a form section if it contains an invalid input */
.form-group:has(input:invalid) {
border-color: var(--color-danger);
}

/* Card with image gets less top padding */
.card:has(img) { padding-top: 0; }

/* Navigation item with an open dropdown */
.nav__item:has(.dropdown.is-open) { color: var(--color-primary); }

/* Label next to a required field */
label:has(+ input:required)::after { content: ' *'; color: var(--color-danger); }

/* Grid changes when it contains a featured item */
.post-grid:has(.card--featured) { grid-template-columns: 2fr 1fr 1fr; }

3. @layer — Cascade Layer Management

@layer gives you explicit control over the cascade — no more specificity wars. ~91% support.

/* Declare layer order first — lower = weaker */
@layer reset, base, components, utilities, wp-theme;

@layer reset {
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
}

@layer base {
body { font-family: var(--font-body); line-height: 1.6; }
:where(h1, h2, h3, h4) { font-family: var(--font-heading); }
}

@layer components {
.card { background: var(--color-surface); border-radius: var(--radius-md); }
.btn { padding: 0.75rem 1.5rem; border-radius: var(--radius-full); }
}

@layer utilities {
.text-center { text-align: center !important; }
.hidden { display: none !important; }
}

@layer wp-theme {
/* WordPress theme overrides — weakest within components but beats reset/base */
.entry-content p { max-width: 72ch; }
}

[!TIP] !important in a lower layer loses to normal rules in a higher layer. This means you can import a third-party stylesheet into a reset layer and it will never beat your component styles — even without !important.

4. color-mix() — Programmatic Color Mixing

Mix two colors at the CSS level — great for dynamic theme generation. ~88% support.

:root {
--color-primary: hsl(245, 80%, 62%);

/* Create tints and shades from one base color */
--color-primary-10: color-mix(in oklch, var(--color-primary) 10%, white);
--color-primary-50: color-mix(in oklch, var(--color-primary) 50%, white);
--color-primary-90: color-mix(in oklch, var(--color-primary) 90%, black);
}

/* On-the-fly: mix with transparent for overlays */
.overlay { background: color-mix(in srgb, var(--color-primary) 20%, transparent); }

/* Mix two brand colors */
.gradient-mid { background: color-mix(in oklch, #6c63ff 50%, #f5a623); }

5. @property — Typed CSS Variables

Register CSS variables with a type — enables animating custom properties. ~84% support.

/* Without @property: hue can't animate because CSS doesn't know it's a number */
@property --hue {
syntax: '<number>';
initial-value: 245;
inherits: false;
}

@property --gradient-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}

/* Now these animate smoothly */
.rotating-gradient {
background: linear-gradient(var(--gradient-angle), #6c63ff, #00ff87);
animation: rotate-gradient 4s linear infinite;
}

@keyframes rotate-gradient {
to { --gradient-angle: 360deg; }
}

6. CSS Subgrid

Subgrid lets children of a grid item inherit the parent grid's tracks — aligning elements across nested containers. ~88% support.

.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}

/* Cards use the parent grid's columns internally */
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* ← The key: inherit parent row tracks */
}

/* Now all cards' inner rows align across the grid */
.card__image { } /* Row 1 — same height across all cards */
.card__body { } /* Row 2 — same height */
.card__footer { } /* Row 3 — all footers on same baseline */

7. field-sizing: content — Auto-Sizing Inputs

Textareas and inputs that grow with their content. ~82% support.

/* Textarea grows as user types — no JS needed */
textarea {
field-sizing: content;
min-height: 3rem;
max-height: 20rem;
}

/* Input width fits its content */
input[type="text"] { field-sizing: content; min-width: 10ch; }

8. Anchor Positioning (Emerging)

CSS-native tooltip/popover positioning relative to any anchor element. ~78% support.

/* Anchor an element */
.trigger { anchor-name: --my-anchor; }

/* Position popover relative to anchor */
.popover {
position-anchor: --my-anchor;
position: absolute;
top: anchor(bottom); /* Align popover top with anchor bottom */
left: anchor(left); /* Align to anchor's left edge */
}

9. Feature Support Timeline Summary

FeatureBrowser SupportUse Now?
CSS Nesting~96%✅ Yes
:has()~88%✅ Yes
@layer~91%✅ Yes
color-mix()~88%✅ Yes (with fallback)
Container Queries~89%✅ Yes
Subgrid~88%✅ Yes
Scroll-driven animation-timeline~82%⚠️ With fallback
@property~84%⚠️ With fallback
Anchor Positioning~78%⚠️ Experimental
field-sizing~82%⚠️ With fallback