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ícatePrincipios 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:
- Identificar patrones repetitivos en nuestro diseño
- Abstraer estos patrones en clases reutilizables
- Separar estructura y apariencia en diferentes clases
- 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-
olayout-
(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-
ohas-
(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:
- Comienza organizando tus archivos CSS según las categorías SMACSS
- Aplica los prefijos de nomenclatura a las nuevas clases que crees
- 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.
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.
Propiedades de posicionamiento
Modelo de caja
Sombras en texto y cajas
Sintaxis básica
Estilos de fuente
Animaciones y transiciones
Proyecto CSS Landing page simple
Propiedades de texto
Metodologías BEM, SMACSS, OOCSS
Herencia y cascada
Reto fondos background CSS
Reto sintaxis CSS
Flexbox en diseños modernos
Reto grid de columnas en CSS
Selectores avanzados
Reto formulario estilizado
Proyecto CSS crear una navbar
Reto selectores básicos CSS
Reto Flexbox Card
Propiedad 'display'
Variables en CSS
Grid en diseños de cuadrícula
Reto tema claro/oscuro con variables
Reto modelo caja CSS
Reto implementación de fuentes web
Diseño responsive con media queries
Reto unidades de medida
Sintaxis avanzada
Elementos 'float' y 'clear'
Pseudo-clases y pseudo-elementos
Reto componente responsive
Proyecto CSS Dashboard Responsive
Reto Flexbox Hero
Propiedades de fondo
Introducción a CSS
Reto propiedades texto
Modelo de caja
Selectores básicos
Reto especificidad y cascada
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
Introducción Y Entorno
Entorno Para Desarrollar Css
Introducción Y Entorno
Sintaxis
Sintaxis De Selectores Y Propiedades
Selectores Básicos
Sintaxis De Selectores Y Propiedades
Herencia Y Cascada
Sintaxis De Selectores Y Propiedades
Pseudo-clases Y Pseudo-elementos
Sintaxis De Selectores Y Propiedades
Colores En Css
Sintaxis De Selectores Y Propiedades
Unidades De Medida
Sintaxis De Selectores Y Propiedades
Especificidad
Sintaxis De Selectores Y Propiedades
Estilos De Fuente
Estilización De Texto Y Fondo
Propiedades De Texto
Estilización De Texto Y Fondo
Sombras En Texto Y Cajas
Estilización De Texto Y Fondo
Propiedades De Fondo
Estilización De Texto Y Fondo
Fuentes Web
Estilización De Texto Y Fondo
Efectos De Texto: Gradientes, Recortes
Estilización De Texto Y Fondo
Tipografía Avanzada
Estilización De Texto Y Fondo
Modelo De Caja
Modelo Caja
Propiedades De Posicionamiento
Modelo Caja
Propiedad 'Display'
Modelo Caja
Elementos 'Float' Y 'Clear'
Modelo Caja
Rellenos Y Márgenes
Modelo Caja
Bordes Y Contornos
Modelo Caja
Absolute, Fixed, Sticky Y Z-index
Posicionamiento
Flexbox Para Crear Layouts Y Estructuras
Flexbox
Css Grid Para Crear Layouts Y Estructuras
Flexbox
Propiedades Del Contenedor Flex
Flexbox
Propiedades De Los Items Flex
Flexbox
Columnas Y Filas En Grid
Css Grid
Espaciado Y Alineación
Css Grid
Tipografía Responsive
Diseño Responsive
Fundamentos Del Diseño Responsive
Diseño Responsive
Imágenes Responsive
Diseño Responsive
Funciones Matemáticas
Variables Y Funciones Css
Transformaciones 2d
Transformación, Transición, Animación
Transformaciones 3d
Transformación, Transición, Animación
Animaciones
Transformación, Transición, Animación
Transiciones
Transformación, Transición, Animación
Css Para Formularios
Css Avanzado
Accesibilidad Web Con Css
Css Avanzado
Container Queries
Css Avanzado
Selectores Avanzados
Css Avanzado
Animaciones Y Transiciones
Técnicas Modernas Y Metodologías
Variables En Css
Técnicas Modernas Y Metodologías
Diseño Responsive Con Media Queries
Técnicas Modernas Y Metodologías
Metodologías De Escritura En Css
Técnicas Modernas Y Metodologías
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.