Webgae

Tailwind CSS vs CSS Modules: ¿Cuál elegir para tu proyecto?

Por WPE
Tailwind CSS vs CSS Modules: ¿Cuál elegir para tu proyecto?

Cuando desarrollamos aplicaciones web modernas, una de las decisiones más importantes es cómo gestionaremos los estilos. Dos enfoques populares que han ganado tracción en los últimos años son Tailwind CSS y CSS Modules. Aunque ambos buscan resolver problemas del CSS tradicional, lo hacen de maneras completamente diferentes.

¿Qué es Tailwind CSS?

Tailwind es un framework de CSS basado en utilidades (utility-first). En lugar de escribir clases semánticas personalizadas, utilizas clases pequeñas y específicas que aplican un único estilo. Por ejemplo, en vez de crear una clase .botón-principal, combinas clases como bg-blue-500 text-white px-4 py-2 rounded.

La filosofía de Tailwind es que puedes construir cualquier diseño directamente en tu HTML sin salir de él. Viene con un sistema de diseño predefinido que incluye espaciados consistentes, paletas de colores, tipografías y breakpoints para diseño responsivo.

Ejemplo práctico:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Enviar
</button>

¿Qué son los CSS Modules?

CSS Modules es un sistema que transforma tus archivos CSS regulares para que las clases tengan alcance local por defecto. Escribes CSS normal en un archivo, lo importas en tu componente JavaScript, y automáticamente se generan nombres de clase únicos para evitar conflictos.

Con CSS Modules sigues el enfoque tradicional de separar estilos en archivos CSS, pero sin preocuparte de que tus clases colisionen con otras partes de la aplicación.

Ejemplo práctico:

/* Button.module.css */
.button {
  background-color: #3b82f6;
  color: white;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
}

.button:hover {
  background-color: #2563eb;
}
import styles from './Button.module.css';

<button className={styles.button}>Enviar</button>

Comparación directa

Velocidad de desarrollo: Tailwind permite prototipar extremadamente rápido una vez que conoces las clases. No necesitas cambiar entre archivos. CSS Modules requiere escribir más código pero resulta más familiar para quienes vienen del CSS tradicional.

Curva de aprendizaje: CSS Modules es más fácil de adoptar porque usas CSS estándar. Tailwind tiene una curva de aprendizaje inicial mientras memorizas las clases utilitarias.

Mantenibilidad: Con CSS Modules, los estilos están organizados en archivos separados, lo que algunos equipos encuentran más limpio. Tailwind puede hacer que tu HTML se vea saturado, aunque herramientas como @apply permiten extraer patrones comunes.

Tamaño del bundle: Tailwind genera archivos CSS muy pequeños en producción gracias al tree-shaking que elimina clases no utilizadas. CSS Modules depende de cuánto CSS escribas.

Consistencia del diseño: Tailwind impone un sistema de diseño que naturalmente crea interfaces consistentes. CSS Modules te da libertad total, lo que puede llevar a inconsistencias sin disciplina.

¿Cuál te conviene?

Elige Tailwind si:

  • Trabajas en un equipo pequeño o solo
  • Priorizas la velocidad de desarrollo
  • Quieres un sistema de diseño incorporado
  • Construyes prototipos o MVPs rápidamente
  • Prefieres ver todos los estilos en el mismo lugar que tu markup

Elige CSS Modules si:

  • Tu equipo prefiere separar markup y estilos
  • Tienes diseñadores que trabajan directamente en CSS
  • Necesitas lógica CSS compleja (animaciones elaboradas, pseudo-elementos complicados)
  • Migras un proyecto existente con mucho CSS
  • Prefieres mantener habilidades de CSS tradicional

La tercera opción

Vale mencionar que no son mutuamente excluyentes. Muchos proyectos usan Tailwind para la mayoría de estilos utilitarios y CSS Modules para componentes específicos que requieren estilos más complejos. Esta combinación puede darte lo mejor de ambos mundos.

En última instancia, ambas herramientas son excelentes y la elección depende más de las preferencias de tu equipo y las necesidades específicas de tu proyecto que de una superioridad técnica objetiva.

Cómo manejar paletas de colores en Tailwind CSS

Tailwind ofrece un sistema robusto y flexible para gestionar colores. Te explico las diferentes formas de trabajar con paletas, desde usar los colores predeterminados hasta crear tu propio sistema personalizado.

Colores predeterminados de Tailwind

Tailwind incluye una paleta extensa con colores organizados en escalas del 50 al 950. Cada color tiene variantes de claridad que facilitan mantener consistencia:

<div class="bg-blue-500">Azul estándar</div>
<div class="bg-blue-700">Azul más oscuro</div>
<div class="bg-blue-300">Azul más claro</div>

Los colores disponibles incluyen: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink y rose.

Personalizar colores en tailwind.config.js

Para adaptar Tailwind a tu marca o diseño, puedes personalizar los colores en el archivo de configuración:

Extender la paleta (mantener los colores por defecto)

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        'brand': {
          50: '#f0f9ff',
          100: '#e0f2fe',
          500: '#0ea5e9',
          900: '#0c4a6e',
        },
        'primary': '#3b82f6',
        'secondary': '#8b5cf6',
        'accent': '#f59e0b',
      }
    }
  }
}

Ahora puedes usar bg-brand-500, text-primary, etc.

Reemplazar completamente la paleta

module.exports = {
  theme: {
    colors: {
      // Esto elimina TODOS los colores por defecto
      white: '#ffffff',
      black: '#000000',
      primary: {
        light: '#93c5fd',
        DEFAULT: '#3b82f6',
        dark: '#1e40af',
      },
      secondary: {
        light: '#c4b5fd',
        DEFAULT: '#8b5cf6',
        dark: '#5b21b6',
      }
    }
  }
}

Usar variables CSS para temas dinámicos

Una técnica avanzada es combinar Tailwind con variables CSS, perfecto para temas claros/oscuros:

/* globals.css */
:root {
  --color-primary: 59 130 246; /* RGB sin 'rgb()' */
  --color-secondary: 139 92 246;
  --color-background: 255 255 255;
  --color-text: 0 0 0;
}

[data-theme="dark"] {
  --color-primary: 96 165 250;
  --color-secondary: 167 139 250;
  --color-background: 15 23 42;
  --color-text: 248 250 252;
}
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: 'rgb(var(--color-primary) / <alpha-value>)',
        secondary: 'rgb(var(--color-secondary) / <alpha-value>)',
        background: 'rgb(var(--color-background) / <alpha-value>)',
        text: 'rgb(var(--color-text) / <alpha-value>)',
      }
    }
  }
}

Ahora puedes cambiar el tema con JavaScript:

document.documentElement.setAttribute('data-theme', 'dark');

Usar transparencias (opacity)

Tailwind permite ajustar la opacidad de cualquier color:

<div class="bg-blue-500/50">50% de opacidad</div>
<div class="bg-blue-500/75">75% de opacidad</div>
<div class="text-red-600/30">Texto semi-transparente</div>

Importar colores de otras librerías

Puedes usar colores de librerías populares como Open Color o Radix:

const colors = require('tailwindcss/colors');

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: colors.blue,
        secondary: colors.purple,
        danger: colors.red,
        success: colors.green,
      }
    }
  }
}

Generar escalas de colores automáticamente

Si tienes un color base y quieres generar una escala completa, puedes usar herramientas como el generador de paletas de Tailwind o librerías como chroma-js:

const chroma = require('chroma-js');

const generateScale = (color) => {
  return {
    50: chroma(color).brighten(2.5).hex(),
    100: chroma(color).brighten(2).hex(),
    200: chroma(color).brighten(1.5).hex(),
    300: chroma(color).brighten(1).hex(),
    400: chroma(color).brighten(0.5).hex(),
    500: color,
    600: chroma(color).darken(0.5).hex(),
    700: chroma(color).darken(1).hex(),
    800: chroma(color).darken(1.5).hex(),
    900: chroma(color).darken(2).hex(),
  };
};

module.exports = {
  theme: {
    extend: {
      colors: {
        brand: generateScale('#3b82f6'),
      }
    }
  }
}

Modo oscuro (Dark Mode)

Tailwind facilita crear paletas para modo oscuro:

<div class="bg-white dark:bg-slate-900">
  <h1 class="text-gray-900 dark:text-white">Título</h1>
  <p class="text-gray-600 dark:text-gray-300">Contenido</p>
</div>

Configura cómo se activa el modo oscuro:

module.exports = {
  darkMode: 'class', // o 'media' para usar preferencias del sistema
}

Consejos prácticos

Define colores semánticos: En lugar de usar bg-blue-500 directamente, crea alias como primary, secondary, danger. Esto facilita cambios globales.

Mantén consistencia: Limita tu paleta a 2-3 colores principales con sus variantes. Demasiados colores crean interfaces confusas.

Usa herramientas: Sitios como Coolors, Adobe Color o el Tailwind Color Palette Generator te ayudan a crear paletas armoniosas.

Documenta tu paleta: Mantén un storybook o página de referencia mostrando todos tus colores y cuándo usarlos.

Con estas técnicas puedes crear sistemas de colores profesionales, escalables y fáciles de mantener en tus proyectos con Tailwind.

Cómo manejar paletas de colores con CSS Modules


Cómo manejar paletas de colores con CSS Modules

CSS Modules ofrece un enfoque más tradicional pero igualmente efectivo para gestionar paletas de colores. A diferencia de Tailwind, tienes control total sobre cómo estructuras y utilizas tus colores. Te muestro las mejores prácticas y técnicas.

Variables CSS: La base moderna

La forma más efectiva de manejar colores en CSS Modules es usar variables CSS (custom properties). Esto te da flexibilidad y la capacidad de crear temas dinámicos.

Crear un archivo de variables globales

/* styles/colors.css o globals.css */
:root {
  /* Colores primarios */
  --color-primary-50: #eff6ff;
  --color-primary-100: #dbeafe;
  --color-primary-500: #3b82f6;
  --color-primary-700: #1d4ed8;
  --color-primary-900: #1e3a8a;
  
  /* Colores secundarios */
  --color-secondary-500: #8b5cf6;
  --color-secondary-700: #6d28d9;
  
  /* Colores semánticos */
  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #3b82f6;
  
  /* Colores neutros */
  --color-gray-50: #f9fafb;
  --color-gray-100: #f3f4f6;
  --color-gray-500: #6b7280;
  --color-gray-900: #111827;
  
  /* Colores de superficie */
  --color-background: #ffffff;
  --color-surface: #f9fafb;
  --color-text-primary: #111827;
  --color-text-secondary: #6b7280;
}

Usar las variables en tus módulos

/* Button.module.css */
.button {
  padding: 0.75rem 1.5rem;
  border-radius: 0.375rem;
  font-weight: 600;
  transition: all 0.2s;
}

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

.primary:hover {
  background-color: var(--color-primary-700);
}

.secondary {
  background-color: var(--color-secondary-500);
  color: white;
}

.secondary:hover {
  background-color: var(--color-secondary-700);
}

.outline {
  background-color: transparent;
  border: 2px solid var(--color-primary-500);
  color: var(--color-primary-500);
}

Organizar colores con archivos dedicados

Para proyectos grandes, organiza tus colores en archivos separados:

/* styles/tokens/colors.css */
:root {
  /* Colores de marca */
  --brand-blue: #3b82f6;
  --brand-purple: #8b5cf6;
  --brand-green: #10b981;
}

/* styles/tokens/semantic-colors.css */
:root {
  /* Mapeo semántico */
  --color-primary: var(--brand-blue);
  --color-secondary: var(--brand-purple);
  --color-success: var(--brand-green);
  
  /* Estados */
  --color-interactive: var(--color-primary);
  --color-interactive-hover: var(--brand-blue-dark);
  --color-disabled: var(--color-gray-300);
}

Sistema de temas (Light/Dark Mode)

Implementa temas cambiando los valores de las variables CSS:

/* themes.css */
:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f9fafb;
  --text-primary: #111827;
  --text-secondary: #6b7280;
  --border-color: #e5e7eb;
}

[data-theme="dark"] {
  --bg-primary: #1f2937;
  --bg-secondary: #111827;
  --text-primary: #f9fafb;
  --text-secondary: #d1d5db;
  --border-color: #374151;
}
/* Card.module.css */
.card {
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  padding: 1.5rem;
  border-radius: 0.5rem;
}

.cardTitle {
  color: var(--text-primary);
  font-size: 1.25rem;
  font-weight: 600;
}

.cardDescription {
  color: var(--text-secondary);
  margin-top: 0.5rem;
}

Para cambiar el tema con JavaScript:

// theme.js
export const setTheme = (theme) => {
  document.documentElement.setAttribute('data-theme', theme);
  localStorage.setItem('theme', theme);
};

export const getTheme = () => {
  return localStorage.getItem('theme') || 'light';
};

// Aplicar al cargar
document.documentElement.setAttribute('data-theme', getTheme());

Usar preprocesadores (SASS/SCSS)

Si usas SASS con CSS Modules, puedes aprovechar variables, mixins y funciones:

/* _colors.scss */
$colors: (
  'primary': (
    50: #eff6ff,
    100: #dbeafe,
    500: #3b82f6,
    700: #1d4ed8,
    900: #1e3a8a,
  ),
  'secondary': (
    500: #8b5cf6,
    700: #6d28d9,
  ),
  'gray': (
    50: #f9fafb,
    500: #6b7280,
    900: #111827,
  )
);

// Función helper para acceder a colores
@function color($name, $shade: 500) {
  @return map-get(map-get($colors, $name), $shade);
}

// Mixin para variantes de color
@mixin color-variant($name, $shade: 500) {
  background-color: color($name, $shade);
  
  &:hover {
    background-color: color($name, $shade + 200);
  }
}
/* Button.module.scss */
@import '../styles/colors';

.button {
  padding: 0.75rem 1.5rem;
  border-radius: 0.375rem;
  font-weight: 600;
  transition: all 0.2s;
  color: white;
}

.primary {
  @include color-variant('primary');
}

.secondary {
  @include color-variant('secondary');
}

.outline {
  background-color: transparent;
  border: 2px solid color('primary');
  color: color('primary');
  
  &:hover {
    background-color: color('primary', 50);
  }
}

Generar utilidades con JavaScript

Para proyectos que necesitan muchas variaciones, genera clases automáticamente:

// scripts/generate-color-utils.js
const fs = require('fs');

const colors = {
  primary: { 500: '#3b82f6', 700: '#1d4ed8' },
  secondary: { 500: '#8b5cf6', 700: '#6d28d9' },
  success: { 500: '#10b981', 700: '#059669' },
};

let css = '/* Generado automáticamente */\n\n';

Object.entries(colors).forEach(([name, shades]) => {
  Object.entries(shades).forEach(([shade, value]) => {
    css += `.bg-${name}-${shade} { background-color: ${value}; }\n`;
    css += `.text-${name}-${shade} { color: ${value}; }\n`;
    css += `.border-${name}-${shade} { border-color: ${value}; }\n\n`;
  });
});

fs.writeFileSync('styles/generated-colors.module.css', css);

Composición de estilos con colores

CSS Modules permite componer estilos elegantemente:

/* styles/base.module.css */
.textPrimary {
  color: var(--text-primary);
}

.textSecondary {
  color: var(--text-secondary);
}

.bgPrimary {
  background-color: var(--color-primary-500);
}
// Component.jsx
import baseStyles from './styles/base.module.css';
import styles from './Component.module.css';

function Component() {
  return (
    <div className={`${styles.container} ${baseStyles.bgPrimary}`}>
      <h1 className={baseStyles.textPrimary}>Título</h1>
      <p className={baseStyles.textSecondary}>Descripción</p>
    </div>
  );
}

TypeScript para type-safety

Si usas TypeScript, puedes tipar tus colores:

// types/colors.ts
export const colors = {
  primary: {
    50: '#eff6ff',
    500: '#3b82f6',
    900: '#1e3a8a',
  },
  secondary: {
    500: '#8b5cf6',
    700: '#6d28d9',
  },
} as const;

export type ColorName = keyof typeof colors;
export type ColorShade<T extends ColorName> = keyof typeof colors[T];

// Helper con types
export function getColor<T extends ColorName>(
  name: T,
  shade: ColorShade<T>
): string {
  return colors[name][shade];
}

Mejores prácticas

Centraliza tus colores: Define todos los colores en un solo lugar (o archivos organizados) para facilitar cambios globales.

Usa nombres semánticos: Prefiere --color-primary sobre --color-blue. Esto facilita rebrandings.

Crea escalas consistentes: Mantén escalas de 50-900 como Tailwind para tener opciones predecibles.

Documenta el uso: Crea una guía de estilos que muestre cuándo usar cada color.

Considera la accesibilidad: Verifica que tus combinaciones de colores tengan suficiente contraste (WCAG AA mínimo 4.5:1).

Usa fallbacks: Siempre proporciona valores de respaldo para navegadores antiguos:

.button {
  background-color: #3b82f6; /* fallback */
  background-color: var(--color-primary-500);
}

Con CSS Modules tienes control total sobre tu sistema de colores, desde la organización hasta la implementación, permitiéndote crear soluciones perfectamente adaptadas a las necesidades de tu proyecto.