CSS Nesting nativo
Durante años, anidar selectores era exclusivo de Sass y LESS. Desde 2023, CSS nativo lo soporta en todos los navegadores modernos. Sin compilador, sin dependencias.
La sintaxis básica
El selector & representa el elemento padre:
/* Antes — sin nesting */
.card { padding: 1rem; border-radius: 8px; }
.card .title { font-size: 1.25rem; }
.card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); }
.card:hover .title { color: var(--color-primary); }
/* Ahora — con CSS Nesting */
.card {
padding: 1rem;
border-radius: 8px;
& .title {
font-size: 1.25rem;
}
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
& .title {
color: var(--color-primary);
}
}
}
El símbolo &
& es el selector del bloque padre. Su posición determina la relación:
.btn {
background: var(--color-primary);
/* .btn:hover */
&:hover {
background: var(--color-accent);
}
/* .btn.activo */
&.activo {
background: var(--color-success);
}
/* .btn + .btn (hermano adyacente) */
& + & {
margin-left: 0.5rem;
}
/* .contenedor .btn (dentro de .contenedor) */
.contenedor & {
width: 100%;
}
}
Media queries anidadas
Una de las ventajas más prácticas: las media queries van junto al componente, no al final del archivo:
.hero {
display: grid;
grid-template-columns: 1fr;
padding: 2rem 1rem;
@media (min-width: 768px) {
grid-template-columns: 1fr 1fr;
padding: 4rem 2rem;
}
@media (min-width: 1200px) {
grid-template-columns: 1fr 1fr 1fr;
}
& .hero-title {
font-size: clamp(2rem, 5vw, 4rem);
@media (min-width: 768px) {
color: var(--color-primary);
}
}
}
@supports anidado
Igual que con media queries:
.elemento {
display: flex;
@supports (display: grid) {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
Diferencias con Sass
| Característica | CSS Nativo | Sass |
|---|---|---|
| Requiere compilador | No | Sí |
& en posición de selector | Sí (a &) | Sí |
& concatenado en nombre | No (&-title no funciona) | Sí |
| Media queries anidadas | Sí | Sí |
@each, @for, @mixin | No | Sí |
| Variables | Sí (custom properties) | Sí (distintas) |
La diferencia clave: en Sass puedes hacer &-title para generar .card-title. En CSS nativo, & solo puede ir donde iría un selector completo, no concatenado a texto.
Buenas prácticas
/* ✅ Bien: nesting para estados y variantes del mismo componente */
.btn {
&:hover { ... }
&:focus-visible { ... }
&.btn--large { ... }
&.btn--ghost { ... }
}
/* ✅ Bien: hijos directos relacionados */
.card {
& .card__header { ... }
& .card__body { ... }
& .card__footer { ... }
}
/* ❌ Evitar: demasiados niveles de anidado */
.nav {
& ul {
& li {
& a {
& span { ... } /* 5 niveles — ilegible */
}
}
}
}
Regla práctica: no más de 3 niveles de anidado. Si necesitas más, es una señal para dividir el componente.
¿Qué hemos aprendido?
- CSS nativo ya soporta anidado con
&sin Sass ni compiladores. - Las media queries y
@supportsse pueden anidar dentro del componente. &representa el selector padre y debe usarse explícitamente para claridad.- Sass sigue siendo útil para funciones, bucles y concatenación de nombres con
&-.
Siguiente paso
En la próxima lección veremos Cascade Layers con @layer: cómo controlar el orden de la cascada de forma explícita, especialmente con CSS de terceros.