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ística | CSS Modules | Tailwind CSS | CSS-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:
- Nuevos componentes en Tailwind
- Migra componentes existentes progresivamente
- 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:
📦 CSS Modules
CSS tradicional con scope automático. Perfecto para proyectos que necesitan máxima performance.
🎨 Tailwind CSS
Clases utilitarias para desarrollo rápido. La opción más popular en 2025.
💅 CSS-in-JS
Estilos dinámicos en JavaScript. Ideal para componentes con muchas variaciones.
Resumen
Tres opciones principales:
- CSS Modules - CSS tradicional con scope
- Tailwind CSS - Clases utilitarias
- 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).