Evolución CSS: desde CSS, SASS, BEM, módulos CSS hasta componentes con estilo

Desde los inicios de Internet siempre hemos tenido la necesidad de diseñar nuestros sitios web, CSS ha existido desde siempre y ha evolucionado a su propio ritmo a lo largo de los años, este artículo lo llevará a través de él.

Para comenzar, necesitamos estar en la misma página de lo que es CSS, creo que todos podemos estar de acuerdo en que css se usa para describir la presentación de un documento escrito en un lenguaje de marcado.

No es ninguna noticia que CSS haya evolucionado en el camino y se haya vuelto más poderoso hoy en día, pero es ampliamente conocido que se necesitan herramientas adicionales para que css funcione de alguna manera para los equipos.

CSS en el salvaje oeste

En los años 90, solíamos centrarnos en crear interfaces "elegantes", el factor sorpresa era lo más importante, los estilos en línea eran la cosa en ese entonces, simplemente no nos importaba si las cosas se veían diferentes, al final las páginas web eran como juguetes lindos podríamos arrojar algunos gifs, carpas y otros elementos horribles (en ese momento impresionantes) y esperar captar la atención de sus visitantes.

Después de eso, comenzamos a crear sitios dinámicos, pero css seguía siendo un desastre constante, cada desarrollador tenía su forma de hacer css. Algunos de nosotros luchamos con la especificidad, causando regresiones visuales al introducir un nuevo código, confiamos en usar! Important para poner en piedra nuestra fuerte voluntad de hacer que un elemento de la interfaz de usuario se vea de cierta manera. Pero pronto nos dimos cuenta de que:

Todas esas prácticas se hicieron más evidentes y mayores problemas tan pronto como los proyectos crecieron en tamaño, complejidad y miembros del equipo. Por lo tanto, no tener un patrón consistente para diseñar se convirtió en uno de los mayores bloqueadores para desarrolladores experimentados e inexpertos que lucharon por encontrar la manera correcta de hacer las cosas en CSS. Al final no había nada correcto o incorrecto que hacer, solo nos preocupamos de que todo se viera bien.

SASS al rescate

SASS transformó CSS ​​en un lenguaje de programación decente en forma de un motor de preprocesamiento que implementó anidamiento, variables, mixins, extensiones y lógica en hojas de estilo, para que pueda organizar mejor sus archivos css y tener al menos algunas formas de deconstruir sus fragmentos css en pequeños archivos, que fue una gran cosa en ese entonces.

Básicamente toma código scss, lo procesa previamente y genera las versiones compiladas del archivo en un paquete css global. Genial verdad? pero no tanto, diría, después de un tiempo se hizo evidente que, a menos que hubiera estrategias y mejores prácticas, SASS solo causó más problemas de los que alivió.

De repente, no nos dimos cuenta de lo que el preprocesador estaba haciendo bajo el capó y confiamos en anidar perezosamente para conquistar la batalla de la especificidad, pero haciendo que las hojas de estilo compiladas se volvieran locas en tamaños.

Hasta que apareció BEM ...

BEM y pensamiento basado en componentes

Cuando apareció BEM, fue un soplo de aire fresco que nos hizo pensar más en la reutilización y los componentes. Básicamente llevó la semántica a un nuevo nivel, nos permitió asegurarnos de que className es único, reduciendo así el riesgo de choque de especificidad mediante el uso de una simple convención Modificador de elemento de bloque. Mira el siguiente ejemplo:

Si analiza un poco el marcado, puede ver inmediatamente la convención Modificador de elemento de bloque en juego aquí.

Puedes ver que tenemos dos bloques muy explícitos en el código: .scenery y .sky, cada uno de ellos tiene sus propios bloques. Sky es el único que tiene modificadores, ya que podría ser brumoso, diurno o al anochecer, esas son características diferentes que podrían aplicarse al mismo elemento.

Echemos un vistazo al CSS complementario con un pseudocódigo que nos permitirá analizarlo mejor:

Si desea tener una comprensión profunda de cómo funciona BEM, le recomiendo que lea este artículo, escrito por mi colega y amigo Andrei Popa.

BEM es bueno en el sentido de que se aseguró de que los componentes fueran únicos #reusabilityFtw. Con este tipo de pensamiento, algunos patrones aparentes se hicieron más evidentes a medida que comenzamos a migrar nuestras viejas hojas de estilo a esta nueva convención.

Pero, surgió otro conjunto de problemas:

  • La selección del nombre de clase se convirtió en una tarea tediosa
  • El marcado se hinchó con todos esos nombres de clase largos
  • Necesitabas extender explícitamente cada componente de la interfaz de usuario siempre que quisieras reutilizar
  • El marcado se volvió innecesariamente semántico

Módulos CSS y alcance local

Algunos de los problemas que ni SASS ni BEM arreglaron fue que en la lógica del lenguaje no existe un concepto de encapsulación verdadera, por lo tanto, confiando en que el desarrollador elija nombres de clase únicos. Un proceso que se podría resolver con herramientas en lugar de convenciones.

Y esto es exactamente lo que hicieron los módulos CSS, se basó en crear nombres de clase dinámicos para cada estilo definido localmente, asegurándose de que no se produzcan regresiones visuales al inyectar nuevas propiedades CSS, todos los estilos se encapsularon correctamente.

Los módulos CSS rápidamente ganaron popularidad en el ecosistema React y ahora es común ver muchos proyectos de reacción que lo usan, tiene sus pros y sus contras, pero sobre todo es un buen paradigma para usar.

Pero ... los módulos CSS por sí solos no resuelven los problemas centrales de CSS, solo le muestran una forma de localizar definiciones de estilo: una forma inteligente de automatizar BEM para que no tenga que pensar en elegir un nombre de clase nunca más (o al menos piénsalo menos).

Pero no alivia la necesidad de una arquitectura de estilo buena y predecible que sea fácil de extender, reutilizar y controlar con la menor cantidad de esfuerzo.

Así es como se ve el CSS local:

Puedes ver que es solo css, la principal diferencia es que todos los classNames precedidos por: local generarán un nombre de clase único que se parece a esto:

.app-components-button -__ root - 3vvFf {}

Puede configurar la identidad generada con el parámetro de consulta localIdentName. Ejemplo: css-loader? LocalIdentName = [ruta] [nombre] --- [local] --- [hash: base64: 5] para una depuración más fácil.

Ese es el principio simple detrás de los módulos CSS locales. Si puede ver, los módulos locales se convirtieron en una forma de automatizar la notación BEM generando un nombre de clase único que estaba seguro de que no entraría en conflicto con otros incluso si usaran el mismo nombre. Muy conveniente

Componentes diseñados para mezclar CSS en JS (completamente)

Los componentes con estilo son primitivos visuales puros que actúan como un componente de envoltura; se pueden asignar a etiquetas html reales y lo que hacen es envolver los componentes secundarios con el componente con estilo.

El siguiente código lo explicará mejor:

Si ve que el componente con estilo es muy simple de entender, utiliza la notación literal de plantilla para definir las propiedades de CSS, parece que el equipo central de componentes con estilo lo logró esta vez, ya que combina todo el poder de ES6 y CSS.

Styled-components proporciona un patrón muy simple para reutilizar y separar completamente la IU de los componentes funcionales y con estado. Crear una API que tenga acceso a etiquetas nativas en el navegador como HTML o de forma nativa utilizando React Native.

Así es como pasa accesorios personalizados (o modificadores) a un Componente con Estilo:

Puede ver que los accesorios de repente se convierten en los modificadores que recibe cada uno de los componentes y pueden procesarse para generar diferentes líneas de CSS, ¿no?

Esto nos permite movernos más rápido y usar toda la potencia de JS para procesar nuestros estilos, al tiempo que nos aseguramos de que sean coherentes y reutilizables.

Interfaz de usuario central para que todos puedan reutilizar

Rápidamente se hizo evidente que los módulos CSS ni los componentes con estilo por sí solos no eran la solución perfecta, necesitaban algún tipo de patrón para que funcionara y escalara. El patrón surgió definiendo qué es un componente y separándolo completamente de la lógica, creando componentes centrales cuyo único propósito es diseñar y nada más.

Un ejemplo de implementación de dicho componente utilizando módulos CSS:

Si ve, no hay nada lujoso aquí, solo un componente que recibe accesorios y esos se asignan al componente secundario. En otras palabras: el componente de envoltura transfiere todos los accesorios a los niños.

Entonces su componente se puede consumir de la siguiente manera

Permíteme mostrarte un ejemplo similar de una implementación completa de un botón usando componentes con estilo:

Lo interesante de este patrón es que el componente es tonto y solo sirve como un contenedor de definiciones CSS asignadas al componente padre. Hay una ventaja de hacer esto:

Nos permite definir una API de interfaz de usuario básica que puede intercambiar a voluntad y asegurarse de que toda la interfaz de usuario permanezca coherente en toda la aplicación.

De esta forma, podemos aislar completamente el proceso de diseño del proceso de implementación, haciendo posible activarlos en paralelo si se desea; puede tener 1 desarrollador enfocado en la implementación de la función y otro pulir la interfaz de usuario logrando una separación completa de las preocupaciones.

Parece una gran solución hasta ahora, internamente tuvimos discusiones al respecto y pensamos que era una buena idea seguir este patrón. Junto con este patrón, comenzamos a identificar otros patrones útiles también:

Prop receptores

Estos cumplen la función de escuchar los accesorios pasados ​​a cualquier componente, lo que facilita el uso de estas funciones en cualquier componente que desee, lo que lo convierte en el santo grial para la reutilización y amplía las capacidades de cualquier componente dado, puede considerarlo como un forma de heredar modificadores, un ejemplo de lo que quiero decir con esto:

De esta manera, está seguro de que no necesitará volver a codificar todos los bordes para cada componente específico , lo que le ahorrará toneladas de tiempo.

Marcador de posición / Mixin como funcionalidad

En los componentes con estilo, puede usar toda la potencia de JS para poder crear funciones no solo como receptores de utilería sino también como una forma de compartir código entre diferentes componentes, aquí hay un ejemplo:

Componentes de diseño

Hemos detectado que una de las primeras cosas que debemos hacer al trabajar en una aplicación es diseñar nuestros elementos de la interfaz de usuario, para este propósito, hemos identificado algunos componentes que nos ayudan en el proceso.

Estos componentes han demostrado ser muy útiles, ya que a menudo algunos desarrolladores (que no están lo suficientemente familiarizados con las técnicas de posicionamiento CSS) tienen dificultades para establecer la estructura, aquí hay un ejemplo de tales componentes:

Si puede ver, tenemos el componente que toma un ancho y una altura como accesorios y también recibe el apoyo horizontal, por lo que la barra de desplazamiento aparece a continuación.

Componentes auxiliares

Los componentes auxiliares nos facilitan la vida y nos permiten reutilizarlos en gran medida. Este es el lugar donde almacenamos todos nuestros patrones comunes.

Estos son algunos de los ayudantes que he encontrado bastante útiles hasta ahora:

Tema

Tener un tema le permite tener 1 fuente de verdad de valores que se pueden reutilizar en toda la aplicación, se ha demostrado que es útil para almacenar valores que se reutilizan comúnmente en la aplicación, como la paleta de colores y el aspecto general.

Pros

  • Todo el poder de JS en nuestras manos, lo que significa una comunicación total con la interfaz de usuario del componente.
  • Elimina la necesidad de mapear componentes y estilos mediante el uso de un className (esto se hace bajo el capó)
  • Gran experiencia de desarrollo hasta ahora, reduce la cantidad de tiempo dedicado a pensar en classNames y asignarlos al componente.

Contras

  • Sin embargo, para ser probado en la naturaleza
  • Creado para reaccionar
  • Super joven
  • Las pruebas deben hacerse a través de aria-labels o usando classNames

Conclusión

Independientemente de la tecnología que utilice, ya sean módulos SASS, BEM, CSS o componentes con estilo, no hay sustituto para una arquitectura de estilo bien definida que haga intuitivo que otros desarrolladores contribuyan a su base de código sin pensar demasiado, romper o introducir nuevas piezas móviles. al sistema

Este enfoque es crucial para escalar adecuadamente y se puede lograr incluso si se usa CSS y BEM simples, la principal diferencia es la cantidad de trabajo y LOC necesarios para cada implementación, los componentes con estilo en general se sienten como un gran juego para casi todos los proyectos de React, aún para probarlo en la naturaleza pero bastante prometedor.

Si tiene comentarios, opiniones, consejos o cualquier cosa, por favor comente a continuación, o no dude en comunicarse conmigo a través de twitter @ perezpriego7