DEV Community

Cover image for Stop Using Tailwind CDN: Build Only the CSS You Actually Use (Django, PHP, Go)
Ijeoma Jahsway
Ijeoma Jahsway

Posted on

Stop Using Tailwind CDN: Build Only the CSS You Actually Use (Django, PHP, Go)

🚨 The Problem

If you've been using Tailwind via CDN in production, then you've been loading the entire Tailwind CSS library into your website, which is awful for user experience. You basically said to your browser:

“Here, take the entire library. I’ll only use like 5% of it, but you figure that out.”

The CDN version of Tailwind ships everything. Every utility class, every variation, every possible styling option. It’s great for quick prototyping, but in production? It’s overkill.

What does that mean in practice?

  • Unnecessary payload: your users download way more CSS than they need
  • Slower load times: especially noticeable on weaker networks (which is not exactly rare)
  • Zero optimization: no tree-shaking, no purging, just raw bulk
  • Not scalable: the more serious your project gets, the worse this decision looks

It works… But when it actually comes down to performance, it quietly becomes one of those things you “fix later” and never do.

💡 The Idea

Instead of shipping the entire Tailwind universe to the browser, you flip the approach:

Only generate the styles you actually use.

Here’s the workflow:

  • Scan your project files (templates, HTML, JS, etc.)
  • Detect the Tailwind classes you’ve used
  • Compile only those classes into a CSS file
  • Output a clean, minimal stylesheet you can serve like any static asset

That’s it.

No frameworks. No over-engineering. No magic. Maybe a bit of voodoo 😁.

You end up with:

  • A much smaller CSS file
  • A faster site
  • A setup that works across Django, PHP, Go, or anything else

It’s one of those changes that feels small, but once you use it, going back to CDN starts to feel… questionable.

⚙️ The Setup

This setup uses Node.js purely as a build tool. No React, no Vite, no complex framework setup.

1. Setup Environment

Make sure you have Node.js installed:

node -v
npm -v
Enter fullscreen mode Exit fullscreen mode

Create a workspace for Tailwind:

mkdir tailwind-build
cd tailwind-build
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install dependencies:

npm install tailwindcss postcss autoprefixer @tailwindcss/typography
Enter fullscreen mode Exit fullscreen mode

2. Configure Tailwind

Initialize Tailwind:

npx tailwindcss init
Enter fullscreen mode Exit fullscreen mode

Create your CSS entry file:

mkdir src
touch src/styles.css
Enter fullscreen mode Exit fullscreen mode

Add this to src/styles.css:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Set up PostCSS (postcss.config.js):

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};
Enter fullscreen mode Exit fullscreen mode

3. Define Content Paths

This is the important part. This tells Tailwind where to look for class names. You can modify it to match your project's template structure.

Update tailwind.config.js:

module.exports = {
  content: [
    "../**/*.html",
    "../**/*.js",
    "../**/*.ts",
  ],
  darkMode: "class",
  theme: {
    extend: {},
  },
  plugins: [
    require("@tailwindcss/typography"),
  ],
};
Enter fullscreen mode Exit fullscreen mode

This works for:

  • Django templates
  • PHP files
  • Go templates
  • basically anything that outputs HTML

4. Build Process

Add scripts to your package.json:

"scripts": {
  "dev": "tailwindcss -i ./src/styles.css -o ./dist/tailwind.css --watch",
  "build": "tailwindcss -i ./src/styles.css -o ./dist/tailwind.css --minify"
}
Enter fullscreen mode Exit fullscreen mode

You can modify the location of the output file (./dist/tailwind.css) to the exact location you want your output tailwind.css file to be generated.

Run development mode:

npm run dev
Enter fullscreen mode Exit fullscreen mode

This runs the dev compiler that actively watches for changes in your template files.

For production:

npm run build
Enter fullscreen mode Exit fullscreen mode

This minifies the output tailwind.css file so that it is as light as possible.
Your compiled CSS will be in:

dist/tailwind.css
Enter fullscreen mode Exit fullscreen mode

Or whatever location you set it to be.

Move or copy that file into your project’s static/assets folder and link it like normal CSS. Or however you stack links to static files.

🔄 How It Works Behind the Scenes

This is the part most tutorials skip, probably because it requires thinking.

Tailwind doesn’t magically “know” what styles you need. It literally scans your files.

That content array in your config:

content: [
  "../**/*.html",
  "../**/*.js",
]
Enter fullscreen mode Exit fullscreen mode

…tells Tailwind:

“Go through these files and collect every class name you can find.”

So if your templates contain:

<div class="bg-black text-white p-4"></div>
Enter fullscreen mode Exit fullscreen mode

Tailwind will generate only:

  • bg-black
  • text-white
  • p-4

Everything else? Ignored.

What about unused styles?

Gone.

Tailwind’s build process effectively purges anything you didn’t use. No extra configuration needed and no cleanup scripts.

Why this works across frameworks

Tailwind doesn’t care about Django, PHP, or Go.

It only cares about:

  • strings in files
  • that look like class names

So whether your HTML comes from:

  • Django templates
  • PHP includes
  • Go’s html/template

…it’s all the same to Tailwind.

Which is why this setup works everywhere without modification.

You’ve basically turned Tailwind into a very obedient assistant that only does exactly what you asked. No more, no less. A rare trait in both software and humans.

🌍 Works With Any Backend

This setup doesn’t care what backend you’re using. It’s not loyal. It just scans files and does its job.

Django

Point Tailwind to your templates:

<div class="bg-black text-white p-4">
  Hello from Django
</div>
Enter fullscreen mode Exit fullscreen mode

After building, only those classes exist in your final CSS. No extras hitching a free ride.


PHP (Blade or Plain PHP)

Same idea:

<div class="bg-blue-500 text-white p-2">
  Hello from PHP
</div>
Enter fullscreen mode Exit fullscreen mode

Tailwind doesn’t care if it’s Blade, raw PHP, or something held together with hope. It just reads the output files.


Go Templates

Even Go gets to join the party:

<div class="text-green-500 font-bold">
  Hello from Go
</div>
Enter fullscreen mode Exit fullscreen mode

As long as your templates live within the paths defined in content, Tailwind will find and compile the classes.


The Point

If your project produces HTML, then this works.
Just files → scan → build → done.

🚀 Production Tips

This is where people quietly sabotage their own setup.

  • Use --minify
    Your users don’t need nicely formatted CSS. They need fast-loading pages.

  • Don’t run --watch in production
    Unless you enjoy wasting server resources for absolutely no benefit.

  • Cache your static files
    Set proper cache headers so browsers don’t keep re-downloading the same CSS file every time. Basic, but often ignored.

If you skip these, you’re basically undoing the performance gains you just worked for.

📦 GitHub Repo

If you don’t feel like setting this up from scratch (completely fair), I’ve already packaged it:

👉 https://github.com/brandnova/tailwind-build-pipeline.git

  • Ready-to-clone
  • Minimal configuration
  • No unnecessary complexity

This is the exact setup I use across my recent web projects, regardless of whether I’m working with Django, PHP, or Go.

You can clone it, drop it into your workflow, and move on with your life instead of reconfiguring Tailwind for the hundredth time.

Top comments (0)