Difficulty: Advanced
What are the newest CSS features? Explain :has(), native nesting, and @layer.
Modern CSS (2023-2025) introduced game-changing features:
1. :has() - parent selector: style parent based on children 2. Native CSS Nesting - nest selectors like Sass (no preprocessor needed) 3. @layer - cascade layers for controlling specificity order 4. @scope - scope styles to a DOM subtree 5. Subgrid - child grids inheriting parent grid tracks
These features reduce the need for preprocessors (Sass) and CSS-in-JS, making vanilla CSS much more powerful.
/* Style parent based on child */
.card:has(img) {
grid-template-rows: auto 1fr;
}
.card:has(img):not(:has(.badge)) {
/* Card with image but no badge */
}
/* Form validation styling */
.field:has(input:invalid) {
border-color: red;
}
.field:has(input:valid) {
border-color: green;
}
.form:has(input:invalid) .submit-btn {
opacity: 0.5;
pointer-events: none;
}
/* Conditional layouts */
.grid:has(> :nth-child(4)) {
grid-template-columns: repeat(2, 1fr);
}
.grid:has(> :nth-child(7)) {
grid-template-columns: repeat(3, 1fr);
}
/* Previous sibling selector (reverse + ) */
.item:has(+ .item:hover) {
/* Style item BEFORE the hovered item */
transform: scale(0.95);
}
:has() is the most requested CSS feature ever. It lets you select parents and previous siblings, which was previously impossible without JavaScript.
/* Native CSS nesting (no Sass needed!) */
.card {
background: white;
border-radius: 0.5rem;
/* Nested selector */
& .title {
font-size: 1.25rem;
font-weight: 600;
}
/* & is optional for pseudo-classes */
&:hover {
box-shadow: 0 4px 12px rgb(0 0 0 / 0.1);
}
/* Nested media query */
@media (min-width: 768px) {
padding: 2rem;
& .title {
font-size: 1.5rem;
}
}
/* BEM with nesting */
&__body {
padding: 1.5rem;
}
&--featured {
border: 2px solid #3b82f6;
}
}
/* Compiles mentally to:
.card { }
.card .title { }
.card:hover { }
.card__body { }
.card--featured { } */
Native CSS nesting works like Sass but in the browser with no build step. The & symbol references the parent selector. Supported in all modern browsers since 2023.
/* Define layer order (lowest to highest priority) */
@layer reset, base, components, utilities;
/* Reset layer (lowest priority) */
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
/* Base layer */
@layer base {
body { font-family: system-ui; line-height: 1.6; }
a { color: #3b82f6; }
}
/* Components layer */
@layer components {
.btn {
padding: 0.75rem 1.5rem;
border-radius: 0.375rem;
}
.card {
background: white;
border-radius: 0.5rem;
}
}
/* Utilities layer (highest priority) */
@layer utilities {
.hidden { display: none !important; }
.text-center { text-align: center; }
}
/* Utilities ALWAYS override components,
regardless of specificity!
.card has higher specificity than .hidden,
but utilities layer wins */
/* Un-layered styles beat ALL layers */
@layer controls the cascade independently from specificity. Later layers override earlier ones regardless of selector specificity. This solves specificity wars.
:has(), CSS Nesting, @layer, Cascade Layers, Modern CSS Features