paint-brush
Es 2023, pero todavía tenemos que hablar sobre estilos anidados en CSSpor@lastcallofsummer
3,720 lecturas
3,720 lecturas

Es 2023, pero todavía tenemos que hablar sobre estilos anidados en CSS

por Olga Stogova8m2023/07/17
Read on Terminal Reader

Demasiado Largo; Para Leer

Los estilos profundamente anidados a menudo generan conflictos de estilo, especialmente si tiene un proyecto grande. Esto puede generar inconsistencias visuales inesperadas y mucho tiempo perdido. El concepto de especificidad (o el "peso" de los estilos) en CSS es crucial para comprender por qué el anidamiento profundo puede ser problemático.
featured image - Es 2023, pero todavía tenemos que hablar sobre estilos anidados en CSS
Olga Stogova HackerNoon profile picture
0-item

Incluso una imagen aleatoria para la solicitud de "estilos CSS" contiene estilos anidados.


Como desarrollador frontend con casi 15 años de experiencia, he sido testigo de primera mano de la evolución del desarrollo web. Para mí, ha recorrido un largo camino desde los días en que subía archivos modificados a través de FTP (sí, GitHub se lanzó hace 15 años, pero recién lo descubrí en 2011) hasta la era moderna de interfaces receptivas, bibliotecas de UI y sitios web generados directamente desde Figma.


Sin embargo, sigo encontrando proyectos que emplean estilos anidados como:


 .some-class ul li div a { /* some style */ }


o,


 #nav .nav-link svg { /* some style */ }


Puede parecer impactante, pero tales prácticas de codificación impregnan todo, desde proyectos multimillonarios y de rápido crecimiento hasta humildes empresas emergentes.


Profundicemos en por qué este enfoque puede plantear problemas.

El conflicto de los estilos anidados

Los estilos profundamente anidados a menudo generan conflictos de estilo, especialmente si tiene un proyecto grande. CSS, como una hoja de estilo en cascada, cae en cascada y se aplica a los elementos según su especificidad. Los estilos profundamente anidados pueden invalidar involuntariamente otros estilos debido a su especificidad.


Considere este ejemplo:


 .some-class ul li div a { color: red; } ... .some-class a { color: blue; }


Es de esperar que todos los enlaces en .some-class sean azules. Sin embargo, debido a la mayor especificidad de la primera regla, cualquier enlace anidado dentro de un ul > li > div será rojo, no azul. Esto puede generar incoherencias visuales inesperadas y mucho tiempo perdido en la depuración.

La complejidad de la especificidad

Comprender el concepto de especificidad (o el "peso" de los estilos) en CSS es crucial para comprender por qué la anidación profunda puede ser problemática. La especificidad determina qué regla CSS se aplica si varias reglas compiten por un solo elemento. Se calcula en función del tipo y la cantidad de selectores.


La especificidad se calcula en base a un sistema de ponderación de cuatro categorías:


  1. Estilos en línea
  2. identificaciones
  3. Clases, atributos y pseudoclases
  4. Elementos y pseudo-elementos


Aquí, considere la regla:


 body #content .data img:hover { /* some style */ }


La especificidad es 0 1 2 2 . Esa es una ID ( #content ), dos clases ( .data y :hover ) y dos elementos ( body e img ).


Ahora, considere la regla:


 #nav .nav-link svg { /* some style */ }


La especificidad aquí es 0 1 1 1 . Esa es una ID ( #nav ), una clase ( .nav-link ) y un elemento ( svg ).


La especificidad no opera en un sistema de "transferencia" como los números decimales tradicionales. Por ejemplo, un selector con una especificidad de 0 1 0 11 no es igual a una especificidad de 0 1 1 1 aunque en un sistema decimal, 11 y 1+1 serían equivalentes.


Finalmente, el selector universal ( * ), los combinadores ( + , > , ~ , ' ') y la pseudoclase de negación ( :not() ) no tienen efecto sobre la especificidad. Sin embargo, dentro del argumento :not() , los selectores se cuentan como de costumbre.


Para los estudiantes visuales, recomiendo este video sobre la especificidad de CSS.


Comprender la especificidad de CSS y cómo se calcula le permite escribir un CSS mejor y más predecible y depurar problemas cuando los estilos no se aplican como se esperaba.

La regla !important y la especificidad

A veces, los desarrolladores recurren al uso de la regla !important cuando enfrentan dificultades con conflictos de especificidad de CSS. Esta regla hace que una propiedad CSS sea extremadamente específica, lo que significa que anulará casi cualquier otra declaración.


Por ejemplo:


 #nav .nav-link svg { color: blue; } .nav-link svg { color: red !important; }


A pesar de que la primera regla tiene una mayor especificidad debido al selector de ID, el color del svg sería rojo debido a la !important de la segunda regla.

Los riesgos del uso excesivo !importante

Si bien !important puede ser una solución rápida cuando se enfrentan problemas de especificidad, no se recomienda su uso extensivo. El uso excesivo puede afectar la capacidad de mantenimiento, la previsibilidad y el rendimiento. En proyectos más grandes, el uso excesivo de !important a menudo indica una dificultad para administrar la especificidad de CSS. En lugar de recurrir a !important , a menudo es mejor invertir tiempo en refactorizar su CSS y reducir el uso de selectores demasiado específicos.


Puedes consultar tu producto ahora mismo 🙂. He comprobado el mio:


111 da como resultado 55 archivos, ¡no está mal para un gran producto!


Si bien !important puede ser una solución rápida y tentadora; es como usar un mazo para romper una nuez. Un enfoque más fácil de mantener es mantener sus selectores lo más simples y planos posible, lo que hace que su CSS sea más fácil de entender, administrar y ampliar en el futuro. Y recuerda, la mejor manera de ganar una guerra !important es no comenzar una en primer lugar.

Atravesando el árbol CSS

Otro problema con los estilos profundamente anidados es el impacto en el rendimiento de la representación del navegador. Cuando un navegador aplica estilos a un elemento, atraviesa el DOM de derecha a izquierda, comenzando con el selector de teclas (en nuestros ejemplos, a y svg ) y moviéndose a través de los ancestros hasta que encuentra una coincidencia o llega a la parte superior. Cuanto más anidado sea el estilo, más tiempo llevará este recorrido, lo que podría afectar el rendimiento y ralentizar los tiempos de carga de la página en proyectos a gran escala.


Cuando especifica una regla CSS, como:


 .some-class ul li a { /* some style */ }


Puede visualizar esta regla comenzando desde la parte inferior del árbol (desde la etiqueta a ) y avanzando hacia arriba a través del árbol (a través de li , ul y .some-class ).



solo una pequeña parte del modelo de objetos CSS



El navegador primero buscará todos (me refiero a TODOS) a elementos a, luego verificará si estas a están dentro de los elementos li . Después de eso, verificará si estos elementos li están dentro ul y, por último, verificará si estos ul están dentro de un elemento con la clase de .some-class .


Así es como los navegadores leen los selectores de CSS y la razón por la cual los selectores complejos pueden conducir a una representación de página más lenta. El navegador tiene que realizar varias comprobaciones para cada elemento para ver si se ajusta a la regla especificada. Cuanto más profunda sea la regla, más verificaciones tiene que hacer el navegador, lo que puede afectar el rendimiento.

Mejores prácticas para administrar CSS en proyectos más grandes

Módulos CSS

Los módulos de CSS le permiten escribir CSS en módulos individuales, que tienen un alcance local para el componente en el que está trabajando. Esto significa que los estilos en un módulo CSS solo se aplican a ese módulo específico y no se filtrarán ni afectarán a otros elementos de la página.


Exploremos cómo los módulos CSS usan nombres de clase con hash para garantizar la encapsulación de estilo. Cuando usa módulos CSS, los nombres de clase que define en su archivo CSS se codificarán en tiempo de compilación. Este hash crea un nombre de clase único que corresponde a su componente. Echemos un vistazo a un ejemplo:


Suponga que tiene un Módulo CSS definido como tal:


 /* Button.module.css */ .button { color: white; background-color: blue; }


Y lo usa en su componente de esta manera (prefiero importar el objeto de estilos como s en lugar de styles , un consejo rápido que ahorra tiempo de escritura y aumenta la eficiencia de la codificación):


 import React from 'react'; import s from './Button.module.css'; const Button = () => { return ( <button className={s.button}>Click me</button> ); }; export default Button;


Cuando se compila su aplicación, su HTML renderizado podría verse así:


 <button class="Button_button__3FQ9Z">Click me</button>


En este caso, Button_button__3FQ9Z es el nombre de clase con hash que se generó a partir de su módulo CSS. Tenga en cuenta que la estructura exacta y la longitud del hash pueden variar según la configuración de su proyecto.


Este nombre de clase único garantiza que los estilos que ha definido en Button.module.css solo se aplican a este botón y no afectarán a ningún otro elemento de su aplicación. También garantiza que ningún otro estilo pueda afectar este botón a menos que apunten explícitamente al nombre de la clase con hash. Esta encapsulación de estilos es uno de los principales beneficios de los Módulos CSS.

Bibliotecas CSS-in-JS

Otra forma popular de manejar CSS es mediante el uso de bibliotecas CSS-in-JS, como componentes con estilo o emoción . Estas bibliotecas le permiten escribir su CSS directamente dentro de su JavaScript, lo que tiene varios beneficios:


  1. Estilos con ámbito : de forma similar a los módulos CSS, los estilos tienen como ámbito el componente en el que están definidos.
  2. Estilos dinámicos : es fácil crear estilos dinámicos basados en accesorios o estado en su componente.
  3. Experiencia de desarrollador mejorada : puede usar la lógica de JavaScript directamente en sus estilos, y todo lo relacionado con un componente se encuentra en un solo lugar, lo que puede hacer que su código sea más fácil de entender y trabajar con él.


Aquí hay un ejemplo de cómo puede usar componentes con estilo en una aplicación React:


 import React from 'react'; import styled from 'styled-components'; const Button = styled.button` color: white; background-color: ${(props) => props.primary ? 'blue' : 'gray'}; `; const App = () => { return ( <div> <Button primary>Primary Button</Button> <Button>Secondary Button</Button> </div> ); }; export default App;


En este ejemplo, el componente Button tiene estilos dinámicos que cambian según su propiedad primary .

Metodología BEM

Si no está trabajando con un marco de JavaScript que admita módulos CSS o similar, aún puede administrar su CSS de manera efectiva utilizando metodologías de nomenclatura como BEM (Bloque, Elemento, Modificador).


BEM significa "Modificador de elemento de bloque" y es una metodología que lo ayuda a crear componentes reutilizables y compartir código en CSS. Así es como puede estructurar su CSS usando BEM:


 /* Block */ .top-menu { } /* Element */ .top-menu__item { } /* Modifier */ .top-menu__item_active { }


En BEM, el 'Bloque' es la entidad independiente que es significativa por sí misma, el 'Elemento' es una parte del Bloque que no tiene un significado independiente y está vinculado semánticamente a su Bloque, y el 'Modificador' es una bandera en un bloque o elemento que se utiliza para cambiar la apariencia o el comportamiento.


El uso de una metodología consistente como BEM puede hacer que su CSS sea más fácil de entender y mantener, particularmente en proyectos más grandes.

En conclusión

Hay varias formas de administrar CSS en proyectos más grandes, desde módulos CSS y bibliotecas CSS-in-JS hasta metodologías de nombres como BEM. La clave es encontrar un enfoque que encaje bien con su equipo y proyecto y aplicarlo de manera consistente. Recuerde, escribir CSS se trata tanto de escribir un código que sea eficiente y eficaz como de escribir un código que sea comprensible y mantenible.


¡Feliz codificación!