Styling - Estilos en NextJS

NextJS soporta múltiples formas de dar estilo a tu aplicación. Cada una tiene sus ventajas y casos de uso ideales.

Las 3 opciones principales

1. CSS Modules

CSS tradicional con scope automático por componente.

// components/Button.tsx
import styles from './Button.module.css'

export default function Button({ children }) {
  return <button className={styles.button}>{children}</button>
}
/* components/Button.module.css */
.button {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
}

Ventajas:

  • CSS puro, nada nuevo que aprender
  • Scope automático (no hay conflictos de nombres)
  • Funciona sin JavaScript
  • Excelente performance
  • Zero runtime

Desventajas:

  • Más archivos para gestionar
  • No puedes usar valores de JavaScript directamente
  • Nombres de clases largos en proyectos grandes

Cuándo usar:

  • Proyectos con diseñadores que prefieren CSS
  • Cuando necesitas CSS puro sin dependencias
  • Aplicaciones donde el bundle size es crítico
  • Migración de proyectos CSS existentes

2. Tailwind CSS

Clases utilitarias que describes tu diseño directamente en el HTML.

// components/Button.tsx
export default function Button({ children }) {
  return (
    <button className="bg-blue-500 text-white px-5 py-2 rounded hover:bg-blue-600">
      {children}
    </button>
  )
}

Ventajas:

  • No necesitas nombrar clases
  • Diseño super rápido (no cambias entre archivos)
  • Purga automática de CSS no usado
  • Sistema de diseño consistente incluido
  • Mobile-first por defecto
  • Comunidad enorme

Desventajas:

  • HTML puede verse "sucio" con muchas clases
  • Curva de aprendizaje para memorizar clases
  • Requiere configuración inicial
  • Dificil reutilizar estilos complejos

Cuándo usar:

  • Proyectos nuevos desde cero
  • Desarrollo rápido y prototipado
  • Equipos que prefieren todo en un lugar
  • Cuando quieres un sistema de diseño listo

3. CSS-in-JS (Styled Components, Emotion)

CSS escrito en JavaScript con soporte para valores dinámicos.

// components/Button.tsx
'use client'

import styled from 'styled-components'

const StyledButton = styled.button`
  background-color: ${props => props.primary ? 'blue' : 'gray'};
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
  
  &:hover {
    opacity: 0.8;
  }
`

export default function Button({ children, primary }) {
  return <StyledButton primary={primary}>{children}</StyledButton>
}

Ventajas:

  • Estilos dinámicos basados en props
  • Todo en JavaScript (sin cambiar de archivo)
  • Soporte completo para temas
  • Auto-prefixing y optimizaciones
  • TypeScript support

Desventajas:

  • Runtime overhead (JS debe ejecutarse para generar CSS)
  • Bundle size más grande
  • Requiere 'use client' en NextJS 15
  • Performance puede ser problema en apps grandes
  • Más complejo de debuggear

Cuándo usar:

  • Componentes altamente dinámicos
  • Sistemas de temas complejos
  • Cuando necesitas estilos basados en estado
  • Migración desde React tradicional

Comparación lado a lado

Veamos el mismo botón con las 3 opciones:

CSS Modules

// Button.tsx
import styles from './Button.module.css'

export default function Button({ children, variant = 'primary' }) {
  return (
    <button className={`${styles.button} ${styles[variant]}`}>
      {children}
    </button>
  )
}
/* Button.module.css */
.button {
  padding: 10px 20px;
  border-radius: 5px;
  font-weight: 600;
  border: none;
  cursor: pointer;
}

.primary {
  background-color: #3b82f6;
  color: white;
}

.secondary {
  background-color: #6b7280;
  color: white;
}

Tailwind CSS

// Button.tsx
export default function Button({ children, variant = 'primary' }) {
  const styles = {
    primary: 'bg-blue-500 text-white hover:bg-blue-600',
    secondary: 'bg-gray-500 text-white hover:bg-gray-600',
  }
  
  return (
    <button className={`px-5 py-2 rounded font-semibold ${styles[variant]}`}>
      {children}
    </button>
  )
}

CSS-in-JS

// Button.tsx
'use client'

import styled from 'styled-components'

const StyledButton = styled.button`
  padding: 10px 20px;
  border-radius: 5px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  background-color: ${props => props.variant === 'primary' ? '#3b82f6' : '#6b7280'};
  color: white;
  
  &:hover {
    background-color: ${props => props.variant === 'primary' ? '#2563eb' : '#4b5563'};
  }
`

export default function Button({ children, variant = 'primary' }) {
  return <StyledButton variant={variant}>{children}</StyledButton>
}

Tabla comparativa

CaracterísticaCSS ModulesTailwind CSSCSS-in-JS
Performance⭐⭐⭐⭐⭐ Excelente⭐⭐⭐⭐⭐ Excelente⭐⭐⭐ Buena
Bundle Size⭐⭐⭐⭐⭐ Mínimo⭐⭐⭐⭐ Pequeño⭐⭐ Más grande
DX (Developer Experience)⭐⭐⭐ Buena⭐⭐⭐⭐⭐ Excelente⭐⭐⭐⭐ Muy buena
Curva de aprendizaje⭐⭐⭐⭐⭐ Fácil (CSS)⭐⭐⭐ Media⭐⭐⭐ Media
Estilos dinámicos⭐⭐ Limitado⭐⭐⭐ Bueno⭐⭐⭐⭐⭐ Excelente
TypeScript⭐⭐ Limitado⭐⭐⭐ Bueno⭐⭐⭐⭐⭐ Excelente
Ecosistema⭐⭐⭐⭐⭐ Estándar⭐⭐⭐⭐⭐ Enorme⭐⭐⭐⭐ Grande
Server Components✅ Compatible✅ Compatible⚠️ Requiere 'use client'
Setup✅ Incluido⚙️ Configuración⚙️ Configuración

¿Cuál elegir?

Elige CSS Modules si:

  • ✅ Tu equipo ya domina CSS
  • ✅ Necesitas máxima performance
  • ✅ Quieres la menor cantidad de dependencias
  • ✅ Tienes diseñadores que prefieren CSS tradicional
  • ✅ Migras de un proyecto CSS existente

Proyectos ideales:

  • Blogs y sitios de contenido
  • Landing pages simples
  • Aplicaciones donde cada KB cuenta
  • Proyectos con diseñadores CSS

Elige Tailwind CSS si:

  • ✅ Empiezas un proyecto desde cero
  • ✅ Quieres desarrollar rápido
  • ✅ Tu equipo prefiere todo en un archivo
  • ✅ Quieres un sistema de diseño consistente
  • ✅ Valoras la comunidad y plugins

Proyectos ideales:

  • SaaS y dashboards
  • E-commerce
  • Aplicaciones web modernas
  • Prototipos y MVPs
  • Casi cualquier proyecto NextJS nuevo

Elige CSS-in-JS si:

  • ✅ Necesitas estilos muy dinámicos
  • ✅ Tu aplicación tiene temas complejos
  • ✅ Todo tu equipo prefiere JavaScript
  • ✅ Vienes de React tradicional
  • ✅ Los estilos dependen mucho del estado

Proyectos ideales:

  • Aplicaciones con temas personalizables
  • Component libraries
  • Apps con estilos muy dinámicos
  • Cuando migras código React existente

Recomendación para NextJS 15

💡
Recomendación oficial

Vercel y el equipo de NextJS recomiendan Tailwind CSS para proyectos nuevos. Es la opción más balanceada entre performance, developer experience y ecosistema.

NextJS viene con soporte para Tailwind incluido en el template por defecto:

npx create-next-app@latest
# Selecciona "Yes" cuando pregunte por Tailwind CSS

Nuestra recomendación por experiencia:

Para la mayoría de proyectos: Tailwind CSS

Es la opción más popular en 2025 y tiene el mejor balance:

  • Performance excelente (purge automático)
  • Desarrollo rápido
  • Sistema de diseño incluido
  • Comunidad enorme
  • Funciona perfectamente con Server Components

Para proyectos específicos:

  • CSS Modules: Blogs, documentación, sitios estáticos
  • CSS-in-JS: Apps con temas complejos, component libraries

Combinar opciones

Puedes mezclar opciones en el mismo proyecto:

// La mayoría usa Tailwind
export default function Dashboard() {
  return (
    <div className="container mx-auto px-4">
      <h1 className="text-3xl font-bold">Dashboard</h1>
      
      {/* Componente específico con CSS Module */}
      <ComplexChart />
      
      {/* Componente dinámico con CSS-in-JS */}
      <ThemeToggle />
    </div>
  )
}

Patrón común:

  • 80% Tailwind para layouts y componentes simples
  • 15% CSS Modules para componentes complejos o reutilizables
  • 5% CSS-in-JS para componentes altamente dinámicos

Estilos globales

Todas las opciones pueden convivir con estilos globales:

/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* Estilos globales */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: var(--font-inter);
  line-height: 1.5;
}

/* Clases utilitarias custom */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
}
// app/layout.tsx
import './globals.css'

export default function RootLayout({ children }) {
  return (
    <html lang="es">
      <body>{children}</body>
    </html>
  )
}

Performance y optimización

CSS Modules y Tailwind

  • ✅ CSS se extrae en archivos .css separados
  • ✅ Cached por el navegador
  • ✅ No requiere JavaScript para funcionar
  • ✅ Critical CSS inline automático

CSS-in-JS

  • ⚠️ Requiere JavaScript para generar CSS
  • ⚠️ Más grande bundle size
  • ⚠️ Requiere 'use client' en NextJS 15
  • ✅ Pero permite estilos muy dinámicos

Tip de performance: Si tu componente no necesita ser interactivo, usa CSS Modules o Tailwind en vez de CSS-in-JS.

Migración entre opciones

De CSS tradicional a CSS Modules

Fácil: Solo renombra tus archivos .css a .module.css y cambia los imports.

De CSS a Tailwind

Más trabajo: Necesitas reescribir los estilos, pero hay herramientas que ayudan:

De CSS-in-JS a Tailwind

Requiere refactorización completa. Considera hacerlo gradualmente:

  1. Nuevos componentes en Tailwind
  2. Migra componentes existentes progresivamente
  3. Elimina CSS-in-JS cuando todos estén migrados

Herramientas y extensiones

Para cualquier opción:

  • PostCSS: Procesador de CSS (incluido en NextJS)
  • Autoprefixer: Prefijos automáticos (incluido)
  • CSS Minification: Automática en producción

Para Tailwind:

  • Tailwind CSS IntelliSense (VSCode)
  • Prettier Plugin Tailwind: Ordena clases automáticamente
  • Headless UI: Componentes sin estilos para Tailwind

Para CSS-in-JS:

  • styled-components VSCode extension: Syntax highlighting
  • vscode-styled-components: Autocompletado

Próximos pasos

Ahora que entiendes las opciones, profundiza en la que elegiste:

Resumen

Tres opciones principales:

  1. CSS Modules - CSS tradicional con scope
  2. Tailwind CSS - Clases utilitarias
  3. CSS-in-JS - Estilos en JavaScript

Nuestra recomendación:

  • Empezando nuevo: Tailwind CSS
  • Máxima performance: CSS Modules
  • Estilos dinámicos: CSS-in-JS

Puedes combinar opciones en el mismo proyecto según las necesidades de cada componente.

NextJS soporta todas sin configuración adicional (excepto Tailwind que requiere instalación inicial).