Drupal 8: Theming With Tailwind CSS

Upon a recommendation from someone in my local Drupal user group I decided to give Tailwind CSS a go. The ultimate aim of this was to replace the base theme I am using here with a more stripped down theme. At the time of writing this I am using the Cog theme, and whilst it has it's merits, I find that it's a little too much for this simple site.

I decided, therefore, to create a new theme and use Tailwind CSS to alter the site a little. This meant an exercise in integrating Tailwind CSS into a Drupal theme.

Tailwind CSS?

In case you haven't heard of Tailwind CSS I'll quote the site here.

"Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you need to build bespoke designs without any annoying opinionated styles you have to fight to override."

When I first encountered Tailwind CSS this made little sense to me. When I looked into it, however, I found it to be a really interesting idea, but it does take some getting used to if you are familiar with traditional CSS.

The bottom line is that instead of having the markup of the site and writing reams and reams of CSS, you instead inject classes into the markup to control how the elements are styled. This means that you end up writing far less CSS and the end result is a very nicely laid out site with only a few classes.

Although it sounds like you'll need to inject classes all over the place to get things working, the reality is that you only need a few classes to create a lot of effect.

Taking an example of the following HTML.

<p>Some text.</p>

If we want to add some formatting to the text we would add a few classes to the p element.

<p class="text-center text-gray-600 underline text-3xl">Some text.</p>

For explanation, the classes added do the following.

  • text-center : Aligns the text to the center.
  • text-gray-600: Adds the color hex value #718096 to the element (making the text gray).
  • underline : Applies an underline style to the element.
  • text-3xl : Sets the font-size attribute to be 1.875rem.

Personally, not being a front end developer, this approach was actually quite intuitive and I found myself using the needed classes easily. The project has a number of sensible defaults and as such you only tend to add classes to the things you want to style.

Adding Tailwind CSS to Drupal

Adding Tailwind CSS to Drupal starts out with a blank Drupal theme, containing no templates. Here are the files I created in the directory themes/custom/tailwindcss_theme.

First, the theme info file tailwindcss_theme.info.yml.

name: 'Drupal Tailwind CSS Theme'
type: theme
description: 'Drupal Tailwind CSS Theme'
core_version_requirement: ^8 || ^9
base theme: false

libraries:
  - tailwindcss_theme/global_styles

regions:
  header: 'Header'
  primary_menu: 'Primary Menu'
  secondary_menu: 'Secondary Menu'
  breadcrumb: 'Breadcrumb'
  highlighted: 'Highlighted'
  help: 'Help'
  pre_content: 'Pre Content'
  content: 'Content'
  post_content: 'Post Content'
  sidebar_first: 'Sidebar First'
  sidebar_second: 'Sidebar Second'
  footer: 'Footer'

Next, the libraries file, which will point to a CSS file we haven't created yet (that comes later). This is the file called tailwindcss_theme.libraries.yml.

global_styles:
  version: VERSION
  css:
    theme:
      css/styles.css: {}

With that in place we can now set up our npm project using the following command.

npm init

This will create a package.json file, which doesn't do a lot on its own, so installing Tailwind CSS is the next step. We do this by installing the tailwindcss package as a dev dependency like this.

npm install tailwindcss --save-dev

With Tailwind CSS installed we can then create a default configuration file. The following command will create a file called tailwind.config.js. This file is used to control some of the configuration and setup of Tailwind CSS.

npx tailwindcss init

With everything in place we then need to set up our source CSS file. Create a CSS file at src/styles.css within in the theme directory and enter the following.

@tailwind base;

@tailwind components;

@tailwind utilities;

These are include statements that will include the different parts of the Tailwind CSS libraries.

The last step here is to compile the Tailwind CSS into CSS that the site can use. This is done using the following command, which takes the src/styles.css file and generates a CSS file at css/styles.css.

npx tailwindcss build src/styles.css -o css/styles.css

You can speed up this by using npm scripts to help build you styles.

{
  "name": "tailwindcss_theme",
  "version": "1.0.0",
  "description": "Tailwind CSS Theme",
  "scripts": {
    "build": "npx tailwindcss build src/styles.css -o css/styles.css"
  }
}

With this in place you can build your styles using the following command.

npm run build

This will run the post CSS processor on the file at src/styles.css and place the result in css/styles.css. We have already set up the Drupal theme to load in the file at css/styles.css so this file will form the styles of the site.

The default instillation of Tailwind CSS doesn't do an awful lot, especially with very few classes being injected into the markup in a basic Drupal theme.

Taking an example of the block template (block.html.twig) we can add a class to the block title. This is done by using the addClass() method on the title_attributes object.

<div{{ attributes }}>
  {{ title_prefix }}
  {% if label %}
    <h2{{ title_attributes.addClass('text-2xl') }}>{{ label }}</h2>
  {% endif %}
  {{ title_suffix }}
  {% block content %}
    {{ content }}
  {% endblock %}
</div>

The above just increases the size of the block title to 1.5rem.

Configuring Tailwind CSS For Drupal

One thing that is important is allowing Tailwind CSS and Drupal to play together nicely. In order to do this you can add the prefix option to the tailwind.config.js configuration file.

The following sets the prefix to be 'tw-'.

module.exports = {
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
  prefix: 'tw-'
}

This means that all Tailwind CSS classes must be prefixed with 'tw-' in order for them to be picked up correctly. This allows Drupal specific classes like 'block' to be used without also being picked up by Tailwind CSS. Whilst you can get along nicely without this option, you will find strange behaviours being produced when the two systems are trying to use the same class name.

Integrating SASS And Gulp

Whilst I could have stopped there I also needed to integrate a SASS build step into the process of building the CSS. This is because I have a number of pre-existing SASS rules that I wanted to include. Tailwind CSS is a postcss system, which means that SASS processing isn't included, so in order to do this I needed to include a CSS preprocessor.

My SASS file is kept at src/sass/components/thing.sass within the theme, and in order to use this file I need to process that into src/components/thing.css. I then need to include that in the main src/style.css file so that we can then use Tailwind CSS to generate css/style.css. That file will then contain all of the styles from Tailwind CSS and by SASS rules.

In order to achieve this I needed to install a few more tools.

  • gulp - The gulp build package.
  • gulp-sass - Process SASS into CSS.
  • gulp-cli - Provides a command line interface to gulp.
  • gulp-postcss - Integrates gulp with postcss and allows the processing of Tailwind CSS though gulp.
  • postcss-import - Adds additional import rules with postcss and allows the inclusion custom files into the build process.

To install all these tools we use the following commands.

npm install gulp --save-dev
npm install gulp-cli --save-dev
npm install gulp-postcss --save-dev
npm install gulp-sass --save-dev
npm install postcss-import --save-dev

With all these tools in place we need to put together a build script so that we can process the SASS files and run the Tailwind CSS processing. To this end I have put together the following, gulpfile.js that contains the commands 'sass' and 'styles', although the 'styles' command will run the 'sass' command first by default.

var gulp = require('gulp');
var sass = require('gulp-sass');
var postcss = require('gulp-postcss');

gulp.task('sass', function () {
    return gulp.src('src/sass/**/*.sass')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('./src'));
});

gulp.task('styles', gulp.series('sass', function () {
    var tailwindcss = require('tailwindcss');
    var postcssimport = require('postcss-import');

    return gulp.src('src/styles.css')
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss([
            postcssimport(),
            tailwindcss('./tailwind.config.js'),
            require('autoprefixer'),
        ]))
        .pipe(gulp.dest('./css'));
}));

One slight modification is needed to the main src/styles.css file by adding in an an @import option. This allows us to use postcss-import to import the needed CSS files we compiled using gulp. Note that we need to add the @import commands to the top of the file.

@import "./components/custom.css";

@tailwind base;
@tailwind components;
@tailwind utilities;

The inclusion of the gulp-cli tool allow us to build the styles using a single command.

./node_modules/gulp-cli/bin/gulp.js styles

We can also drop this into the package.json file so that we can build the styles more easily.

{
  "name": "tailwindcss_theme",
  "version": "1.0.0",
  "description": "Tailwind CSS Drupal Theme",
  "scripts": {
    "gulp": "./node_modules/gulp-cli/bin/gulp.js styles",
    "build": "npx tailwindcss build src/styles.css -o css/styles.css"
  },
  "dependencies": {},
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-cli": "^2.2.0",
    "gulp-postcss": "^8.0.0",
    "gulp-sass": "^4.0.2",
    "postcss-import": "^12.0.1",
    "tailwindcss": "^1.2.0"
  }
}

This means we can run 'npm run build' to build all of the styles in the project.

PurgeCSS

One thing I have missed out here is the purging the CSS rules you haven't used. The entire TailwindCSS library is over a megabyte so removing the items that aren't being used is an essential part of any TailwindCSS setup. The library to use here is PurgeCSS, which can be used to flush out any CSS classes that aren't in use.

To install PurgeCSS to work with gulp use the gulp-purgecss library, this can be installed as a dev dependency in the following manner.

npm install gulp-purgecss --save-dev

With that in place we need to inform PurgeCSS about what classes are available in the theme so that they don't get purged. I also needed to update the regular expression used to match the classes so that all classes and sub-classes were picked up and not purged.

gulp.task('styles', gulp.series('sass', function () {
    var tailwindcss = require('tailwindcss');
    var postcssimport = require('postcss-import');

    return gulp.src('src/styles.css')
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss([
            postcssimport(),
            tailwindcss('./tailwind.config.js'),
            require('autoprefixer'),
        ]))
        .pipe(purgecss({
            mode: 'layers',
            content: [
                'templates/**/*.twig',
                '../../../../config/**/*.yml',
                'hashbangcode_theme2.theme',
                'src/sass/**/*.scss'
            ],
            defaultExtractor: content =>
              content.match(/[\w-/:]+(?<!:)/g) || []
        }))
        .pipe(gulp.dest('./css'));
}));

This vastly reduces the footprint of the CSS and turned the 1.2MB CSS file I had to about 23KB. Note that if you have used TailwindCSS styles in your content then you will need to inform PurgeCSS of this change in addition to any other theme files or configuration items you have.

Thanks

As a final note I should say thanks to Oliver Davies, who has created a blog post and a Drupal theme that will also provide information on how to get started with Tailwind CSS. Oliver takes a slightly different approach when building the styles, and also doesn't use any preprocessing, but the theme he has created is a really good starting point.

Comments

very useful guide:)

Inside tailwindcss_theme.info.yml, base theme needs added.

Permalink

This tailwindcss theme does not need a base theme. The idea is that is doesn't need any classes or other items coming from Drupal. There are some internal classes that come with certain aspects, but generally a clean theme is needed for this to work.

Name
Philip Norton
Permalink

Hi Philip, 

very nice and useful guide! But as Yuezhu mentioned, you should add 'base theme: false' to your 'tailwindcss_theme.info.yml' as this entry is needed. I ran into several 500 errors, before adding this.

Thanks for your work!

Timm

Permalink

Thanks for the comment Timm, :)

I've updated it now with the correct base theme. Looking at the sites theme it looks like I updated that and forgot to update this post.

Name
Philip Norton
Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
16 + 4 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.