Supercharge your WordPress themes with Tailwind and Gulp

Updated by Tom on

In this tutorial, we'll take your WordPress theme development to the next level by utilising Tailwind CSS, purgeCSS and gulp. Tailwind is a robust CSS framework for rapidly developing custom designs whilst remaining highly flexible and configurable. It's quickly becoming one of the best tools for building any website or app, and WordPress themes are no different!

To make this possible, we're going to use Gulp. Gulp is a toolkit that helps you automate slow or repetitive tasks and compose them into efficient pipelines. For example, you could concatenate your javascript files into a single, minified file which reduces your HTTP requests and overall page size.

In our case, we're going to use it to add Tailwind, purge the unused CSS and generate a small style.css file in the root for use in your WordPress theme.

Install dependencies

Before continuing, ensure you have Node.js installed alongside npm. Once done, initialise the project with npm init in your terminal and follow the steps on-screen. The installation will create a package.json file in your project root, which is essential for using Node.js and npm packages.

Once complete, the next step is to install the npm packages required Gulp and Tailwind to work. Install these with:

npm i --save-dev gulp fs-path gulp-clean-css gulp-footer gulp-header gulp-postcss gulp-sourcemaps gulp-strip-css-comments tailwindcss postcss-import autoprefixer

As you can see, we're using many packages here, but you should also notice that many of these packages add extra functionality to the gulp pipelines.

A quick summary of the npm packages:

  • gulp installs the main Gulp package and fs-path allows us to copy some package.json properties into the stylesheet header.
  • The other gulp packages are for cleaning CSS, removing comments and adding a header to the style.css file.
  • And finally, the tailwindcss package for Tailwind and postcss-import to inline CSS imports.

Folder structure

The folder structure for your WordPress theme will require these changes:

/

- configs/
-- clean-css.js

- src/
-- css/
--- <additional-css-files>.css

- gulpfile.js
- tailwind.config.js
- package.json (should have been created above)

...

Ensure the above files and folders are present before you continue this tutorial.

Configure Tailwind

Now the files and folders have been created; it's time to configure Tailwind to purge CSS and target your theme files. Add the following to the tailwind.config.js file:

tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./**/*.php']
  },
  theme: {},
  variants: {},
  plugins: []
}

Here, we're instructing purgeCSS to target all PHP files in the project. The flexibility offered here is particularly useful if you use other folders for template files, custom navwalkers etc. as you'll retain the ability to use tailwind classes in these files and they won't be purged from the final CSS build.

If you require further customisation of your Tailwind config, check out their documentation.

Configure Clean CSS

gulp-clean-css is a simple Gulp wrapper for clean-css. With clean-css we can optimise the CSS for browsers, powered by Node.js. The configuration is created in configs/clean-css.js:

configs/clean-css.js
module.exports = {
  format: {
    breaks: {
      // controls where to insert breaks
      afterAtRule: false, // controls if a line break comes after an at-rule; e.g. `@charset`; defaults to `false`
      afterBlockBegins: false, // controls if a line break comes after a block begins; e.g. `@media`; defaults to `false`
      afterBlockEnds: false, // controls if a line break comes after a block ends, defaults to `false`
      afterComment: false, // controls if a line break comes after a comment; defaults to `false`
      afterProperty: false, // controls if a line break comes after a property; defaults to `false`
      afterRuleBegins: false, // controls if a line break comes after a rule begins; defaults to `false`
      afterRuleEnds: true, // controls if a line break comes after a rule ends; defaults to `false`
      beforeBlockEnds: false, // controls if a line break comes before a block ends; defaults to `false`
      betweenSelectors: false // controls if a line break comes between selectors; defaults to `false`
    },
    breakWith: '\n', // controls the new line character, can be `'\r\n'` or `'\n'` (aliased as `'windows'` and `'unix'` or `'crlf'` and `'lf'`); defaults to system one, so former on Windows and latter on Unix
    indentBy: 0, // controls number of characters to indent with; defaults to `0`
    indentWith: 'space', // controls a character to indent with, can be `'space'` or `'tab'`; defaults to `'space'`
    spaces: {
      // controls where to insert spaces
      aroundSelectorRelation: true, // controls if spaces come around selector relations; e.g. `div > a`; defaults to `false`
      beforeBlockBegins: true, // controls if a space comes before a block begins; e.g. `.block {`; defaults to `false`
      beforeValue: false // controls if a space comes before a value; e.g. `width: 1rem`; defaults to `false`
    },
    wrapAt: false, // controls maximum line length; defaults to `false`
    semicolonAfterLastProperty: false // controls removing trailing semicolons in rule; defaults to `false` - means remove
  }
}

Descriptions of all properties used above are in the comments.

Create your gulpfile

The gulpfile.js contains all the methods to create the WordPress theme stylesheet and purge the unused CSS found in the CSS and PHP files throughout the project:

gulpfile.js
const gulp = require('gulp')
const postcss = require('gulp-postcss')
const stripCssComments = require('gulp-strip-css-comments')
const cleanCSS = require('gulp-clean-css')

// WP write header and footer
const fs = require('fs')
const header = require('gulp-header')
const footer = require('gulp-footer')

// Package.JSON contents
const pkg = JSON.parse(fs.readFileSync('./package.json'))

function css() {
  const cssbanner = [
    '/*',
    'Theme Name:          ' + pkg.themename,
    'Description:         ' + pkg.description,
    'Author:              ' + pkg.author,
    'Author URI:          ' + pkg.authoruri,
    'Version:             ' + pkg.version,
    'Theme URI:           ' + pkg.homepage,
    'License:             ' + pkg.license,
    'License URI:         ' + pkg.licenseuri,
    'Text Domain:         ' + pkg.textDomain,
    '*/',
    ''
  ].join('\n')

  return gulp
    .src('src/css/style.css') // Change this to your own stylesheet
    .pipe(
      postcss([
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer')
      ])
    )
    .pipe(stripCssComments({ preserve: false }))
    .pipe(cleanCSS(require('./configs/clean-css.js')))
    .pipe(
      header(cssbanner, {
        pkg: pkg
      })
    )
    .pipe(footer('\n'))
    .on('error', console.error.bind(console))
    .pipe(gulp.dest('./'))
}

// default watch function
exports.default = function() {
  gulp.watch(
    ['./**/*.php', './src/css/*.css'],
    { interval: 750 },
    gulp.series(css)
  )
}

This gulpfile.js is quite large, but here's a quick breakdown of what's going on:

  • The first eight lines import our dependencies.
  • The pkg variable imports the contents of the package.json file. This variable generates the header of style.css in the format that WordPress understands.
  • The css() function first creates the header in the cssBanner variable.
  • Then the pipeline uses postcss to add vendor prefixes and other useful transformations, alongside Tailwind and autoprefixer.
  • Next, the CSS comments are stripped and cleaned.
  • Once all CSS is prepared, the file header is added with an extra line added to the end of the file.
  • The pipeline ends by outputting the new style.css file into the project root directory.
  • Finally, we create a watch for watching all PHP and CSS file changes throughout the project. The interval is added for improved performance.

Usage and deployment

Don't worry, we're nearly done! The final steps are ensuring your package.json is complete with the following properties:

package.json
{
  "name": "custom-wp-theme",
  "version": "1.0.0",
  "themename": "Your WordPress theme",
  "description": "This WordPress theme built with tailwind",
  "author": "Author here",
  "authoruri": "https://example.com",
  "homepage": "https://example.com",
  "textDomain": "a-text-domain",
  "license": "GPL-2.0",
  "licenseuri": "http://www.gnu.org/licenses/gpl-2.0.txt",
  ...
}

And finally, to create your theme CSS it's as simple as using the gulp command in your terminal. Updating your theme files will automagically generate a new version of the file, too, so you can use this method with something like Local for super-efficient WordPress theme development.

When deploying your theme or compressing it for upload, remember to omit the node_modules folder, as this will be quite large with the number of dependencies we're using. For example, you could use something like this on MacOS:

zip -r theme.zip . -x node_modules/\*

That's it, enjoy your theme development!

I hope you found this useful and if you have any questions, don't hesitate to contact me on Twitter.

If you enjoyed the article, please consider sharing it on Twitter or Facebook