CSS

CSS

Tutorial CSS: Metodologías de escritura en CSS

Aprende las principales metodologías CSS para organizar y mantener código limpio: BEM, OOCSS, SMACSS y Atomic CSS con ejemplos prácticos.

Aprende CSS y certifícate

Principios de arquitectura BEM (Block, Element, Modifier)

Cuando trabajamos con proyectos CSS que crecen en complejidad, mantener un código organizado se vuelve un desafío. La arquitectura BEM es una metodología que nos ayuda a crear componentes reutilizables y a mantener nuestro código CSS más limpio y estructurado.

BEM significa Block, Element, Modifier (Bloque, Elemento, Modificador) y propone una convención de nomenclatura específica para nuestras clases CSS que refleja la estructura del DOM y facilita la comprensión del código.

Estructura básica de BEM

La nomenclatura BEM se basa en tres conceptos fundamentales:

  • Bloque: Un componente independiente que tiene significado por sí mismo.
  • Elemento: Una parte de un bloque que no tiene significado independiente.
  • Modificador: Una variante o estado de un bloque o elemento.

La sintaxis general sigue este patrón:

.bloque {}
.bloque__elemento {}
.bloque--modificador {}
.bloque__elemento--modificador {}

Veamos cada uno de estos conceptos con más detalle:

Bloques

Un bloque representa un componente autónomo de la interfaz. Piensa en él como una "pieza de Lego" que puede utilizarse en cualquier parte de tu sitio web. Los bloques deben nombrarse utilizando sustantivos que describan su propósito.

/* Ejemplos de bloques */
.header {}
.menu {}
.search-form {}
.button {}

Los bloques son independientes y pueden colocarse en cualquier parte de la página sin depender de otros componentes. Esto facilita la reutilización del código.

Elementos

Un elemento es una parte de un bloque que no tiene sentido por sí solo. Los elementos están semánticamente vinculados a su bloque y se nombran usando el nombre del bloque, seguido de dos guiones bajos y el nombre del elemento.

/* Ejemplos de elementos */
.menu__item {}
.header__logo {}
.search-form__input {}
.button__icon {}

La sintaxis bloque__elemento indica claramente que este elemento pertenece a un bloque específico. Esta relación visual en el código nos ayuda a entender la estructura de nuestros componentes.

Modificadores

Un modificador representa una variación o estado de un bloque o elemento. Se utiliza para cambiar la apariencia, el comportamiento o el estado. Los modificadores se nombran usando el nombre del bloque o elemento, seguido de dos guiones y el nombre del modificador.

/* Ejemplos de modificadores */
.button--large {}
.button--primary {}
.menu__item--active {}
.search-form--disabled {}

Los modificadores nos permiten crear variaciones de nuestros componentes sin duplicar código.

Ejemplo práctico de BEM

Veamos un ejemplo completo de un componente "tarjeta" utilizando la metodología BEM:

<div class="card">
  <img class="card__image" src="imagen.jpg" alt="Descripción">
  <div class="card__content">
    <h2 class="card__title">Título de la tarjeta</h2>
    <p class="card__text">Descripción de la tarjeta</p>
    <button class="card__button card__button--primary">Aceptar</button>
    <button class="card__button card__button--secondary">Cancelar</button>
  </div>
</div>

Y el CSS correspondiente:

/* Bloque */
.card {
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  max-width: 300px;
}

/* Elementos */
.card__image {
  width: 100%;
  height: auto;
}

.card__content {
  padding: 16px;
}

.card__title {
  margin-top: 0;
  font-size: 18px;
}

.card__text {
  color: #666;
  line-height: 1.5;
}

.card__button {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 8px;
}

/* Modificadores */
.card__button--primary {
  background-color: #4a90e2;
  color: white;
}

.card__button--secondary {
  background-color: #e0e0e0;
  color: #333;
}

Ventajas de utilizar BEM

  • Claridad en la estructura: La nomenclatura BEM refleja la estructura del DOM, lo que facilita entender la relación entre los elementos.

  • Especificidad controlada: Al usar clases únicas, evitamos problemas de especificidad y cascada que suelen complicar el mantenimiento del CSS.

/* Sin BEM - mayor especificidad y difícil de sobrescribir */
.header .navigation ul li a {}

/* Con BEM - especificidad plana y predecible */
.main-nav__link {}
  • Modularidad: Cada bloque es independiente, lo que facilita la reutilización y el mantenimiento.

  • Escalabilidad: BEM funciona especialmente bien en proyectos grandes donde múltiples desarrolladores trabajan en el mismo código.

Consejos para implementar BEM correctamente

  • Nombres descriptivos: Usa nombres que describan el propósito del componente, no su apariencia.
/* Incorrecto - describe apariencia */
.red-button {}

/* Correcto - describe propósito */
.submit-button {}
.submit-button--error {}
  • Evita elementos anidados: Aunque es posible tener elementos dentro de elementos (como .block__element1__element2), esto generalmente indica que tu estructura es demasiado compleja y deberías considerar crear un nuevo bloque.

  • Usa modificadores con moderación: Los modificadores deben representar variaciones significativas, no pequeños cambios de estilo.

  • Combina BEM con otras metodologías: BEM funciona bien en combinación con otras técnicas como los módulos CSS o las variables CSS.

/* Usando BEM con variables CSS */
:root {
  --primary-color: #4a90e2;
  --secondary-color: #e0e0e0;
}

.card__button--primary {
  background-color: var(--primary-color);
  color: white;
}

Ejemplo de refactorización a BEM

Veamos cómo podríamos refactorizar un código CSS tradicional a BEM:

Antes (sin BEM):

.navigation {
  background: #333;
}

.navigation ul {
  display: flex;
  list-style: none;
}

.navigation li {
  margin-right: 20px;
}

.navigation a {
  color: white;
  text-decoration: none;
}

.navigation a.active {
  font-weight: bold;
}

Después (con BEM):

.nav {
  background: #333;
}

.nav__list {
  display: flex;
  list-style: none;
}

.nav__item {
  margin-right: 20px;
}

.nav__link {
  color: white;
  text-decoration: none;
}

.nav__link--active {
  font-weight: bold;
}

El código refactorizado con BEM es más plano en términos de especificidad, más modular y más fácil de mantener a largo plazo.

BEM y el rendimiento

Una preocupación común sobre BEM es que genera nombres de clase largos. Sin embargo, el impacto en el rendimiento es mínimo comparado con los beneficios de mantenibilidad que ofrece. Además, las herramientas modernas de minificación pueden reducir estos nombres en producción.

La verdadera ventaja de BEM en términos de rendimiento viene de su especificidad plana, que evita selectores complejos que son costosos para el navegador al renderizar.

/* Selector complejo (más lento) */
.header nav ul li a.active {}

/* Selector BEM (más rápido) */
.nav__link--active {}

BEM nos proporciona una estructura clara para nuestro CSS, facilitando la creación de componentes reutilizables y mantenibles. Al adoptar esta metodología, podemos escribir código más organizado y escalable, especialmente en proyectos grandes o cuando trabajamos en equipo.

Enfoque OOCSS para reutilización de estilos

El CSS Orientado a Objetos (OOCSS, por sus siglas en inglés) es una metodología que nos ayuda a escribir CSS más eficiente y reutilizable. Desarrollada por Nicole Sullivan en 2008, esta aproximación aplica principios de la programación orientada a objetos al CSS, permitiéndonos crear código más modular y mantenible.

Principios fundamentales de OOCSS

OOCSS se basa en dos principios clave:

  • Separación de estructura y apariencia: Dividir las propiedades CSS que definen la estructura (como dimensiones y posicionamiento) de las que definen la apariencia visual (como colores y bordes).

  • Separación de contenedor y contenido: Los elementos no deberían depender de su ubicación en el DOM para recibir estilos.

Veamos cómo aplicar estos principios en la práctica:

Separación de estructura y apariencia

En lugar de crear clases específicas para cada elemento, OOCSS propone crear clases reutilizables que definan patrones comunes de estructura y apariencia por separado.

Enfoque tradicional (sin OOCSS):

.button-login {
  display: inline-block;
  padding: 10px 20px;
  border-radius: 5px;
  background-color: blue;
  color: white;
  font-weight: bold;
}

.button-signup {
  display: inline-block;
  padding: 10px 20px;
  border-radius: 5px;
  background-color: green;
  color: white;
  font-weight: bold;
}

Enfoque OOCSS:

/* Estructura (el "objeto" botón) */
.button {
  display: inline-block;
  padding: 10px 20px;
  border-radius: 5px;
}

/* Apariencia (temas para el botón) */
.button-primary {
  background-color: blue;
  color: white;
  font-weight: bold;
}

.button-success {
  background-color: green;
  color: white;
  font-weight: bold;
}

En HTML, aplicaríamos estas clases combinadas:

<button class="button button-primary">Iniciar sesión</button>
<button class="button button-success">Registrarse</button>

Esta separación nos permite reutilizar la estructura del botón con diferentes apariencias, reduciendo la duplicación de código.

Separación de contenedor y contenido

Este principio establece que un elemento debe verse igual independientemente de dónde se coloque en la página. Los estilos no deberían depender de selectores anidados.

Enfoque tradicional (sin OOCSS):

.sidebar h2 {
  font-size: 18px;
  color: #333;
  margin-bottom: 10px;
}

.main-content h2 {
  font-size: 18px;
  color: #333;
  margin-bottom: 15px;
}

Enfoque OOCSS:

.heading {
  font-size: 18px;
  color: #333;
}

.sidebar .heading {
  margin-bottom: 10px;
}

.main-content .heading {
  margin-bottom: 15px;
}

Mejor aún, podríamos crear clases de utilidad para los márgenes:

.heading {
  font-size: 18px;
  color: #333;
}

.mb-10 {
  margin-bottom: 10px;
}

.mb-15 {
  margin-bottom: 15px;
}

Y en HTML:

<div class="sidebar">
  <h2 class="heading mb-10">Título en sidebar</h2>
  <!-- Contenido -->
</div>

<div class="main-content">
  <h2 class="heading mb-15">Título en contenido principal</h2>
  <!-- Contenido -->
</div>

Creación de "objetos" reutilizables

En OOCSS, un "objeto" es un patrón de diseño recurrente que podemos abstraer en una clase reutilizable. Algunos ejemplos comunes son:

  • Media object: Para elementos con una imagen a un lado y texto al otro.
  • Flag object: Similar al media object, pero con alineación vertical.
  • Grid systems: Para crear layouts basados en cuadrículas.

Veamos un ejemplo del "media object", uno de los patrones más utilizados en diseño web:

.media {
  display: flex;
  align-items: flex-start;
}

.media__image {
  margin-right: 16px;
}

.media__content {
  flex: 1;
}
<div class="media">
  <img class="media__image" src="avatar.jpg" alt="Avatar de usuario">
  <div class="media__content">
    <h3>Nombre de usuario</h3>
    <p>Comentario del usuario que puede ocupar varias líneas de texto...</p>
  </div>
</div>

Este patrón se puede reutilizar en múltiples contextos: comentarios, listas de usuarios, notificaciones, etc.

Implementación práctica de OOCSS

Para implementar OOCSS de manera efectiva, podemos seguir estos pasos:

  1. Identificar patrones repetitivos en nuestro diseño
  2. Abstraer estos patrones en clases reutilizables
  3. Separar estructura y apariencia en diferentes clases
  4. Crear una biblioteca de componentes que podamos reutilizar

Veamos un ejemplo más completo de implementación OOCSS:

/* Estructuras básicas (objetos) */
.card {
  border-radius: 4px;
  overflow: hidden;
}

.btn {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  text-align: center;
  cursor: pointer;
}

/* Apariencias (temas) */
.card--bordered {
  border: 1px solid #ddd;
}

.card--shadowed {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.btn--primary {
  background-color: #4a90e2;
  color: white;
}

.btn--secondary {
  background-color: #f5f5f5;
  color: #333;
  border: 1px solid #ddd;
}

/* Utilidades para espaciado */
.p-20 {
  padding: 20px;
}

.mt-10 {
  margin-top: 10px;
}

Y en HTML:

<div class="card card--shadowed">
  <img src="imagen.jpg" alt="Imagen de producto">
  <div class="p-20">
    <h3>Título del producto</h3>
    <p>Descripción del producto...</p>
    <button class="btn btn--primary mt-10">Comprar ahora</button>
    <button class="btn btn--secondary mt-10">Añadir al carrito</button>
  </div>
</div>

Ventajas del enfoque OOCSS

  • Reducción de código: Al reutilizar patrones, eliminamos la duplicación de código CSS.

  • Mayor consistencia: Los componentes mantienen una apariencia coherente en toda la aplicación.

  • Mejor rendimiento: Menos código CSS significa archivos más pequeños y tiempos de carga más rápidos.

  • Mantenimiento más sencillo: Los cambios se pueden aplicar de manera global modificando una sola clase.

  • Escalabilidad: Facilita el crecimiento del proyecto sin que el CSS se vuelva inmanejable.

Comparación con otras metodologías

A diferencia de BEM, que se centra principalmente en la nomenclatura de clases, OOCSS se enfoca en la estructura conceptual del CSS. Mientras que BEM proporciona una convención de nombres clara, OOCSS ofrece principios para organizar y reutilizar el código.

Veamos una comparación rápida:

/* Enfoque BEM */
.card {}
.card__title {}
.card__content {}
.card--featured {}

/* Enfoque OOCSS */
.card {} /* Estructura */
.card-title {} /* Componente independiente */
.featured {} /* Tema/apariencia */

En la práctica, muchos desarrolladores combinan aspectos de diferentes metodologías para crear un enfoque híbrido que se adapte a sus necesidades específicas.

Ejemplo de refactorización a OOCSS

Veamos cómo podríamos refactorizar un código CSS tradicional a OOCSS:

Antes (CSS tradicional):

.product-box {
  width: 300px;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
  margin-bottom: 20px;
}

.user-profile {
  width: 300px;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
  margin-bottom: 20px;
  background-color: #f9f9f9;
}

Después (con OOCSS):

/* Estructura base */
.box {
  width: 300px;
  border-radius: 4px;
  padding: 15px;
  margin-bottom: 20px;
}

/* Temas/apariencias */
.box--bordered {
  border: 1px solid #ddd;
}

.box--light-bg {
  background-color: #f9f9f9;
}

En HTML:

<div class="box box--bordered">
  <!-- Contenido del producto -->
</div>

<div class="box box--bordered box--light-bg">
  <!-- Contenido del perfil de usuario -->
</div>

Consejos para implementar OOCSS correctamente

  • Nombra tus clases según su función, no su contenido: Usa nombres como .card en lugar de .product-info.

  • Crea clases pequeñas y específicas: Es mejor tener varias clases pequeñas que una grande con muchas propiedades.

  • Evita selectores anidados: Mantén la especificidad baja usando clases directas.

  • Documenta tus objetos: Crea una guía de estilos para que otros desarrolladores entiendan cómo usar tus componentes.

  • Usa herramientas de preprocesamiento con moderación: Aunque Sass o Less pueden ayudar, ten cuidado de no crear estructuras demasiado complejas que vayan contra los principios de OOCSS.

// Ejemplo con Sass - manteniéndolo simple
.btn {
  padding: 8px 16px;
  border-radius: 4px;
  
  &--primary {
    background-color: blue;
    color: white;
  }
  
  &--secondary {
    background-color: gray;
    color: black;
  }
}

OOCSS nos proporciona un enfoque estructurado para escribir CSS más modular y reutilizable. Al separar la estructura de la apariencia y el contenedor del contenido, podemos crear componentes flexibles que se pueden combinar de diferentes maneras, reduciendo la duplicación de código y facilitando el mantenimiento a largo plazo.

Metodología SMACSS para organización por categorías

SMACSS (Scalable and Modular Architecture for CSS) es una metodología de organización de código CSS desarrollada por Jonathan Snook que busca categorizar las reglas CSS según su función y alcance. A diferencia de BEM o OOCSS, SMACSS se centra principalmente en cómo estructurar y organizar nuestros archivos y reglas CSS en categorías bien definidas.

La idea fundamental de SMACSS es clasificar nuestras reglas CSS en cinco categorías distintas, cada una con un propósito específico y reglas de implementación propias. Esta categorización nos ayuda a mantener nuestro código más organizado y facilita la toma de decisiones sobre dónde colocar cada estilo.

Las cinco categorías de SMACSS

SMACSS divide nuestro CSS en estas categorías principales:

  • Base: Estilos predeterminados para elementos HTML sin clases ni IDs
  • Layout: Divisiones principales de la página
  • Module: Componentes reutilizables e independientes
  • State: Estados específicos de elementos y módulos
  • Theme: Variaciones visuales (opcional)

Veamos cada una de estas categorías con más detalle:

1. Reglas Base

Las reglas base definen la apariencia predeterminada de los elementos HTML en su estado natural, sin clases ni IDs aplicados. Estas reglas suelen incluir resets o normalizaciones de CSS y estilos por defecto para elementos como <body>, <h1>-<h6>, <a>, etc.

/* Ejemplo de reglas base */
body {
  font-family: 'Roboto', sans-serif;
  line-height: 1.5;
  color: #333;
}

h1, h2, h3, h4, h5, h6 {
  margin-top: 0;
  font-weight: 500;
}

a {
  color: #0066cc;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

Las reglas base utilizan selectores de elementos y establecen los fundamentos visuales de tu sitio.

2. Reglas de Layout

Las reglas de layout definen la estructura principal de la página y cómo se dividen las secciones mayores. Estas reglas controlan la disposición de los elementos principales como cabeceras, barras laterales, contenido principal y pies de página.

En SMACSS, se recomienda usar el prefijo l- o layout- para identificar estas clases:

/* Ejemplo de reglas de layout */
.l-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}

.l-header {
  height: 60px;
  position: sticky;
  top: 0;
  z-index: 100;
}

.l-sidebar {
  width: 25%;
  float: left;
}

.l-main {
  width: 75%;
  float: right;
}

.l-footer {
  clear: both;
  padding: 20px 0;
}

En HTML:

<div class="l-container">
  <header class="l-header">
    <!-- Contenido del encabezado -->
  </header>
  
  <aside class="l-sidebar">
    <!-- Contenido de la barra lateral -->
  </aside>
  
  <main class="l-main">
    <!-- Contenido principal -->
  </main>
  
  <footer class="l-footer">
    <!-- Contenido del pie de página -->
  </footer>
</div>

3. Reglas de Módulo

Los módulos son componentes de interfaz reutilizables e independientes. Representan unidades discretas de funcionalidad como botones, tarjetas, formularios, galerías, etc. La mayoría del CSS que escribimos entra en esta categoría.

Los módulos deben ser independientes del contexto y funcionar en cualquier parte de la aplicación:

/* Ejemplo de reglas de módulo */
.card {
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.card-header {
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.card-body {
  padding: 16px;
}

.btn {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  font-weight: 500;
}

.btn-primary {
  background-color: #0066cc;
  color: white;
}

Observa que los submódulos (elementos secundarios) utilizan el nombre del módulo como prefijo, separado por un guion (no doble guion bajo como en BEM).

4. Reglas de Estado

Las reglas de estado definen cómo se ven los módulos o layouts en diferentes estados: oculto/visible, activo/inactivo, expandido/colapsado, etc. Estas reglas suelen aplicarse temporalmente mediante JavaScript.

En SMACSS, se recomienda usar el prefijo is- o has- para estas clases:

/* Ejemplo de reglas de estado */
.is-hidden {
  display: none;
}

.is-active {
  font-weight: bold;
  color: #0066cc;
}

.is-disabled {
  opacity: 0.5;
  pointer-events: none;
}

.has-error {
  border-color: #ff3333;
}

Estas clases se aplican y eliminan dinámicamente:

<nav class="nav">
  <a href="#" class="nav-item is-active">Inicio</a>
  <a href="#" class="nav-item">Productos</a>
  <a href="#" class="nav-item">Contacto</a>
</nav>

<input type="text" class="form-input has-error">

5. Reglas de Tema

Las reglas de tema definen variaciones visuales alternativas para módulos o layouts. Esta categoría es opcional y más común en aplicaciones que permiten cambiar entre temas (modo claro/oscuro, diferentes marcas, etc.).

/* Ejemplo de reglas de tema */
.theme-dark {
  background-color: #222;
  color: #eee;
}

.theme-dark .card {
  background-color: #333;
  border-color: #444;
}

.theme-corporate .btn-primary {
  background-color: #00457c;
}

Convenciones de nomenclatura en SMACSS

SMACSS propone estas convenciones para nombrar clases:

  • Layout: Prefijo l- o layout- (ej. l-header, l-sidebar)
  • Módulos: Nombre del módulo (ej. card, nav, btn)
  • Submódulos: Nombre del módulo + - + elemento (ej. card-header, nav-item)
  • Estados: Prefijo is- o has- (ej. is-active, has-error)
  • Temas: Prefijo theme- (ej. theme-dark, theme-corporate)

Esta nomenclatura ayuda a identificar rápidamente la función de cada clase en nuestro código.

Organización de archivos según SMACSS

Una de las ventajas de SMACSS es que propone una estructura clara para organizar nuestros archivos CSS:

css/
├── base/
│   ├── reset.css
│   ├── typography.css
│   └── base.css
├── layout/
│   ├── grid.css
│   ├── header.css
│   ├── sidebar.css
│   └── footer.css
├── modules/
│   ├── buttons.css
│   ├── cards.css
│   ├── forms.css
│   └── navigation.css
├── states/
│   └── states.css
├── themes/
│   ├── dark.css
│   └── corporate.css
└── main.css (importa todos los archivos)

Esta estructura facilita encontrar y mantener el código, especialmente en proyectos grandes.

Reglas de especificidad en SMACSS

SMACSS recomienda mantener una baja especificidad en los selectores para facilitar la sobrescritura cuando sea necesario:

  • Reglas base: Usar selectores de elementos (body, a, h1)
  • Layout: Usar clases únicas (.l-header, .l-sidebar)
  • Módulos: Usar clases únicas (.card, .btn)
  • Submódulos: Usar clases únicas o selectores descendentes simples (.card-header, .card .title)
  • Estados: Usar clases con !important cuando sea necesario (.is-hidden { display: none !important; })

Ejemplo práctico de SMACSS

Veamos un ejemplo completo de cómo aplicar SMACSS a un componente de navegación:

<header class="l-header">
  <nav class="nav">
    <ul class="nav-list">
      <li class="nav-item">
        <a href="#" class="nav-link is-active">Inicio</a>
      </li>
      <li class="nav-item">
        <a href="#" class="nav-link">Productos</a>
      </li>
      <li class="nav-item">
        <a href="#" class="nav-link is-disabled">Servicios</a>
      </li>
    </ul>
  </nav>
</header>

Y el CSS correspondiente, organizado según SMACSS:

/* Layout (archivo: layout/header.css) */
.l-header {
  height: 60px;
  background-color: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Módulo (archivo: modules/navigation.css) */
.nav {
  height: 100%;
  display: flex;
  align-items: center;
}

.nav-list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-item {
  margin-right: 20px;
}

.nav-link {
  color: #333;
  text-decoration: none;
  padding: 5px 0;
  position: relative;
}

.nav-link:hover {
  color: #0066cc;
}

/* Estados (archivo: states/states.css) */
.nav-link.is-active {
  color: #0066cc;
}

.nav-link.is-active::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: #0066cc;
}

.nav-link.is-disabled {
  color: #999;
  pointer-events: none;
}

/* Tema (archivo: themes/dark.css) */
.theme-dark .l-header {
  background-color: #222;
}

.theme-dark .nav-link {
  color: #eee;
}

.theme-dark .nav-link.is-active {
  color: #66aaff;
}

.theme-dark .nav-link.is-active::after {
  background-color: #66aaff;
}

Ventajas de utilizar SMACSS

  • Organización clara: La categorización facilita saber dónde colocar cada regla CSS.

  • Escalabilidad: La estructura modular permite que el proyecto crezca de manera ordenada.

  • Mantenibilidad: Es más fácil encontrar y modificar estilos específicos.

  • Reutilización: Los módulos independientes pueden usarse en diferentes contextos.

  • Colaboración: Los equipos pueden trabajar en diferentes categorías sin conflictos.

Comparación con otras metodologías

SMACSS se diferencia de otras metodologías en su enfoque de categorización:

  • BEM se centra en la nomenclatura de clases para reflejar la estructura del DOM.
  • OOCSS se enfoca en separar estructura y apariencia para la reutilización.
  • SMACSS se enfoca en categorizar las reglas CSS según su función y alcance.

En la práctica, muchos desarrolladores combinan elementos de estas metodologías:

/* Combinando SMACSS y BEM */
.l-header {} /* Layout (SMACSS) */
.card {} /* Módulo (SMACSS) */
.card__title {} /* Elemento (BEM) */
.card--featured {} /* Modificador (BEM) */
.is-hidden {} /* Estado (SMACSS) */

Implementación gradual de SMACSS

Una ventaja de SMACSS es que puede implementarse gradualmente en proyectos existentes:

  1. Comienza organizando tus archivos CSS según las categorías SMACSS
  2. Aplica los prefijos de nomenclatura a las nuevas clases que crees
  3. Refactoriza gradualmente el código existente cuando sea necesario

Este enfoque permite mejorar la organización sin necesidad de reescribir todo el CSS de una vez.

SMACSS proporciona un marco conceptual para organizar nuestro CSS de manera lógica y escalable. Al categorizar nuestras reglas según su función y alcance, podemos crear una estructura más mantenible que facilita el desarrollo y la colaboración en proyectos de cualquier tamaño.

Atomic CSS y enfoque utility-first

El enfoque Atomic CSS representa un cambio de paradigma en la forma de escribir estilos CSS. A diferencia de las metodologías anteriores que se centran en componentes y objetos, Atomic CSS adopta una filosofía minimalista basada en clases de utilidad pequeñas y de propósito único.

Esta metodología, también conocida como CSS funcional o utility-first, se basa en crear pequeñas clases CSS que realizan una única tarea específica. Cada clase aplica una sola propiedad CSS (o un conjunto muy limitado de propiedades relacionadas), lo que permite construir interfaces combinando estas "utilidades atómicas".

Principios del enfoque Atomic CSS

El Atomic CSS se fundamenta en estos principios clave:

  • Clases de utilidad de propósito único: Cada clase CSS hace una sola cosa y la hace bien.
  • Nombres predecibles: Las clases siguen patrones consistentes que reflejan la propiedad CSS que aplican.
  • Composición sobre herencia: Se construyen interfaces componiendo múltiples clases pequeñas en lugar de heredar estilos de clases más grandes.
  • Reutilización máxima: Las mismas clases se utilizan en toda la aplicación, reduciendo la duplicación de código.

Estructura de clases en Atomic CSS

Las clases en Atomic CSS suelen seguir una convención de nomenclatura que refleja la propiedad CSS y su valor:

/* Ejemplos de clases atómicas */
.m-0 { margin: 0; }
.mt-10 { margin-top: 10px; }
.p-20 { padding: 20px; }
.flex { display: flex; }
.justify-between { justify-content: space-between; }
.text-center { text-align: center; }
.bg-blue { background-color: #0066cc; }
.text-white { color: white; }
.rounded { border-radius: 4px; }
.shadow { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); }

Estas clases se combinan en el HTML para construir la interfaz:

<div class="flex justify-between p-20 bg-blue text-white rounded shadow">
  <h2 class="m-0">Título del panel</h2>
  <button class="bg-white text-blue p-10 rounded">Acción</button>
</div>

Frameworks populares de Atomic CSS

Existen varios frameworks que implementan el enfoque Atomic CSS:

  • Tailwind CSS: Probablemente el más popular actualmente, ofrece un sistema completo de utilidades predefinidas.
  • Tachyons: Uno de los pioneros del enfoque utility-first.
  • Basscss: Framework minimalista con clases de utilidad para diseño rápido.

Veamos un ejemplo usando la sintaxis de Tailwind CSS, que ha popularizado enormemente este enfoque:

<div class="flex items-center justify-between p-6 bg-blue-600 text-white rounded-lg shadow-md">
  <div>
    <h3 class="text-xl font-bold">Notificación importante</h3>
    <p class="mt-1 text-blue-100">Esta alerta requiere tu atención inmediata.</p>
  </div>
  <button class="px-4 py-2 bg-white text-blue-600 font-semibold rounded-md hover:bg-blue-50">
    Entendido
  </button>
</div>

Ventajas del enfoque Atomic CSS

  • Menos CSS total: Al reutilizar las mismas clases en toda la aplicación, el tamaño total del CSS se reduce significativamente.
/* En lugar de esto (enfoque tradicional) */
.header-button { padding: 10px 20px; background-color: blue; color: white; border-radius: 4px; }
.sidebar-button { padding: 10px 20px; background-color: green; color: white; border-radius: 4px; }
.footer-button { padding: 10px 20px; background-color: gray; color: white; border-radius: 4px; }

/* Usamos esto (enfoque atomic) */
.p-10-20 { padding: 10px 20px; }
.bg-blue { background-color: blue; }
.bg-green { background-color: green; }
.bg-gray { background-color: gray; }
.text-white { color: white; }
.rounded-4 { border-radius: 4px; }
  • Desarrollo más rápido: No es necesario crear y nombrar nuevas clases CSS para cada componente.

  • Consistencia de diseño: Al usar un conjunto limitado de valores predefinidos (como espaciados, colores, tamaños), se mantiene la consistencia visual.

  • Cambios más seguros: Las clases atómicas tienen un alcance muy limitado, por lo que es menos probable que los cambios tengan efectos secundarios inesperados.

  • Menos decisiones de nomenclatura: No hay que pensar en nombres creativos para componentes, lo que elimina una carga cognitiva.

Implementación práctica

Para implementar Atomic CSS en un proyecto, podemos seguir estos enfoques:

1. Crear nuestro propio sistema de utilidades

Podemos definir nuestras propias clases atómicas basadas en el sistema de diseño:

/* Espaciado */
.m-0 { margin: 0; }
.m-1 { margin: 0.25rem; }
.m-2 { margin: 0.5rem; }
.m-4 { margin: 1rem; }
.m-8 { margin: 2rem; }
/* Y así sucesivamente para mt, mb, ml, mr, p, pt, etc. */

/* Colores */
.bg-primary { background-color: #0066cc; }
.bg-secondary { background-color: #6c757d; }
.bg-success { background-color: #28a745; }
.text-primary { color: #0066cc; }
.text-secondary { color: #6c757d; }
/* Y así sucesivamente */

/* Tipografía */
.text-xs { font-size: 0.75rem; }
.text-sm { font-size: 0.875rem; }
.text-base { font-size: 1rem; }
.text-lg { font-size: 1.125rem; }
.font-bold { font-weight: 700; }
.text-center { text-align: center; }
/* Y así sucesivamente */

/* Layout */
.flex { display: flex; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
/* Y así sucesivamente */

2. Usar un framework existente

Alternativamente, podemos usar un framework como Tailwind CSS, que proporciona un sistema completo de utilidades:

<!-- Ejemplo con Tailwind CSS -->
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
  <div class="md:flex">
    <div class="md:shrink-0">
      <img class="h-48 w-full object-cover md:h-full md:w-48" src="imagen.jpg" alt="Imagen">
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">Categoría</div>
      <a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">Título del artículo</a>
      <p class="mt-2 text-slate-500">Descripción breve del contenido que puede ocupar varias líneas...</p>
    </div>
  </div>
</div>

Estrategias para mantener el código limpio

Aunque Atomic CSS puede resultar en HTML con muchas clases, existen estrategias para mantener el código organizado:

Componentes abstractos

Podemos crear componentes reutilizables que encapsulen conjuntos de utilidades:

// Ejemplo en React con Tailwind CSS
function Button({ children, variant = 'primary' }) {
  const baseClasses = "px-4 py-2 rounded font-semibold";
  
  const variantClasses = {
    primary: "bg-blue-600 text-white hover:bg-blue-700",
    secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300"
  };
  
  return (
    <button className={`${baseClasses} ${variantClasses[variant]}`}>
      {children}
    </button>
  );
}

// Uso
<Button>Guardar cambios</Button>
<Button variant="secondary">Cancelar</Button>

Uso de directivas en preprocesadores

Con Tailwind y otros frameworks, podemos usar directivas para aplicar conjuntos de utilidades:

/* En un archivo CSS con directivas de Tailwind */
.card {
  @apply p-6 bg-white rounded-lg shadow-md;
}

.card-title {
  @apply text-xl font-bold text-gray-800;
}

.card-content {
  @apply mt-2 text-gray-600;
}
<!-- Uso en HTML -->
<div class="card">
  <h3 class="card-title">Título de la tarjeta</h3>
  <p class="card-content">Contenido de la tarjeta...</p>
</div>

Atomic CSS vs. otras metodologías

El enfoque Atomic CSS difiere significativamente de las metodologías anteriores:

  • BEM organiza el CSS por componentes con una nomenclatura específica.
  • OOCSS separa estructura y apariencia para reutilización.
  • SMACSS categoriza el CSS por función y alcance.
  • Atomic CSS descompone los estilos en clases de utilidad mínimas.

Comparemos cómo se vería un mismo componente con diferentes enfoques:

Enfoque BEM:

<div class="card card--featured">
  <h3 class="card__title">Título</h3>
  <p class="card__content">Contenido</p>
  <button class="card__button">Acción</button>
</div>
.card {
  padding: 20px;
  border-radius: 4px;
  background-color: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.card--featured {
  border-left: 4px solid blue;
}

.card__title {
  font-size: 18px;
  font-weight: bold;
  margin-top: 0;
}

.card__content {
  color: #666;
  margin: 10px 0;
}

.card__button {
  padding: 8px 16px;
  background-color: blue;
  color: white;
  border-radius: 4px;
  border: none;
}

Enfoque Atomic CSS:

<div class="p-5 bg-white rounded shadow-sm border-l-4 border-blue">
  <h3 class="text-lg font-bold m-0">Título</h3>
  <p class="text-gray-600 my-2">Contenido</p>
  <button class="px-4 py-2 bg-blue text-white rounded border-0">Acción</button>
</div>
/* Estas clases estarían predefinidas en tu sistema de utilidades */
.p-5 { padding: 1.25rem; }
.bg-white { background-color: white; }
.rounded { border-radius: 0.25rem; }
.shadow-sm { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); }
.border-l-4 { border-left-width: 4px; }
.border-blue { border-color: blue; }
.text-lg { font-size: 1.125rem; }
.font-bold { font-weight: 700; }
.m-0 { margin: 0; }
.text-gray-600 { color: #666; }
.my-2 { margin-top: 0.5rem; margin-bottom: 0.5rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.bg-blue { background-color: blue; }
.text-white { color: white; }
.border-0 { border: none; }

Consideraciones y posibles desventajas

El enfoque Atomic CSS no está exento de críticas:

  • HTML más verboso: El HTML puede llenarse de muchas clases, lo que algunos consideran menos legible.

  • Curva de aprendizaje: Es necesario familiarizarse con todas las clases de utilidad disponibles.

  • Separación de preocupaciones: Algunos argumentan que mezcla demasiado la presentación con el marcado.

  • Personalización: Para proyectos con diseños muy personalizados, puede ser necesario extender constantemente el sistema de utilidades.

Cuándo usar Atomic CSS

El enfoque Atomic CSS es especialmente adecuado para:

  • Proyectos que priorizan la velocidad de desarrollo
  • Equipos que necesitan mantener consistencia visual
  • Aplicaciones con muchos componentes de interfaz similares
  • Proyectos donde el rendimiento y el tamaño del CSS son críticos

Puede ser menos adecuado para:

  • Sitios con diseños altamente personalizados y únicos
  • Equipos que prefieren una separación estricta entre HTML y CSS
  • Proyectos pequeños donde la sobrecarga de aprender un sistema de utilidades no se justifica

Ejemplo de implementación progresiva

Una estrategia común es adoptar Atomic CSS gradualmente, combinándolo con otras metodologías:

<!-- Combinando BEM para la estructura principal con utilidades para ajustes específicos -->
<div class="card p-0 mb-4">
  <div class="card__header flex justify-between items-center">
    <h3 class="card__title text-lg">Título</h3>
    <span class="badge bg-green text-white">Nuevo</span>
  </div>
  <div class="card__body">
    <p class="text-gray-600">Contenido</p>
  </div>
</div>

Este enfoque híbrido permite aprovechar las ventajas de ambos mundos: la estructura semántica de BEM con la flexibilidad de las utilidades atómicas.

Optimización para producción

Una preocupación común con Atomic CSS es el tamaño del archivo CSS. Sin embargo, con las herramientas modernas, esto se puede optimizar:

  • Purge CSS: Elimina las clases no utilizadas del CSS final.
  • Minificación: Reduce el tamaño del archivo eliminando espacios y caracteres innecesarios.
  • Compresión HTTP: Reduce aún más el tamaño de transferencia.

Con Tailwind CSS, por ejemplo, un proyecto típico puede terminar con un archivo CSS de producción de solo 10-20KB después de la purga y minificación, a pesar de tener miles de clases de utilidad disponibles durante el desarrollo.

El enfoque Atomic CSS representa un cambio radical en cómo pensamos sobre el CSS, priorizando la composición de pequeñas utilidades sobre la creación de componentes estilizados. Aunque puede parecer contraintuitivo al principio, muchos equipos han encontrado que este enfoque les permite desarrollar interfaces más rápidamente y mantener bases de código CSS más pequeñas y manejables a largo plazo.

Aprende CSS online

Otros ejercicios de programación de CSS

Evalúa tus conocimientos de esta lección Metodologías de escritura en CSS con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de CSS

Accede a todas las lecciones de CSS y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Css

CSS

Introducción Y Entorno

Entorno Para Desarrollar Css

CSS

Introducción Y Entorno

Sintaxis

CSS

Sintaxis De Selectores Y Propiedades

Selectores Básicos

CSS

Sintaxis De Selectores Y Propiedades

Herencia Y Cascada

CSS

Sintaxis De Selectores Y Propiedades

Pseudo-clases Y Pseudo-elementos

CSS

Sintaxis De Selectores Y Propiedades

Colores En Css

CSS

Sintaxis De Selectores Y Propiedades

Unidades De Medida

CSS

Sintaxis De Selectores Y Propiedades

Especificidad

CSS

Sintaxis De Selectores Y Propiedades

Estilos De Fuente

CSS

Estilización De Texto Y Fondo

Propiedades De Texto

CSS

Estilización De Texto Y Fondo

Sombras En Texto Y Cajas

CSS

Estilización De Texto Y Fondo

Propiedades De Fondo

CSS

Estilización De Texto Y Fondo

Fuentes Web

CSS

Estilización De Texto Y Fondo

Efectos De Texto: Gradientes, Recortes

CSS

Estilización De Texto Y Fondo

Tipografía Avanzada

CSS

Estilización De Texto Y Fondo

Modelo De Caja

CSS

Modelo Caja

Propiedades De Posicionamiento

CSS

Modelo Caja

Propiedad 'Display'

CSS

Modelo Caja

Elementos 'Float' Y 'Clear'

CSS

Modelo Caja

Rellenos Y Márgenes

CSS

Modelo Caja

Bordes Y Contornos

CSS

Modelo Caja

Absolute, Fixed, Sticky Y Z-index

CSS

Posicionamiento

Flexbox Para Crear Layouts Y Estructuras

CSS

Flexbox

Css Grid Para Crear Layouts Y Estructuras

CSS

Flexbox

Propiedades Del Contenedor Flex

CSS

Flexbox

Propiedades De Los Items Flex

CSS

Flexbox

Columnas Y Filas En Grid

CSS

Css Grid

Espaciado Y Alineación

CSS

Css Grid

Tipografía Responsive

CSS

Diseño Responsive

Fundamentos Del Diseño Responsive

CSS

Diseño Responsive

Imágenes Responsive

CSS

Diseño Responsive

Funciones Matemáticas

CSS

Variables Y Funciones Css

Transformaciones 2d

CSS

Transformación, Transición, Animación

Transformaciones 3d

CSS

Transformación, Transición, Animación

Animaciones

CSS

Transformación, Transición, Animación

Transiciones

CSS

Transformación, Transición, Animación

Css Para Formularios

CSS

Css Avanzado

Accesibilidad Web Con Css

CSS

Css Avanzado

Container Queries

CSS

Css Avanzado

Selectores Avanzados

CSS

Css Avanzado

Animaciones Y Transiciones

CSS

Técnicas Modernas Y Metodologías

Variables En Css

CSS

Técnicas Modernas Y Metodologías

Diseño Responsive Con Media Queries

CSS

Técnicas Modernas Y Metodologías

Metodologías De Escritura En Css

CSS

Técnicas Modernas Y Metodologías

Accede GRATIS a CSS y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender los principios y estructura de la metodología BEM para organizar clases CSS.
  • Aprender a aplicar el enfoque OOCSS para separar estructura y apariencia y crear objetos reutilizables.
  • Conocer la organización y categorización de reglas CSS según SMACSS para mantener código escalable.
  • Entender el paradigma Atomic CSS y el enfoque utility-first para construir interfaces con clases atómicas.
  • Comparar ventajas, desventajas y casos de uso de cada metodología para elegir la más adecuada según el proyecto.