How to Setup Tailwind CSS with Django (Part 2)

Table of Contents

Django Tailwind CSS, Alpine.js Tutorial Series:

  1. Introduction
  2. How to Setup Tailwind CSS with Django (Part 1)
  3. How to Setup Tailwind CSS with Django (Part 2)
  4. Optimize Tailwind CSS in Django
  5. Render Django Form with Tailwind CSS Style
  6. Integrate Alpine.js with Django (Part 1) (coming soon)
  7. Integrate Alpine.js with Django (Part 2) (coming soon)
  8. Build Task List with Tailwind CSS, Alpine.js and Django (coming soon)
  9. Django Form Validation in Tailwind Modal (Alpine.js) (coming soon)
  10. Django Form Validation in Tailwind Modal (Alpine.js + HTMX) (coming soon)
  11. How to deploy Django Tailwind CSS project with Docker (coming soon)

The source code is on Github/django-tailwind-alpine-htmx

Recommended Posts:

  1. Lightweight Javascript Framework Review (For Django Developers)

Objectives

By the end of this chapter, you should be able to:

  1. Use python-webpack-boilerplate to jump start frontend project bundled by Webpack
  2. Setup Tailwind CSS to the frontend project.

python-webpack-boilerplate

python-webpack-boilerplate can help you Jump start frontend project bundled by Webpack

Create Django project

$ mkdir django_tailwind_project && cd django_tailwind_project
$ python3 -m venv env
$ source env/bin/activate

You can also use other tools such as Poetry or Pipenv

Create requirements.txt

django==3.2
(env)$ pip install -r requirements.txt
(env)$ django-admin.py startproject django_tailwind_app .

You will see structure like this

.
├── django_tailwind_app
├── env
├── manage.py
└── requirements.txt

Now, let's get the project running on local env.

# create db tables
(env)$ python manage.py migrate
(env)$ python manage.py runserver

Check on http://127.0.0.1:8000/, and you should be able to see the Django welcome page

Import python-webpack-boilerplate

Add python-webpack-boilerplate to the requirements.txt

django==3.2
python-webpack-boilerplate==0.0.5
(env)$ pip install -r requirements.txt

Update django_tailwind_app/settings.py to add 'webpack_boilerplate' to INSTALLED_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'webpack_boilerplate',               # new
]

Let's run Django command to create frontend project from the python-webpack-boilerplate

$ python manage.py webpack_init
# here we use the default frontend slug
project_slug [frontend]:

Now a new frontend directory is created which contains pre-defined files for our frontend project.

├── django_tailwind_app
├── env
├── frontend                          # new
│   ├── README.md
│   ├── package-lock.json
│   ├── package.json
│   ├── postcss.config.js
│   ├── src
│   ├── vendors
│   └── webpack
├── manage.py
└── requirements.txt

Run frontend project

If you have no nodejs installed, please install it first by using below links

  1. On nodejs homepage
  2. Using nvm I recommend this way.
$ node -v
v14.18.0
$ npm -v
6.14.15
$ cd frontend

# install dependency packages
$ npm install

# launch webpack dev server
$ npm run start

If the command run without error, that means the setup works, let's terminate the npm run start by pressing Ctrl + C

Add Tailwind

By default Python Webpack Boilerplate does not contains Tailwind CSS, let's add it.

$ cd frontend

# install packages
$ npm install -D tailwindcss@latest postcss-import

You should see something like this in the frontend/package.json

"postcss-import": "^14.0.2",
"tailwindcss": "^3.0.12",

Next, let's edit postcss.config.js

// https://tailwindcss.com/docs/using-with-preprocessors

module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss/nesting')(require('postcss-nesting')),
    require('tailwindcss'),
    require('postcss-preset-env')({
      features: { 'nesting-rules': false }
    }),
  ]
};

Next, generate a config file for your frontend project using the Tailwind CLI utility included when you install the tailwindcss npm package

$ cd frontend

$ npx tailwindcss init

Now tailwind.config.js is generated

module.exports = {
    content: [],
    theme: {
        extend: {},
    },
    plugins: [],
}

We will update this file after a while.

Write Tailwind CSS

Update src/application/app.js

// This is the scss entry file
import "../styles/index.scss";

window.document.addEventListener("DOMContentLoaded", function () {
  window.console.log("dom ready 1");
});

Update src/styles/index.scss

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

.jumbotron {
  // should be relative path of the entry scss file
  background-image: url("../../vendors/images/sample.jpg");
  background-size: cover;
}

.btn-blue {
  @apply inline-flex items-center px-4 py-2 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75;
}

Let's test again.

$ cd frontend
$ npm run start

Now the tailwindcss can be compiled successfully, let's test in Django template.

Test in Django Template

Add code below to django_tailwind_app/settings.py

import os

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "frontend/build"),
]

WEBPACK_LOADER = {
    'MANIFEST_FILE': os.path.join(BASE_DIR, "frontend/build/manifest.json"),
}
  1. We add the above frontend/build to STATICFILES_DIRS so Django can find the static assets (img, font and others)
  2. We add MANIFEST_FILE location to the WEBPACK_LOADER so our custom loader can help us load JS and CSS.

Update django_tailwind_app/urls.py

from django.contrib import admin
from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path('', TemplateView.as_view(template_name="index.html")),     # new
    path('admin/', admin.site.urls),
]

Create directory for templates

$ mkdir django_tailwind_app/templates

├── django_tailwind_app
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── templates               # new
│   ├── urls.py
│   └── wsgi.py

Update TEMPLATES in django_tailwind_app/settings.py, so Django can know where to find the templates

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['django_tailwind_app/templates'],                             # new
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Add index.html to the above django_tailwind_app/templates

{% load webpack_loader static %}

<!DOCTYPE html>
<html>
<head>
  <title>Index</title>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  {% stylesheet_pack 'app' %}
</head>
<body>

<div class="jumbotron py-5">
  <div class="w-full max-w-7xl mx-auto px-4">
      <h1 class="text-4xl mb-4">Hello, world!</h1>
      <p class="mb-4">This is a template for a simple marketing or informational website. It includes a large callout called a
        jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>

      <p><a class="btn-blue mb-4" href="#" role="button">Learn more »</a></p>

      <div class="flex justify-center">
        <img src="{% static 'vendors/images/webpack.png' %}" class="img-fluid"/>
      </div>
  </div>
</div>

{% javascript_pack 'app' %}

</body>
</html>
  1. We load webpack_loader at the top of the template, which come from python-webpack-boilerplate
  2. We can still use static to import image from the frontend project.
  3. We use stylesheet_pack and javascript_pack to load CSS and JS bundle files to Django
(env)$ python manage.py migrate
(env)$ python manage.py runserver

Now check on http://127.0.0.1:8000/ and you should be able to see a welcome page.

Here we can see:

  1. The button style is working.
  2. Some styles in the Django templates such as w-full max-w-7xl mx-auto px-4 is not working.

JIT

From Tailwind V3, it enabled JIT (Just-in-Time) all the time.

Tailwind CSS works by scanning all of your HTML, JavaScript components, and any other template files for class names, then generating all of the corresponding CSS for those styles.

In order for Tailwind to generate all of the CSS you need, it needs to know about every single file in your project that contains any Tailwind class names.

So we should config content section of the tailwind.config.js, then Tailwind will know which css classes are used.

Let's update frontend/tailwind.config.js

const Path = require("path");
const pwd = process.env.PWD;

// We can add current project paths here
const projectPaths = [
    Path.join(pwd, "../django_tailwind_app/templates/**/*.html"),
    // add js file paths if you need
];

const contentPaths = [...projectPaths];
console.log(`tailwindcss will scan ${contentPaths}`);

module.exports = {
    content: contentPaths,
    theme: {
        extend: {},
    },
    plugins: [],
}

Notes:

  1. Here we add Django templates path to the projectPaths
  2. And then we pass the contentPaths to the content
  3. The final built css file will contain css classes used in the Django templates
$ cd frontend
$ npm run start

tailwindcss will scan django_tailwind_project/django_tailwind_app/templates/**/*.html

Workflow

  1. We use python-webpack-boilerplate to jump start frontend project.
  2. And then, we install Tailwind CSS to the frontend project to make it work.

Notes

  1. python-webpack-boilerplate is easy to extend and customize, and we can benefit from the rich Webpack ecosystem.
  2. It supports code linting on the JS and SCSS code.
  3. It supports ES6+ syntax and has great JS bundle solution.

Django Tailwind CSS, Alpine.js Tutorial Series:

  1. Introduction
  2. How to Setup Tailwind CSS with Django (Part 1)
  3. How to Setup Tailwind CSS with Django (Part 2)
  4. Optimize Tailwind CSS in Django
  5. Render Django Form with Tailwind CSS Style
  6. Integrate Alpine.js with Django (Part 1) (coming soon)
  7. Integrate Alpine.js with Django (Part 2) (coming soon)
  8. Build Task List with Tailwind CSS, Alpine.js and Django (coming soon)
  9. Django Form Validation in Tailwind Modal (Alpine.js) (coming soon)
  10. Django Form Validation in Tailwind Modal (Alpine.js + HTMX) (coming soon)
  11. How to deploy Django Tailwind CSS project with Docker (coming soon)

The source code is on Github/django-tailwind-alpine-htmx

Recommended Posts:

  1. Lightweight Javascript Framework Review (For Django Developers)
Launch Products Faster with Django

Unlock the power of Django combined with Hotwire through SaaS Hammer. Supercharge productivity, tap into Python's rich ecosystem, and focus on perfecting your product!

Michael Yin

Michael Yin

Michael is a Full Stack Developer who loves writing code, tutorials about Django, and modern frontend techs.

He has published some tech course on testdriven.io and ebooks on leanpub.

© 2024 SaaS Hammer