Índice de contenido
- Por qué Tailwind CSS se ha vuelto tan popular (y por qué no lo usaba en Django)
- Qué es realmente Tailwind CSS y cómo funciona
- ¿Qué es Tailwind CSS?
- ¿Tailwind CSS es un framework de componentes?
- Lo malo de Tailwind CSS
- El verdadero problema entre Tailwind CSS y Django
- Por qué usar Tailwind vía CDN es una mala idea en Django
- Opciones reales para usar Tailwind CSS en Django 6
- Usar Tailwind CSS con Node y npm (enfoque clásico)
- django-tailwind: integración tradicional con Node
- django-tailwind-cli: Tailwind sin Node en Django
- Cuándo usar django-tailwind y cuándo django-tailwind-cli
- El problema técnico entre Tailwind CSS y Django: más detalle
- ¿Cómo evitar ese problema?
- django-tailwind: la solución clásica
- Extra: Tailwind CSS Typography
- Configuración para producción y purgado de CSS
- Plugins útiles: Tailwind Typography y DaisyUI
- ¿Vale la pena usar Tailwind CSS en Django 6?
- Conclusión
- FAQs rápidas
Integrar Tailwind CSS en Django 6 es una de esas tareas que parecen sencillas… hasta que empiezas a preparar el proyecto para producción.
Durante mucho tiempo opté por Bootstrap sin pensarlo demasiado: funcionaba de entrada, venía listo para usar y Django no se quejaba. Pero cuando necesitas control total sobre el diseño, Bootstrap empieza a estorbar más de lo que ayuda.
Ahí es donde entra Tailwind CSS. El problema no es Tailwind en sí, sino cómo encaja —o no— con el ecosistema de Django.
En este artículo te explico cómo usar Tailwind CSS en Django 6 de forma correcta, qué errores evitar y qué opciones reales existen hoy, incluyendo una alternativa moderna sin Node.js que cambia bastante el panorama.
Después de cubrir la autenticación personalizada, el siguiente paso natural es incorporar un framework CSS que nos permita maquetar la interfaz de forma eficiente. Aunque suelo usar Bootstrap, en esta ocasión vamos a usar Tailwind CSS, que es ideal para darle vida a nuestro sistema de autenticación del backend personalizado en Django.
Por qué Tailwind CSS se ha vuelto tan popular (y por qué no lo usaba en Django)
Si no conoces Tailwind CSS, probablemente llevas tiempo fuera del ecosistema frontend .
Básicamente, Tailwind no es un framework de componentes como Bootstrap, sino un sistema de utilidades: clases pequeñas y predefinidas que aplican estilos directamente en el HTML, sin necesidad de salir al archivo CSS.
En lugar de escribir CSS tradicional, construyes la interfaz combinando clases como:
mt-6→ margen superior de nivel 6p-2→ padding general de nivel 2text-xl,bg-gray-900,rounded-xl, etc.
En mi experiencia, este enfoque hace que el diseño sea:
- Más rápido de prototipar
- Más consistente
- Mucho más flexible
Pero durante años evité usar Tailwind con Django. ¿La razón? El flujo de trabajo no encajaba bien, y en producción era un dolor de cabeza.
Qué es realmente Tailwind CSS y cómo funciona
Tailwind CSS funciona generando un conjunto enorme de clases utilitarias que cubren todo lo que podrías necesitar: colores, márgenes, tipografías, sombras, opacidades, layouts, etc.
Eso tiene una consecuencia importante:
Si usas Tailwind por CDN, te llevas todo el CSS, incluso lo que no usas.
Y eso, en producción, es inaceptable.
En proyectos reales, Tailwind debe:
- Analizar tus templates
- Detectar qué clases usas realmente
- Purgar (eliminar) todo lo que no se usa
- Generar un archivo CSS final pequeño y optimizado
Ahí es donde empiezan los problemas con Django.
¿Qué es Tailwind CSS?
En mis propias palabras: Tailwind CSS es una colección enorme de clases utilitarias con las que puedes construir cualquier interfaz directamente desde el HTML, sin escribir CSS personalizado. Todo lo que puedes hacer con CSS tradicional —variar texto, tamaño, color, fondo, márgenes, espaciado y más— lo tienes disponible en Tailwind mediante clases con valores predefinidos.
Más que clases arbitrarias, son reglas con una escala predefinida. Por ejemplo, si quieres aplicar un margen superior, no defines un valor exacto en píxeles, sino que usas clases como mt-1, mt-4 o mt-6, que corresponden a valores en rem (la unidad que maneja Tailwind internamente). Si necesitas un valor muy específico fuera de la escala, Tailwind v3+ permite valores arbitrarios con la sintaxis mt-[16px].
Aquí puedes ver algunos ejemplos con márgenes y paddings:
mt-6 → margen superior nivel 6
p-2 → padding general nivel 2
<div class="mt-6 ...">mt-6</div>
<div class="mr-4 ...">mr-4</div>
<div class="pt-6 ...">pt-6</div>
<div class="pr-4 ...">pr-4</div>Es una especie de "vocabulario CSS" estandarizado que hace el código mucho más modular y predecible.
¿Tailwind CSS es un framework de componentes?
No. Tailwind CSS no es un framework basado en componentes como Bootstrap o Bulma. Los componentes los tienes que construir tú mismo combinando las clases utilitarias.
Por ejemplo, esta misma pantalla que estás viendo está construida con Tailwind CSS: los colores, la tipografía, el espaciado… todo definido con clases. Puede ser más o menos bonita, pero ese nivel de control es precisamente lo que lo hace tan atractivo.
Bootstrap, en cambio, te da un botón, una tarjeta o una navbar ya definidos, y si quieres cambiarlos tienes que sobreescribir los estilos o modificar variables SASS. Con Tailwind no tienes ese problema: como todo son simples clases, tú eres quien define el componente desde cero.
Dicho eso, si buscas en internet "Tailwind CSS components" encontrarás una enorme cantidad de ejemplos listos para copiar y adaptar (cards, avatares, navbars, etc.) de proyectos como Flowbite o DaisyUI.
Lo malo de Tailwind CSS
La principal crítica que recibe Tailwind es que ensucia el HTML. Y tiene razón: cuando empiezas a acumular clases, el marcado puede volverse verboso:
<div class="flex flex-col items-center p rounded-2xl">
<div>
<img class="size-48 shadow-xl" alt="" src="/img/cover.png" />
</div>
<div class="flex">
<span>Class Warfare</span>
<span>The Anti-Patterns</span>
<span class="flex">
<span>No. 4</span>
<span>·</span>
<span>2025</span>
</span>
</div>
</div>Es feo al inicio, sí. Lo que suelo hacer para mitigarlo es extraer esas combinaciones de clases repetidas a una clase personalizada usando la directiva @apply en el CSS:
/* styles.css */
.card {
@apply flex flex-col items-center rounded-2xl p-4 shadow-xl;
}Así mantienes el HTML limpio y Tailwind te sigue generando el CSS optimizado. Lo veremos con más detalle en próximas clases.
El verdadero problema entre Tailwind CSS y Django
Django no incluye de serie ningún entorno de build para el frontend.
No hay Node, no hay npm, no hay Vite, no hay nada similar a lo que ofrece Laravel con su integración nativa de Vite.
Y Tailwind sí necesita un proceso de build si quieres usarlo correctamente en producción.
Por eso, durante mucho tiempo, la integración típica implicaba:
- Instalar Node.js manualmente
- Configurar
npm - Compilar el CSS aparte
- Sincronizar eso con
collectstatic
Funciona, sí. Pero es fricción innecesaria, especialmente si llegas a Django buscando simplicidad y un stack limpio.
Por qué usar Tailwind vía CDN es una mala idea en Django
Esto es importante decirlo claro: usar Tailwind por CDN en un proyecto Django real es mala práctica.
¿Por qué?
- Cargas un CSS enorme (varios megabytes en versiones antiguas, o el motor JIT completo en v3+)
- El navegador compila Tailwind en tiempo real, añadiendo latencia
- No hay purgado: se incluyen todas las clases, usadas o no
- Dependencia externa: si el CDN falla, tu interfaz se rompe
- Peor rendimiento general: impacta las métricas de Core Web Vitals
Para un prototipo rápido o una prueba de concepto puede pasar, pero no es una opción válida para producción.
Opciones reales para usar Tailwind CSS en Django 6
Hoy tenemos tres enfoques reales, cada uno con sus ventajas y sus costes.
Usar Tailwind CSS con Node y npm (enfoque clásico)
Es el enfoque más documentado en internet:
- Instalas Node.js
- Configuras Tailwind con
tailwind.config.js - Compilas el CSS con scripts de
npm - Sirves el archivo estático resultante desde Django
Ventajas:
- Control total sobre el proceso de build
- Acceso al ecosistema completo de plugins de Tailwind
Desventajas:
- Añade Node a un proyecto que no lo necesitaba
- Mayor complejidad en el setup y en el deploy
- Más puntos de fallo en entornos de CI/CD
Este enfoque aparece mucho en artículos "production-grade", pero no es el más elegante para un proyecto Django puro.
django-tailwind: integración tradicional con Node
Aquí entra django-tailwind, una librería bastante popular que simplifica bastante el proceso anterior envolviéndolo dentro de comandos de manage.py.
Lo bueno:
- Integra Tailwind directamente dentro de la estructura del proyecto Django
- Permite purgar el CSS en el proceso de build
- Flujo más Django-friendly con comandos como
python manage.py tailwind start
Lo malo (desde mi experiencia):
- Sigue dependiendo de Node.js y
npm - Si Node no está bien configurado en el sistema, todo se rompe
- No siempre es ideal en entornos simples, educativos o de servidores sin Node
Durante mucho tiempo, esta fue "la solución". Pero hoy ya no es la única.
django-tailwind-cli: Tailwind sin Node en Django
Aquí es donde la cosa se pone interesante.
django-tailwind-cli utiliza el Tailwind CSS CLI standalone, un binario independiente que no requiere npm, ni webpack, ni Node.js. El propio paquete lo descarga automáticamente la primera vez que lo usas.
Y esto cambia totalmente el juego.
Características clave:
- ❌ No requiere Node.js
- ⚡ Setup en minutos con un solo comando
- Hot reload integrado durante el desarrollo
- Build optimizado con purgado automático para producción
- Soporte para DaisyUI como plugin opcional
- Pensado específicamente para el ecosistema Django
En proyectos Django 6 modernos, esta es mi recomendación por defecto si no quieres meter Node solo por Tailwind.
Cuándo usar django-tailwind y cuándo django-tailwind-cli
Mi criterio práctico es este:
- Usa
django-tailwind-clisi:- No quieres depender de Node.js
- Tu frontend vive enteramente en templates de Django
- Buscas simplicidad, rapidez de setup y buen rendimiento
- Usa
django-tailwindsi:- Ya usas Node en el proyecto por otras razones
- Tienes un tooling frontend más complejo (Vite, Webpack, etc.)
- Necesitas compartir la configuración de Tailwind con otros frameworks del mismo repo
No hay dogmas. Hay contexto.
El problema técnico entre Tailwind CSS y Django: más detalle
A diferencia de Bootstrap, Tailwind CSS no se lleva bien "de entrada" con frameworks como Django, y aquí te explico por qué con más precisión:
Tailwind CSS define en su hoja de estilos todas las combinaciones posibles de clases: box-shadow, opacity, variantes de color, breakpoints responsivos, estados hover/focus… todo. Si usas la CDN tal como se hace con Bootstrap, todas esas clases se van a cargar en el navegador, uses o no uses la mayoría de ellas. En versiones recientes el CDN de Tailwind usa un motor JIT en el navegador, pero eso tiene su propio coste en tiempo de ejecución.
Y eso es extremadamente ineficiente para producción.
¿Cómo evitar ese problema?
La solución es usar herramientas de build —como Node.js con npm, o Vite— para rastrear los archivos de tu proyecto, identificar qué clases de Tailwind realmente utilizas y generar un CSS final con solo esas clases. Este proceso se conoce como purgado.
En Django, no tenemos eso de forma nativa. A diferencia de Laravel, que incluye Vite de serie y tiene todo el entorno de build JavaScript listo desde el primer día, en Django hay que configurarlo todo manualmente… o usar un paquete que lo abstraiga.
Por eso es que normalmente no suelo recomendar Tailwind con Django sin una solución específica. Pero tenemos algo especial que vemos en el siguiente apartado.
django-tailwind: la solución clásica
Existe un paquete llamado django-tailwind que permite integrar Tailwind CSS en Django de forma más eficiente que la CDN. Puedes encontrarlo fácilmente buscando "Django Tailwind" en Google, y su documentación oficial cubre los pasos de instalación con detalle.
Lo relevante es que permite purgar el CSS durante la fase de build para producción.
Veamos los pasos para integrarlo. Primero, instalamos el paquete:
$ pip install django-tailwindEsto descargará el paquete y sus dependencias:
Collecting django-tailwind
Downloading django_tailwind-4.2.0-py3-none-any.whl.metadata (4.4 kB)
Requirement already satisfied: django>=4.2.20 in c:\users\andre\desktop\proy\django\curso\.venv\lib\site-packages (from django-tailwind) (5.2.4)
Requirement already satisfied: asgiref>=3.8.1 in c:\users\andre\desktop\proy\django\curso\.venv\lib\site-packages (from django>=4.2.20->django-tailwind) (3.9.1)
Requirement already satisfied: sqlparse>=0.3.1 in c:\users\andre\desktop\proy\django\curso\.venv\lib\site-packages (from django>=4.2.20->django-tailwind) (0.5.3)
Requirement already satisfied: tzdata in c:\users\andre\desktop\proy\django\curso\.venv\lib\site-packages (from django>=4.2.20->django-tailwind) (2025.2)
Downloading django_tailwind-4.2.0-py3-none-any.whl (19 kB)Registramos tailwind como aplicación instalada en settings.py:
djangoshopping/djangoshopping/settings.py
INSTALLED_APPS = [
...
'tailwind',
]Inicializamos el proyecto de Tailwind dentro de Django:
$ python manage.py tailwind initEste comando descarga algunas dependencias adicionales como cookiecutter (usado para generar la app de Tailwind a partir de una plantilla):
Collecting cookiecutter
Downloading cookiecutter-2.6.0-py3-none-any.whl.metadata (7.3 kB)
Collecting binaryornot>=0.4.4 (from cookiecutter)
Downloading binaryornot-0.4.4-py2.py3-none-any.whl.metadata (6.0 kB)
Collecting Jinja2<4.0.0,>=2.7 (from cookiecutter)
Downloading jinja2-3.1.6-py3-none-any.whl.metadata (2.9 kB)
Collecting click<9.0.0,>=7.0 (from cookiecutter)
Downloading click-8.2.1-py3-none-any.whl.metadata (2.5 kB)Y crea una aplicación Django dedicada para Tailwind. El nombre sugerido —y el que usaremos— es theme:
[1/2] Your Tailwind app/theme name (theme): themeTambién pregunta si quieres instalar DaisyUI como plugin. Por ahora seleccionamos que no, aunque puedes activarlo si lo necesitas:
[2/2] Include daisyUI plugin?
1 - no
2 - yes
Choose from [1/2] (1): 1
Finalmente obtendrás una salida como esta:
Tailwind application 'theme' has been successfully created. Please add 'theme' to INSTALLED_APPS in settings.py, then run the following command to install Tailwind CSS dependencies: `python manage.py tailwind install`
Ahora registramos tanto tailwind como la app theme generada, y configuramos la variable TAILWIND_APP_NAME en settings.py:
djangoshopping/djangoshopping/settings.py
INSTALLED_APPS = [
...
'tailwind',
'theme',
]
TAILWIND_APP_NAME = 'theme'Instalamos las dependencias de Node que Tailwind necesita internamente. Este paso requiere tener npm instalado:
$ python manage.py tailwind installSi ves el siguiente error:
It looks like node.js and/or npm is not installed or cannot be found.
Visit https://nodejs.org to download and install node.js for your system.
If you have npm installed and still getting this error message, set NPM_BIN_PATH variable in settings.py to match path of NPM executable in your system.
Significa que npm (el gestor de paquetes de Node) no está instalado o Django no puede encontrarlo. Puedes descargarlo desde la web oficial:
https://nodejs.org/es/download
En caso de que ya lo tengas instalado pero el paquete no lo encuentre —por ejemplo, si lo gestionas con Laragon o Laravel Herd— debes localizar la ruta exacta del ejecutable npm en tu sistema y configurarla en settings.py:
djangoshopping/djangoshopping/settings.py
NPM_BIN_PATH = "C:/Users/andre/.config/herd/bin/nvm/v23.11.0/npm.cmd"Esta ruta es solo un ejemplo. Reemplázala con la que corresponda a tu sistema operativo y a tu instalación de Node.
Con todo configurado, podemos añadir la etiqueta de Tailwind en nuestra plantilla base. Esta etiqueta es la que inyecta el enlace al CSS generado:
djangoshopping/blog/templates/master.html
{% load static tailwind_tags %}
...
<head>
...
{% tailwind_css %}
...
</head>Puedes inspeccionar el código fuente de la página al ejecutar la aplicación. Si todo funciona bien, verás que el estilo cambia ligeramente y aparecerá una etiqueta como la siguiente en el HTML generado:
<link rel="stylesheet" type="text/css" href="/static/css/dist/styles.css?v=<V>">Que es el CSS de Tailwind ya compilado y servido como estático dentro de tu proyecto.
Finalmente, para producción, ejecutas el siguiente comando que purga el CSS y genera un archivo optimizado:
$ python manage.py tailwind buildEsta es exactamente la razón por la que hicimos todos estos pasos: el objetivo final es purgar el CSS y quedarnos solo con las clases que realmente usamos en el proyecto. La opción de la CDN incorporaría todo el CSS de Tailwind sin filtrar, lo cual es inaceptable en producción. Con este setup tienes un CSS justo, eficiente y sin peso muerto.
Extra: Tailwind CSS Typography
El plugin @tailwindcss/typography nos facilita enormemente el trabajo de aplicar estilos tipográficos a bloques de texto: márgenes entre párrafos, tamaño de encabezados h1 a h6, estilos de listas, citas, código inline… todo aquello que en CSS puro requiere definir regla por regla.
Lo interesante de mostrar esta variante es que gracias a django-tailwind disponemos de un proyecto Node real embebido dentro de Django, lo que nos permite extender Tailwind con plugins externos de forma relativamente sencilla. Para instalarlo, primero nos posicionamos dentro de la aplicación theme que creamos antes, específicamente en su directorio de fuentes de Node:
djangoshopping/theme/static_src
Dentro de esa carpeta encontrarás el package.json, que es el archivo fundamental de cualquier proyecto Node y es aquí donde se deben instalar los paquetes adicionales. Instalamos el plugin:
$ npm install -D @tailwindcss/typographyAgregamos el plugin en el archivo de estilos principal de Tailwind:
djangoshopping/theme/static_src/src/styles.css
@import "tailwindcss";
+ @plugin "@tailwindcss/typography";A partir de ahí, solo tienes que añadir la clase prose al elemento contenedor de tu texto y el plugin se encarga de todo el estilo tipográfico automáticamente. Por ejemplo:
<article class="prose prose-lg mx-auto">
{{ post.content|safe }}
</article>Configuración para producción y purgado de CSS
Aquí es donde se separan los proyectos serios de los experimentos.
En producción necesitas:
- CSS mínimo: solo lo que se usa
- Purgado activo de clases no utilizadas
- Archivos estáticos correctamente servidos vía
collectstatic - Caché agresiva para maximizar el rendimiento
Con django-tailwind-cli, el comando:
$ python manage.py tailwind buildGenera un CSS optimizado, purgado y listo para producción. Sin hacks, sin scripts externos raros.
Luego, combinado con collectstatic y herramientas como WhiteNoise, tienes un pipeline de assets limpio y eficiente sin necesidad de un servidor de medios externo.
Plugins útiles: Tailwind Typography y DaisyUI
Uno de mis favoritos es @tailwindcss/typography, tal como mostramos antes.
Definir márgenes, tamaños y estilos para textos largos —artículos de blog, documentación, contenido generado dinámicamente— es tedioso con CSS puro. Con la clase prose del plugin, todo eso se resuelve en segundos.
Y si no quieres construir todos tus componentes desde cero:
- DaisyUI te da botones, cards, layouts y docenas de componentes listos para usar
- Sin abandonar Tailwind ni su sistema de utilidades
- Sin perder el control sobre el diseño final
Ambos plugins son compatibles con django-tailwind y con django-tailwind-cli, por lo que puedes usarlos independientemente del enfoque que elijas.
¿Vale la pena usar Tailwind CSS en Django 6?
Sí.
Pero solo si lo usas bien.
Tailwind no es mágico:
- Puede ensuciar el HTML si no abstraes las clases repetidas con
@applyo con componentes - Tiene un coste cognitivo inicial: hay que aprender su sistema de escala
- Requiere disciplina en el equipo para mantener la coherencia
Pero cuando lo integras correctamente, especialmente con soluciones modernas como django-tailwind-cli, el resultado es:
- CSS mínimo y sin peso muerto
- Diseño flexible y completamente personalizado
- Rendimiento excelente en producción
- Flujo de trabajo limpio y reproducible
En mi caso, hoy ya no descarto Tailwind en Django. Simplemente elijo la herramienta correcta según el contexto del proyecto.
Conclusión
Usar Tailwind CSS en Django 6 no va de copiar comandos: va de entender el flujo completo de principio a fin:
- Desarrollo (con watcher y hot reload)
- Build (compilación y purgado del CSS)
- Producción (servir los estáticos correctamente)
- Rendimiento (caché y CSS mínimo)
La aparición de django-tailwind-cli elimina uno de los mayores frenos históricos: Node como dependencia obligatoria. Si buscas control, rendimiento y una integración elegante sin complicar tu stack, hoy en día esa es la opción que más sentido tiene.
FAQs rápidas
- ¿Se puede usar Tailwind CSS en Django sin Node?
- Sí, usando
django-tailwind-cli, que descarga el CLI standalone de Tailwind sin necesitarnpm.
- Sí, usando
- ¿Es recomendable usar Tailwind por CDN en Django?
- No, solo para pruebas rápidas o prototipos locales. En producción siempre debes purgar el CSS.
- ¿Tailwind reemplaza a Bootstrap en Django?
- Depende del proyecto, pero ofrece mucho más control y flexibilidad a cambio de un poco más de esfuerzo inicial.
- ¿Tailwind afecta el rendimiento de Django?
- Solo si lo usas mal (CDN sin purgar). Con el proceso de build correcto, es extremadamente eficiente y el CSS final suele pesar pocos kilobytes.
- ¿Puedo usar DaisyUI o Flowbite con Django Tailwind?
- Sí. Ambos plugins son compatibles tanto con
django-tailwindcomo condjango-tailwind-cli. Flowbite también requiere incluir su JavaScript para los componentes interactivos.
- Sí. Ambos plugins son compatibles tanto con
- ¿Funciona django-crispy-forms con Tailwind?
- Sí. Existe el paquete
crispy-tailwindque añade soporte de Tailwind CSS como template pack paradjango-crispy-forms, permitiéndote renderizar formularios con las clases de Tailwind automáticamente.
- Sí. Existe el paquete
Siguiente paso: aprende sobre el Problema del N+1 en el ORM de Django y cómo evitarlo