Introducción
Si eres un desarrollador front-end que ha trabajado con un preprocesador CSS, probablemente hayas conocido o utilizado la función de anidamiento. Ha sido una función popular y, en mi caso, fue una de las que me impulsaron a usar un preprocesador CSS.
Este año, la anidación nativa de CSS fue compatible con los principales navegadores: Chrome, Firefox y Safari. Es una función esencial de CSS que facilita la escritura. En este artículo, documentaré lo que he aprendido sobre la anidación de CSS hasta ahora y compartiré mis hallazgos con ustedes, junto con casos de uso y ejemplos.
No hay requisitos previos que seguir excepto tu entusiasmo y concentración.
La anidación en CSS ha sido una función muy esperada por muchos desarrolladores. Antes dependíamos de preprocesadores CSS como Sass o Less. Les daré un breve resumen:
Considere el siguiente ejemplo. Tenemos un icono en el selector .nav__item.
.nav__item {
.icon {
display: flex;
padding: 1rem;
}
}El código anterior es código Sass válido. Al compilarlo, se verá así en el navegador:
.nav__item .icon {
display: flex;
padding: 1rem;
}Con la anidación de CSS nativo, el mismo CSS funcionará tal cual. Aquí se muestra una figura que compara la anidación de CSS nativo con las herramientas de desarrollo del navegador.
Observe cómo el navegador muestra el CSS de forma similar (casi) a como se muestra en CSS.
Si este CSS se compilara en Sass, el navegador lo mostraría de la siguiente manera:
Beneficios de la anidación de CSS
En mi opinión, hay razones válidas que hacen que el CSS anidado sea útil:
- CSS es más fácil de leer.
- Estilo de agrupación juntos
- Limitar estilos específicos
- Dar estilo a elementos HTML que no tienen clases ni ID.
Reglas de anidación CSS
Para educarte sobre la anidación de CSS, intentaré proporcionar ejemplos visuales de varios problemas de CSS y cómo la anidación puede ayudar a resolverlos.
Primero que nada, necesitas aprender sobre el símbolo &. Hay varias situaciones en las que este símbolo es esencial.
Anidar un elemento sin una clase o ID
En este ejemplo, el elemento <a> Estilo mediante .nav__item. El uso de la marca <head> es opcional para que el CSS sea válido.
.nav__item {
& a {
display: block;
padding: 1.5rem 1rem;
}
}
/* Same as: */
.nav__item a {
}También puedes desactivar la marca de verificación:
.nav__item {
a {
display: block;
padding: 1.5rem 1rem;
}
}
/* Same as: */
.nav__item a {
}Tenga en cuenta que esta es una actualización reciente llamada Anidación CSS relajada. Funciona en las versiones más recientes de Chrome Canary y Safari Technology Preview. Consulte esta publicación sobre Anidación relajada de Adam Argyle.
Anidar un elemento con una clase
Consideremos el mismo ejemplo que antes, pero supongamos que el elemento <a> Tiene una clase HTML.
.nav__item {
.link {
display: block;
padding: 1.5rem 1rem;
}
}
/* Same as: */
.nav__item .link {
}No es necesario usar ningún símbolo. El nombre de la clase funcionará perfectamente.
Combinadores CSS anidados
Una de las ventajas de la anidación nativa de CSS es el uso de combinadores. Veamos algunos ejemplos.
En el siguiente ejemplo, quiero seleccionar cualquier elemento con la clase .nav__item precedido por otro elemento de la misma clase. Para ello, utilicé el selector de elementos hermanos adyacentes.
En la anidación nativa de CSS, podemos usar el símbolo "&" para imitar esto. Observa que lo repetí dos veces.
.nav__item {
& + & {
border-left: 2px solid;
}
}
La magia ocurre en la segunda iteración del símbolo &. Aquí, el navegador detecta que quiero usar el selector de hermano adyacente. Les mostraré una figura que lo demuestra:
Otro ejemplo de anidación es el combinador de elementos secundarios. Permite seleccionar el elemento secundario directo de un elemento.
.nav__item {
> a {
padding: 1rem;
}
}Símbolo de ampersand
.nav__item {
& a {
color: blue;
}
}Esto era obligatorio en la especificación original de anidación de CSS. En Safari TP 179+ y Chrome Canary 120, el símbolo & ya no es necesario para los elementos anidados.
Como resultado se realizaron las siguientes obras:
.nav__item {
a {
color: blue;
}
}El único problema es que hay que volver a la versión anterior de la especificación, que debe incluir el marcado y el marcado.
Anidación con ejemplo: Activo, Enfoque, Flotar
:active, :focus y :hover son pseudoclases CSS que se activan mediante la acción del usuario.
Con la anidación de CSS, podemos anidarlos todos a la vez para evitar la duplicación de código. Tomemos :hover como ejemplo:
button {
&:hover {
background-color: var(--bg-color);
}
&:focus {
outline: solid 2px;
}
}La diferencia al utilizar un preprocesador para anidar es que el navegador lo procesa de la siguiente manera:
button:hover {
background-color: var(--bg-color);
}
button:focus {
outline: solid 2px;
}Echemos un vistazo a cómo se muestra la anidación de CSS en Chrome, Safari y Firefox.
Tengo algunas ideas sobre DevTools UX para la anidación de CSS y las abordaré más adelante en el artículo.
Anidación con ejemplo: publicación de contenido
Uno de los primeros ejemplos de pruebas de CSS anidado es la aplicación de estilo al contenido del cuerpo de una publicación. Imagina un artículo con encabezados, texto, imágenes, citas y más.
Titulares
Tendemos a diseñar títulos como los siguientes:
.post-content h1,
.post-content h2,
.post-content h3,
.post-content h4 {
/* styles here */
}Con CSS anidado, es más fácil:
.post-content {
h1,
h2,
h3,
h4 {
color: var(--heading-color);
font-weight: var(--heading-font-bold);
margin-bottom: var(--size-2);
}
}También podemos hacer lo mismo usando el selector :is().
.post-content {
:is(h1, h2, h3, h4) {
color: var(--heading-color);
font-weight: var(--heading-font-bold);
margin-bottom: var(--size-2);
}
}Elemento de párrafo
Un caso común es aplicar estilo a un enlace dentro de un párrafo. En este caso, la anidación de CSS funciona de maravilla.
.post-content {
& p {
color: var(--color-black);
& a {
font-weight: bold;
text-decoration: underline;
}
}
}El enlace también puede requerir un efecto de desplazamiento o enfoque.
.post-content {
& p {
color: var(--color-black);
& a {
font-weight: bold;
text-decoration: underline;
&:hover {
/* hover styles */
}
}
}
}También podemos anidar consultas de medios.
.post-content {
& p {
/* base styles */
@media (min-width: 400px) {
/* do something */
}
}
}En algunos casos, un CMS puede ser un elemento <p> envuélvalo en otro elemento y, por motivos de estilo, solo debe usarse para elementos directos <p> Dale estilo.
.post-content {
/* Select the direct <p> elements */
> p {
/* base styles */
}
}Cita en bloque
En este ejemplo, la cita obtiene su propio estilo personalizado y el elemento <p> Dentro de la cita, seleccione para restablecer el margen inferior a cero.
.post-content {
& blockquote {
/* custom quote styling */
& p {
margin-bottom: 0;
}
}
}Forma del poste
El formulario de publicación contiene una imagen y un
En mi ejemplo, si
.post-content {
& figure {
& img {
/* the figure's image styles */
}
/* changes to the <figure> container, if it has a figcaption element */
&:has(figcaption) {
display: flex;
align-items: start;
}
& figcaption {
/* caption styling */
}
}
}Lista de publicaciones
Necesito añadir un borde a todos los elementos de la lista excepto al último. Para ello, usé el selector :not().
.post-content {
li {
&:not(:last-child) {
border-bottom: 1px solid;
}
}
}Para usar :not(), necesitamos agregar un ampersand antes.
Espaciado personalizado para encabezados
La distancia de seguimiento debe ser <h3> y <h4> Lo reduciré si uno de ellos va seguido de un fragmento de código.
.post-content {
& h3 + [class*="language-"],
& h4 + [class*="language-"] {
margin-top: 0.5rem;
}
}Como viste en este ejemplo práctico, usar la anidación de CSS es simple, especialmente si tienes experiencia en preprocesadores de CSS.
Anidación con ejemplo: componente Tarjeta
Mostraré un componente de tarjeta simple que utiliza anidación CSS para lograr los estilos deseados.
Suponiendo que hay un elemento .card con estilos predeterminados o base, demostraré el uso de CSS anidado.
.card {
/* default card styles */
}
CONSULTAS DE CONTENEDORES ANIDADOS
Si el ancho del contenedor es mayor a 400px, quiero que la tarjeta se transforme en un contenedor flexible.
.card {
/* default card styles */
/* if the container width is 400px or bigger */
@container card (min-width: 400px) {
display: flex;
}
}Dar estilo a un elemento de párrafo
Quiero utilizar el elemento de párrafo a través de <h3> De esta manera, puedo aplicar márgenes y relleno al elemento. <p> Lo añadiré. Si no está, la interfaz no tendrá el espacio adicional.
.card__content {
& h3 + p {
border-top: 1px solid #000;
padding-top: 0.5rem;
margin-top: 0.5rem;
}
}Cuando el ancho del contenedor es de 400 píxeles o más, el elemento .card__content también debe convertirse en un contenedor flexible.
.card__content {
& h3 + p {
border-top: 1px solid #000;
padding-top: 0.5rem;
margin-top: 0.5rem;
}
@container card (min-width: 400px) {
display: flex;
flex-direction: column;
justify-content: center;
}
}ANIDACIÓN con ejemplo: Entrada de formulario
Un caso común es aplicar estilo a un marcador de posición de entrada. El problema es que cada proveedor de navegador tiene su propio prefijo (¡vaya, estamos en 2023!).
Dado que los estilos de prefijo requieren dos puntos, debemos usar el símbolo &; de lo contrario, los estilos se romperán.
input {
--placeholder-color: #969696;
/* other styles */
&::-webkit-input-placeholder {
color: var(--placeholder-color);
}
&::-moz-placeholder {
color: var(--placeholder-color);
opacity: 1;
}
&:-moz-placeholder {
color: var(--placeholder-color);
}
}Quizás te preguntes cuál es la diferencia entre usar CSS anidado o escribir un estilo de prefijo directamente sin él.
/********** Option 1: native nesting **********/
input {
&::-webkit-input-placeholder {
color: var(--placeholder-color);
}
}
/********** Option 2: without nesting **********/
input::-webkit-input-placeholder {
color: var(--placeholder-color);
}No hay diferencia entre ambos. Ambos tienen las mismas propiedades (0, 1, 1).
ANIDACIÓN con ejemplo: Estilizar un elemento a través de su elemento padre
Podemos usar la anidación CSS para cambiar los estilos de un elemento secundario según su ubicación. Por ejemplo, si un elemento .button reside en un elemento primario .box, debería ocupar todo el ancho.
<div class="box">
<h2>Get access to all features</h2>
<p>Create an account now and get access to all exclusive features.</p>
<a href="/offer" class="button">Create an account</a>
</div>.button {
.box & {
width: 100%;
}
}
/* equivalent to */
.box .button {
}Errores que vi al explorar la anidación de CSS
Uso del selector global sin signo
Supongamos que tenemos una tarjeta y queremos seleccionar todos los elementos que contiene. Con la anidación nativa de CSS, esto debería funcionar:
.card {
* {
/* styles here */
}
}Noté que esto no funciona en Chrome Stable, pero funciona bien en Chrome Canary 121, Safari 17.1 y Firefox 119.
La solución es añadir el signo de puntuación.
.card {
& * {
/* styles here */
}
}Uso de atributos de datos sin signo
En este problema, seleccionar un atributo de datos sin una marca de verificación no proporciona el resultado esperado.
.card {
[data-type="featured"] {
/* styles here */
}
}Noté que no funciona en Chrome Stable, pero funciona bien en Chrome Canary 121, Safari 17.1 y Firefox 119.
Para solucionarlo, necesitamos agregar una coma:
.card {
&[data-type="featured"] {
/* styles here */
}
}Ambos errores se solucionaron en la versión para la anidación relajada de CSS en Chrome Canary.
Identificación del soporte de anidación de CSS
@supports se puede usar para comprobar la compatibilidad con la anidación de CSS. En nuestro caso, queremos comprobar si el navegador reconoce el símbolo "&".
@supports selector(&) {
.post-content {
& h2 {
/* styles here. */
}
}
}Puedes explorar otras opciones para identificar soporte en este Codepen de Bramus.
Hoy usaré el plugin de anidación PostCSS, que compila CSS anidado a CSS normal. Lo eliminaré cuando sea seguro usarlo.
DevTools UX para anidación de CSS
No soy un gran admirador de la experiencia de usuario actual para la anidación de CSS en DevTools del navegador.
Trabajé en un artículo aparte donde exploré algunas sugerencias sobre cómo me gustaría que fuera la anidación de CSS en DevTools.
Resultado
La anidación de CSS es una característica importante que mejora la escritura de CSS. Actualmente, es posible usar la anidación, pero hay que tener cuidado con el público, ya que el soporte es aún nuevo.
























