Explorando SMACSS: arquitectura escalable y modular para CSS
Publicado: 2022-03-11Cuando estamos trabajando en grandes proyectos o con grupos de desarrolladores, a menudo encontramos que nuestro código es desordenado, difícil de leer y difícil de extender. Esto es especialmente cierto después de que pasa el tiempo y volvemos y lo miramos de nuevo; tenemos que tratar de estar en la misma mentalidad que teníamos cuando lo escribimos.
Entonces, lo que mucha gente ha hecho es crear arquitecturas CSS para ayudar a diseñar su código para que CSS se vuelva más legible. SMACSS , es decir, arquitectura escalable y modular para CSS , tiene como objetivo hacer precisamente eso. Es un conjunto particular de pautas de arquitectura CSS de Jonathan Snook que he adoptado.
Ahora, el enfoque arquitectónico de SMACSS es un poco diferente de un marco CSS como Bootstrap o Foundation. En cambio, es un conjunto de reglas, más como una plantilla o guía. Entonces, profundicemos en algunos patrones de diseño de CSS para descubrir cómo podemos usarlos para hacer que nuestro código sea mejor, más limpio, más fácil de leer y más modular.
Cada estructura de proyecto SMACSS utiliza cinco categorías:
- Base
- Disposición
- Módulos
- Estado
- Tema
Base
En SMACSS, los estilos básicos definen el aspecto que debería tener un elemento en cualquier parte de la página. Son los predeterminados. Si está utilizando una hoja de estilo de restablecimiento, esto garantiza que sus estilos resultantes sean los mismos en todos los navegadores a pesar de las diferencias entre sus valores predeterminados de CSS básicos internos y codificados.
En un estilo base, solo debe incluir selectores de elementos desnudos, o aquellos con pseudoclases, pero no con selectores de clase o ID. (Debería tener una muy buena razón para poner clase o ID dentro de él, tal vez solo si está diseñando los elementos de un complemento de terceros y necesita anular el estilo predeterminado para ese elemento en particular).
Aquí hay un ejemplo de cómo debería verse una unidad de archivo base:
html { margin: 0; font-family: sans-serif; } a { color: #000; } button { color: #ababab; border: 1px solid #f2f2f2; }
Por lo tanto, debe incluir tamaños, márgenes, colores, bordes y cualquier otro valor predeterminado que planee usar en su sitio web. Su tipografía y los elementos de su formulario deben tener estilos unificados que aparezcan en cada página y den la sensación y apariencia de que son parte del mismo diseño y tema.
SMACSS o no, recomiendo evitar el uso de !important
tanto como sea posible, y no usar anidamiento profundo, pero hablaré más sobre eso más adelante en esta publicación. Además, si su práctica es usar reset CSS, este es el lugar donde debe incluirlo. (Prefiero usar Sass, así que simplemente lo incluyo en la parte superior del archivo, en lugar de tener que copiarlo o referirme a él por separado del elemento <head>
de cada página).
Disposición
Los estilos de diseño dividirán la página en secciones principales, no secciones como la navegación o tal vez el acordeón, por ejemplo, sino divisiones de nivel superior:
Estos diseños contendrán múltiples módulos CSS como cuadros, tarjetas, listas desordenadas, galerías y similares, pero hablaré más sobre los módulos en la siguiente sección. Consideremos una página web de ejemplo para ver qué podemos dividir en diseños:
Aquí tenemos encabezado, principal y pie de página. Estos diseños tienen módulos como enlaces y logotipo en el encabezado en la parte superior, recuadros y artículos en la página principal y enlaces y derechos de autor en el pie de página. Por lo general, le damos a los diseños un selector de ID, ya que no se repiten en la página y son únicos.
También debe prefijar las reglas para los estilos de diseño con la letra l
para distinguirlos de los estilos de módulos. Por lo general, aquí diseñaría cosas específicas del diseño, como bordes, alineaciones, márgenes, etc. También el fondo de esa parte de la página podría tener sentido, incluso si no parece ser tan específico del diseño.
Aquí hay un ejemplo de cómo debería verse:
#header { background: #fcfcfc; } #header .l-right { float: right; } #header .l-align-center { text-align: center; }
También puede agregar estos ayudantes para alineaciones que puede usar para colocar fácilmente elementos simplemente agregando la clase apropiada a su hijo o para alinear su texto.
Para otro ejemplo, podría usar algunos márgenes predeterminados en un cuadro de diseño, como .l-margin
con un margen de 20px
. Luego, donde quiera que desee relleno para algún contenedor, elemento, tarjeta o caja, simplemente agregue la clase l-margin
. Pero quieres algo reutilizable:
.l-full-width { width: 100%; }
No algo acoplado internamente como esto:
.l-width-25 { width: 25px; }
Quiero tomarme un momento para hablar sobre las convenciones de nomenclatura en SMACSS. Si nunca ha oído hablar del concepto de espacio de nombres en CSS, básicamente se trata de agregar el nombre al comienzo de otro elemento para ayudar a distinguirlo de cualquier otra cosa. Pero, ¿por qué necesitamos esto?
No sé si alguna vez te has encontrado con el siguiente problema. Está escribiendo CSS y tiene una etiqueta en algo: coloca los estilos que desee y llama a su clase .label
. Pero luego llegas a otro elemento más adelante, y también quieres que sea .label
, pero con un estilo diferente. Entonces, dos cosas diferentes tienen el mismo nombre: un conflicto de nombres.
El espacio de nombres lo ayuda a resolver esto. En última instancia, se llaman igual en un nivel, pero tienen un espacio de nombres diferente (un prefijo diferente) y, por lo tanto, pueden representar dos estilos diferentes:
.box--label { color: blue; } .card--label { color: red; }
Módulo
Como mencioné anteriormente, los módulos SMACSS son fragmentos de código más pequeños que se pueden reutilizar en la página y forman parte de un diseño único. Estas son partes de CSS que queremos almacenar en una carpeta separada, ya que tendremos muchas de ellas en una sola página. Y a medida que crece un proyecto, podemos dividirlo utilizando las mejores prácticas de estructura de carpetas, es decir, por módulos/páginas:

Entonces, en el ejemplo anterior, teníamos un artículo, que puede ser un módulo por sí solo. ¿Cómo debería estructurarse CSS aquí? Deberíamos tener una clase .article
que pueda tener elementos secundarios title
y text
. Entonces, para poder mantenerlo en el mismo módulo, necesitamos prefijar los elementos secundarios:
.article { background: #f32; } .article--title { font-size: 16px; } .article--text { font-size: 12px; }
Puede notar que estamos usando dos guiones después del prefijo del módulo. La razón es que, a veces, los nombres de los módulos tienen dos palabras o sus propios prefijos, como big-article
. Necesitamos tener dos guiones para saber qué parte de él es el elemento secundario, por ejemplo, compare big-article-title
con big-article--title
y big-article--text
.
Además, puede anidar módulos dentro de módulos si un módulo en particular ocupa una gran parte de la página:
<div class="box"> <div class="box--label">This is box label</div> <ul class="box--list list"> <li class="list--li">Box list element</li> </ul> </div>
Aquí, en este ejemplo simple, puede ver que el box
es un módulo y la list
es otro módulo dentro. Entonces list--li
es un elemento secundario del módulo list
y no del box
. Uno de los conceptos clave aquí es usar dos selectores como máximo por cada regla de CSS, pero en la mayoría de los escenarios tener solo un selector con prefijos.
De esta manera, podemos evitar la duplicación de reglas y también tener selectores adicionales en elementos secundarios con los mismos nombres, mejorando así la velocidad. Pero también nos ayuda a evitar el uso de reglas de estilo !important
no deseadas, que son un signo de proyectos CSS mal estructurados.
Bueno (tenga en cuenta el selector único):
.red--box { background: #fafcfe; } .red-box--list { color: #000; }
Malo (tenga en cuenta la repetición dentro de los selectores y el método de referencia superpuesto):
.red .box { background: #fafcfe; } .red .box .list { color: #000; } .box ul { color: #fafafa; }
Estado
Lo que define el estado en SMACSS es una forma de describir cómo se ven nuestros módulos en diferentes situaciones dinámicas. Entonces, esta parte es realmente para la interactividad: queremos un comportamiento diferente si se considera que un elemento está oculto, expandido o modificado. Por ejemplo, un acordeón jQuery necesitará ayuda para definir cuándo puede o no puede ver el contenido de un elemento. Nos ayuda a definir el estilo de un elemento en un momento específico.
Los estados se aplican al mismo elemento que el diseño, por lo que estamos agregando una regla adicional que anulará las anteriores, si las hay. La regla estatal tiene prioridad, ya que es la última en la cadena de reglas.
Al igual que con los estilos de diseño, tendemos a usar prefijos aquí. Esto nos ayuda a reconocerlos y darles prioridad. Aquí usamos el prefijo is
, como en is-hidden
o is-selected
.
<header> <ul class="nav"> <li class="nav--item is-selected">Contact</li> <li class="nav--item">About</li> </ul> </header>
.nav--item.is-selected { color: #fff; }
Aquí, se puede usar !important
, ya que el estado se usa a menudo como una modificación de JavaScript y no en el momento del procesamiento. Por ejemplo, tiene un elemento que está oculto en la carga de la página. Al hacer clic en el botón, desea mostrarlo. Pero la clase predeterminada es así:
.box .element { display: none; }
Entonces, si solo agregas esto:
.is-shown { display: block; }
Permanecerá oculto incluso después de agregar la clase .is-shown
al elemento a través de JavaScript. Esto se debe a que la primera regla tiene dos niveles de profundidad y la anulará.
Entonces, en su lugar, puede definir la clase de estado de esta manera:
.is-shown { display: block !important; }
Así es como distinguimos los modificadores de estado de los de diseño, que se aplican solo en la carga inicial de una página. Esto funcionará ahora manteniendo las ventajas de los selectores mínimos.
Tema
Este debería ser el más obvio, ya que se usa para contener las reglas de los colores primarios, formas, bordes, sombras y demás. En su mayoría, estos son elementos que se repiten en todo un sitio web. No queremos redefinirlos cada vez que los creamos. En su lugar, queremos definir una clase única que solo agregaremos más tarde a un elemento predeterminado.
.button-large { width: 60px; height: 60px; }
<button class="button-large">Like</button>
No confunda estas reglas de tema SMACSS con las básicas, ya que las reglas básicas apuntan solo a la apariencia predeterminada y tienden a ser algo así como restablecer la configuración predeterminada del navegador, mientras que una unidad de tema es más un tipo de estilo en el que da el aspecto final, único para este esquema de color específico.
Las reglas de temas también pueden ser útiles si un sitio tiene más de un estilo o tal vez un par de temas utilizados en diferentes estados y, por lo tanto, se pueden cambiar o intercambiar fácilmente durante algunos eventos en una página, por ejemplo, con un botón de cambio de tema. Como mínimo, mantienen todos los estilos de temas en un solo lugar para que pueda cambiarlos fácilmente y mantenerlos bien organizados.
Metodologías de organización CSS
He cubierto algunos de los conceptos clave de esta idea de arquitectura CSS. Si quieres saber más sobre este concepto puedes visitar la web oficial de SMACSS y profundizar en él.
Sí, probablemente puedas usar metodologías más avanzadas como OOCSS y BEM. Este último cubre casi todo el flujo de trabajo de frontend y sus tecnologías. Los selectores BEM pueden funcionar muy bien para algunas personas, pero algunas pueden encontrarlos demasiado largos y abrumadores, y también demasiado complicados de usar. Si necesita algo más simple que sea más fácil de aprender e incorporar a su flujo de trabajo, y también algo que defina las reglas básicas para usted y su equipo, SMACSS es la opción perfecta.
Será fácil para los nuevos miembros del equipo no solo entender lo que hicieron los desarrolladores anteriores, sino también comenzar a trabajar en ello al instante, sin diferencias en el estilo de codificación. SMACSS es solo una arquitectura CSS y hace lo que dice en la lata, nada más y nada menos.