Incorporating Tailwind CSS into Django 6

Video thumbnail

Integrating Tailwind CSS in Django 6 is one of those things that seem simple… until you start preparing the project for production.
In my case, for a long time I opted for Bootstrap without thinking too much about it. It worked, it came ready-to-use, and Django didn't complain. But when you need total design control, Bootstrap starts to get in the way more than it helps.

That's where Tailwind CSS comes in. The problem isn't Tailwind. The problem is how it fits (or doesn't) with Django.

In this article, I'm going to explain how to use Tailwind CSS in Django 6 correctly, what errors to avoid, and what real options exist today, including a modern alternative without Node.js that significantly changes the landscape.

The next step we'll want is, finally, by the gods, to introduce some library, some API (whatever you want to call it), or some framework for the CSS part. Usually, I use Bootstrap, but for a change, in these types of frameworks, we are going to use Tailwind CSS, which is ideal for layout out our custom backend authentication system in Django.

Why Tailwind CSS has become so popular (and why I didn't use it in Django)

If you don't know Tailwind CSS, you're probably living under a rock .
Basically, Tailwind is not a component framework like Bootstrap, but a utility system: small, predefined classes that apply styles directly in the HTML.

Instead of writing traditional CSS, you do things like:

  • mt-6 → margin-top
  • p-2 → padding
  • text-xl, bg-gray-900, rounded-xl, etc.

In my experience, this makes the design:

  • Faster to prototype
  • More consistent
  • Much more flexible

But for years I avoided using Tailwind with Django. The reason? The workflow didn't fit well… and in production, it was a pain.

What Tailwind CSS really is and how it works

Tailwind CSS works by generating all the possible classes you might need: colors, margins, typographies, shadows, opacities, layouts, etc.

This has an important consequence:

If you use Tailwind via CDN, you take EVERYTHING, even the CSS you don't use.

And that, in production, is unacceptable.

In real projects, Tailwind must:

  • Analyze your templates
  • Detect which classes you use
  • Purge (remove) everything else
  • Generate a small and optimized final CSS

That's where the problems with Django begin.

What is Tailwind CSS?

Ultimately, Tailwind CSS (I can define it myself (these are my own words)) is a bunch of classes that we can organize, as you can see here, where at some point the animation is reproduced.

They are a bunch of classes with which we can apply styles. In other words: everything we can do (I dare say everything) with traditional CSS (varying text, size, color, background, margin, spacing, and everything that exists) we have in Tailwind through classes with predefined values.

More than classes, we have rules. For example, if we want to define something like my-margin with a margin X, in Tailwind we have a class that defines this rule to some extent.

By "to some extent," I mean that, for example, you might want to put 16px here, but we don't have a class with exactly that value. Tailwind uses other units —my memory fails me right now, they aren't pixels, they are one of the other four units used— but we have a way to apply margins like mt-1, mt-6, etc.

Here you can see some examples with margins and paddings:

mt-6 → margin-top level 6

p-2 → general padding level 2

<div class="mt-6 ...">mt-6</div>
<div class="mr-4 ...">mr-4</div>
<div class="pt-6 ...">mt-6</div>
<div class="pr-4 ...">mr-4</div>

We have that kind of jargon, so to speak. So, with this, everything is more modularized.

Is Tailwind CSS a component framework?

No, Tailwind CSS is not a component-based framework. We have to create the components ourselves.

For example, this screen you are seeing, I made it using Tailwind CSS to define the colors, texts, etc. Whether it's pretty or not (however you want to define it), that's how it works.

So, yes, it is very widely used. In fact, Bootstrap has moved a bit to the background. In Bootstrap, you are forced to stick with the defined style, or modify it manually or overwrite it.

With Tailwind CSS you don't have that problem, because since they are just classes, you are the one who creates the components.
Of course, you can also search the internet for "Tailwind CSS components" and see a lot of ready-to-use examples (cards, avatars, etc.).

The bad side of Tailwind CSS

The bad thing is that we have many classes and we must work more manually:

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

It's ugly at first, yes. Usually, what I do is: instead of putting everything inline, I define a custom class with the structure.
We will see that later.

The video has already gone a bit long introducing Tailwind CSS, so we'll leave it for the next class, where we will install and configure Tailwind CSS in Django.

The real problem between Tailwind CSS and Django

Django does not come with a built-in frontend build environment.

There is no Node, no npm, no Vite, there's nothing.

And Tailwind does need a build process if you want to use it well.

That's why, for a long time, typical integration involved:

  • Installing Node
  • Configuring npm
  • Compiling CSS separately
  • Syncing that with collectstatic

It works, yes.

But it's unnecessary friction, especially if you come to Django looking for simplicity.

Why using Tailwind via CDN is a bad idea in Django

This is important to state clearly: using Tailwind via CDN in Django is bad practice.

Why?

  • You load a huge CSS file (megabytes)
  • The browser compiles Tailwind in real-time
  • There is no purging
  • External dependency
  • Worse performance

For rapid development, it might work, but it's not a real option for production.

Real options for using Tailwind CSS in Django 6

Today we have three real approaches, each with its pros and cons.

Using Tailwind CSS with Node and npm (classic approach)

It's the best-known approach:

  • You install Node.js
  • You configure Tailwind
  • You compile CSS with npm scripts
  • You serve the static file in Django

Advantages:

  • Total control
  • Full Tailwind ecosystem

Disadvantages:

  • Adds Node to a project that didn't need it
  • More complexity
  • More points of failure

You see this approach a lot in "production-grade" articles, but it's not the most elegant for pure Django.

Django Tailwind: traditional integration with Node

This is where django-tailwind comes in, a quite popular library.

The good:

  • Integrates Tailwind inside the Django project
  • Allows CSS purging
  • More Django-friendly flow

The bad (from my experience):

  • Still depends on Node
  • If Node is not well-configured, everything breaks
  • Not always ideal for simple or educational environments

For a long time, this was "the solution." But today it's no longer the only one.

Django Tailwind CLI: Tailwind without Node in Django

This is where things get interesting.

django-tailwind-cli uses the standalone Tailwind CSS CLI, without npm, without webpack, without Node.js.

And this completely changes the game.

Key features:

  • ❌ Does not require Node.js
  • ⚡ Setup in minutes
  • Integrated hot reload
  • Optimized build with automatic purging
  • Support for DaisyUI
  • Designed specifically for Django

In modern Django 6 projects, this is my default recommendation if you don't want to bring in Node just for Tailwind.

When to use django-tailwind and when to use django-tailwind-cli

My practical criteria is this:

  • Use django-tailwind-cli if:
    • You don't want Node
    • Your frontend lives in Django templates
    • You're looking for simplicity and performance
  • Use django-tailwind if:
    • You already use Node in the project
    • You have complex frontend tooling
    • You share Tailwind with other frameworks

There are no dogmas. There is context.

The problem with Tailwind CSS and Django

Unlike Bootstrap, Tailwind CSS doesn't get along well with frameworks like Django, and here's why:

Tailwind CSS defines all possible CSS rules via classes. So, what happens if you don't use certain classes like box-shadow or opacity?

If you use a CDN (as is done with Bootstrap), all those classes will still be loaded, taking up space and slowing down the site.

And that is extremely inefficient.

How to avoid that problem?

The solution would be to use tools like Node.js, Vite, etc., to track files and purge the CSS (remove what you don't use).

In Django, we don't have that natively. Unlike Laravel, which does incorporate an environment with Node and facilitates that work.

That's why I usually don't use Tailwind CSS with Django. But... we have something special that we talk about in the next section.

Django Tailwind CSS: the solution

There is a package called Django-Tailwind CSS, which allows integrating Tailwind CSS into Django more efficiently.

You can search for "Django Tailwind" and access its official page. There you will see the installation steps.
The good thing is that it allows purging the CSS during the production build phase.

Let's see the steps to integrate it; first, we run the following command:

$ pip install django-tailwind

This will download the package and dependencies such as:

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)

We configure Tailwind as an installed app:

In settings.py:

INSTALLED_APPS = [ *** 'tailwind', ]

We initialize the project:

$ python manage.py tailwind init

This command downloads some additional dependencies:

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

And it creates a Django application to which we give the suggested name 'theme':

32.4 rich-14.0.0 six-1.17.0 text-unidecode-1.3 types-python-dateutil-2.9.0.20250708 urllib3-2.5.0

  [1/2] Your Tailwind app/theme name (theme): theme
  [1/2] Your Tailwind app/theme name (theme): theme

It also asks to install some plugins, which we say no to:

  [2/2] Include daisyUI plugin?
    1 - no
    2 - yes

   Choose from [1/2] (1): 1

Although, you can install it if you wish; finally, we will have an output like the following:

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`

We configure the application generated earlier:

In settings.py:

INSTALLED_APPS = [
   ...
   'tailwind',
   'theme',  # name you will give to your custom Tailwind app
   ...
]

We register the application generated earlier:

djangoshopping\djangoshopping\settings.py

INSTALLED_APPS = [
   ***
   'tailwind',
   'theme',
]
TAILWIND_APP_NAME = 'theme'

We install the Tailwind CSS dependencies, in this case, the CSS itself and dependencies:

$ python manage.py tailwind install

If you see an output like the following:

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.

It means you do NOT have Node installed, specifically NPM which is the Node package manager and you must install it; to do so, you can download it from the official website:

https://nodejs.org/en/download

In case you have it installed but it's not found, for example, if you have it installed through Laragon or Laravel Herd, you must find the path in your system and configure it:

djangoshopping\djangoshopping\settings.py

NPM_BIN_PATH = "C:/Users/andre/.config/herd/bin/nvm/v23.11.0/npm.cmd"

As we mentioned before, this path is an example and is for when you have it configured but the django tailwind package DID NOT find it; you must replace the previous path with the one you use in your system.

Finally, we can use the following tag in our master template which is the one that imports CSS internally:

djangoshopping\blog\templates\master.html

{% load static tailwind_tags %}
...
<head>
   ...
   {% tailwind_css %}
   ...
</head>

You can inspect the page's source code when running the application, check that the incorporated style doesn't return a 404 or something similar, and if everything is working fine, you'll see that now the style changes slightly and you'll have a tag like the following:

<link rel="stylesheet" type="text/css" href="/static/css/dist/styles.css?v=<V>">

Which is your Tailwind configured in your project.

In production, we have the following command to purge the CSS:

$ python manage.py tailwind build

As you can see if you have worked with Tailwind, and the reason why we did all these steps to configure Tailwind in our project, is because we are interested in purging the CSS that we are NOT going to use in production, and that's what the previous command is for; this way, we have exactly the CSS we're going to use without additional rules that we DON'T use in our project, and that's why we usually DON'T use Tailwind if the associated project DOES NOT use Node (as happens in the case of Django, but in Django we have the package configured in this section); because the CDN option incorporates ALL the CSS of the Tailwind framework that we DON'T want to keep for when we launch the project to production.

Extra: Tailwind CSS Typography

Video thumbnail

This plugin makes the extremely tedious process of having to define margins and text size for our texts easier, including H1..H6 elements; although we can use the configuration we used before for texts, it's interesting to show a variant and since thanks to Django Tailwind we have a Node project in Django and we can extend Tailwind itself in a relatively simple way, first, we position ourselves inside the application we created which remember we called theme:

djangoshopping\theme\static_src

Inside the previous folder is where the package.json is located, which is a fundamental file for any Node project, and that's why this is where we must perform the installation of the Node packages.

We install the package inside the Node project of the app called theme that we created, whose location would be this:

djangoshopping\theme\static_src

At the previous location, you should see files of a Node project like package.json. We install the package:

$ npm install -D @tailwindcss/typography

We add the dependency:

djangoshopping\theme\static_src\src\styles.css

 @import "tailwindcss"; + @plugin "@tailwindcss/typography";

Now, we only have to add the prose class to the text container classes.

When to use django-tailwind and when to use django-tailwind-cli

My practical criteria is this:

Use django-tailwind-cli if:

  • You don't want Node
  • Your frontend lives in Django templates
  • You're looking for simplicity and performance

Use django-tailwind if:

  • You already use Node in the project
  • You have complex frontend tooling
  • You share Tailwind with other frameworks

There are no dogmas. There is context.

Production configuration and CSS purging

This is where serious projects separate from experiments.

In production you need:

  • Minimal CSS
  • Active purging
  • Well-served static files
  • Aggressive caching

With django-tailwind-cli, the command:

$ python manage.py tailwind build

Generates an optimized, purged, and production-ready CSS.

No hacks. No weird scripts.

Then, with collectstatic and tools like WhiteNoise, you have a clean and efficient pipeline.

Useful plugins: Tailwind Typography and DaisyUI

One of my favorites is Tailwind Typography as we showed before.

Defining margins, sizes, and styles for long texts is tedious.

With prose, all that is solved in seconds.

And if you don't want to build components from scratch:

  • DaisyUI gives you buttons, cards, and layouts ready to use
  • Without leaving Tailwind
  • Without losing control

Is it worth using Tailwind CSS in Django 6?

Yes.

But only if you use it correctly.

Tailwind is not magic:

  • It litters the HTML if you don't abstract
  • It has a cognitive cost
  • It requires discipline

But when you integrate it correctly, especially with modern solutions like django-tailwind-cli, the result is:

  • Minimal CSS
  • Flexible design
  • Excellent performance
  • Clean workflow

In my case, today I no longer rule out Tailwind in Django.

I simply choose the right tool according to the project.

Conclusion

Using Tailwind CSS in Django 6 is not about copying commands, it's about understanding the full flow:

  • Development
  • Build
  • Production
  • Performance

The emergence of django-tailwind-cli removes one of the major historical hurdles: Node as a mandatory dependency.

If you are looking for control, performance, and elegant integration, that is the option that makes the most sense today.

Quick FAQs

  • Can Tailwind CSS be used in Django without Node?
    • Yes, using django-tailwind-cli.
  • Is it advisable to use Tailwind via CDN in Django?
    • No, only for quick tests.
  • Does Tailwind replace Bootstrap in Django?
    • It depends on the project, but it offers much more control.
  • Does Tailwind affect performance?
    • Only if you use it poorly. With purging, it's extremely efficient.

Next step: learn about the N+1 Problem in Django's ORM and how to avoid it.

We will incorporate Tailwind CSS into the Django framework using a package that allows us to create a Node project natively as if it were a Laravel project.

I agree to receive announcements of interest about this Blog.

Andrés Cruz

ES En español