Tailwind CSS en Django 6: instalación, configuración y purgado de CSS paso a paso

- Andrés Cruz - EN In english

Video thumbnail

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 6
  • p-2 → padding general de nivel 2
  • text-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-cli si:
    • No quieres depender de Node.js
    • Tu frontend vive enteramente en templates de Django
    • Buscas simplicidad, rapidez de setup y buen rendimiento
  • Usa django-tailwind si:
    • 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-tailwind

Esto 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 init

Este 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): theme

Tambié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 install

Si 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 build

Esta 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

Video thumbnail

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/typography

Agregamos 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 build

Genera 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 @apply o 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 necesitar npm.
  • ¿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-tailwind como con django-tailwind-cli. Flowbite también requiere incluir su JavaScript para los componentes interactivos.
  • ¿Funciona django-crispy-forms con Tailwind?
    • Sí. Existe el paquete crispy-tailwind que añade soporte de Tailwind CSS como template pack para django-crispy-forms, permitiéndote renderizar formularios con las clases de Tailwind automáticamente.

Siguiente paso: aprende sobre el Problema del N+1 en el ORM de Django y cómo evitarlo

Aprende a integrar Tailwind CSS en Django 6 correctamente. Comparamos django-tailwind, django-tailwind-cli y CDN, con guía de instalación completa, purgado de CSS para producción y plugins como DaisyUI y Typography.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

Acepto recibir anuncios de interes sobre este Blog.