Buenas prácticas con Tailwind CSS en proyectos grandes

Tailwind CSS ha revolucionado la forma de escribir estilos en la web, pero cuando el proyecto crece es fácil caer en un desorden de clases que dificulta el mantenimiento. En este artículo comparto las prácticas que me han ayudado a escalar Tailwind en aplicaciones grandes, manteniendo el código limpio, rápido y fácil de evolucionar.
1. Configura el purge y los tamaños de producción desde el inicio
El primer paso es asegurarse de que Tailwind elimine todo el CSS que no se usa. En tailwind.config.js define los paths correctos y limita los tamaños de los screens y fontSize a los que realmente necesitas.
module.exports = {
content: [
"./src/**/*.tsx",
"./src/**/*.ts",
"./public/index.html"
],
theme: {
extend: {},
screens: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
},
fontSize: {
xs: "0.75rem",
sm: "0.875rem",
base: "1rem",
lg: "1.125rem",
xl: "1.25rem"
}
},
plugins: []
};Con esto evitas que el bundle incluya utilidades que nunca vas a usar, reduciendo el peso final.
2. Usa @apply para abstraer patrones repetidos
En componentes que comparten la misma combinación de utilidades, crea clases de nivel superior con @apply dentro de tus archivos CSS o .module.css. De esta forma el HTML vuelve más legible y la semántica mejora.
/* src/styles/buttons.css */
.btn-primary {
@apply bg-indigo-600 text-white font-medium py-2 px-4 rounded hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500;
}
.btn-secondary {
@apply bg-gray-200 text-gray-800 font-medium py-2 px-4 rounded hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-400;
}Luego basta con className="btn-primary" en el JSX.
3. Componentes UI como bloques de Tailwind
En proyectos grandes es habitual usar una librería de componentes internos (por ejemplo, con Storybook). Cada componente debe exponer su propia API de props y encapsular las clases Tailwind dentro. Evita pasar className arbitrario desde fuera, a menos que sea una prop explícita como className para extensiones controladas.
type CardProps = {
title: string;
children: React.ReactNode;
className?: string;
};
export const Card = ({title, children, className}: CardProps) => (
{title}
{children}
);
Así, el componente sigue siendo responsable de su propio estilo y la aplicación mantiene una capa de abstracción clara.
4. Tematización y modo oscuro con variables CSS
Tailwind permite definir colores personalizados que pueden depender de variables CSS. Declara las variables en :root y @media (prefers-color-scheme: dark), y usa la función var() dentro de la configuración.
/* src/index.css */
:root {
--color-bg: #ffffff;
--color-text: #1a202c;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #1a202c;
--color-text: #f7fafc;
}
}
/* tailwind.config.js */
module.exports = {
theme: {
extend: {
colors: {
bg: "var(--color-bg)",
text: "var(--color-text)"
}
}
}
};Con esto, cambiar el tema es cuestión de actualizar las variables, sin tocar el HTML.
5. Limita el uso de clases arbitrarias
Tailwind permite escribir clases como mt-[23px] o bg-[#123abc]. En proyectos grandes es tentador abusar de ellas, pero pierden la ventaja de la consistencia. Define una escala de valores en theme.extend y usa esas claves en todo el proyecto.
module.exports = {
theme: {
extend: {
spacing: {
"9": "2.25rem", // 36px
"11": "2.75rem" // 44px
},
colors: {
"brand-primary": "#0066ff",
"brand-secondary": "#ff6600"
}
}
}
};Así evitas valores “mágicos” y facilitas la revisión de código.
6. Integra linting y auto‑formateado
Herramientas como stylelint con el plugin stylelint-config-tailwindcss detectan clases no usadas o mal escritas. Configura eslint-plugin-tailwindcss para que el IDE te alerte cuando una clase no exista en la configuración.
// .eslintrc.js
module.exports = {
plugins: ["tailwindcss"],
rules: {
"tailwindcss/classnames-order": "warn",
"tailwindcss/no-custom-classname": "error"
}
};Con esto mantienes una base de código homogénea y reduces errores humanos.
7. Documenta los patrones de Tailwind en tu wiki
En equipos de más de tres personas es fundamental que todos conozcan la convención de nombres, los valores extendidos y cuándo usar @apply frente a clases inline. Un documento breve con ejemplos claros acelera la incorporación de nuevos miembros y evita que cada quien invente su propio “estilo”.
Aplicando estas prácticas, Tailwind sigue siendo una herramienta productiva incluso en aplicaciones con cientos de componentes y miles de líneas de código. La clave está en centralizar la configuración, abstraer patrones repetidos y reforzar la disciplina mediante linting y documentación.