Skip to Main Content
Jigsaw puzzle

Compiling Tachyons CSS with Gulp

In a previous post, Laura explained the benefits of the utility-first CSS framework Tachyons from a performance and maintainability perspective, so now let's look at the Gulp process we developed to compile our stylesheets.

Installing the Dependencies

The first step is to make sure you have the Gulp CLI installed, along with NPM and Node by running the following commands through a shell with root user privileges:

apt install npm
apt install nodejs
npm install --global gulp-cli

Now switch back to the user account that will be compiling the style sheets and navigate to the root directory of the project before configuring NPM and installing some prerequisite packages with the following commands:

npm init
npm install gulp@4.0.2
npm install stylelint gulp-stylelint --save-dev
npm install --save-dev tachyons-build-css
npm install --save-dev gulp-rename
npm install --save-dev gulp-purgecss
npm install --save-dev autoprefixer@latest -D
npm install postcss-clean --save-dev
npm install

These include Gulp v. 4.0.2, a linter to validate CSS syntax, the Tachyons build process, a utility to rename files with Gulp, and finally a package to tree shake the resulting CSS so that unused styles are removed from production CSS. Note that we rerun the npm install command so that all the new packages are fully installed.

Configuring the Linter

You're likely to want to configure the linter's rules by adding something like the following to the package.json file created with the npm init command run earlier:

"stylelint": {
    "rules": {
      "block-no-empty": null,
      "color-no-invalid-hex": true,
      "unit-whitelist": [
        "em",
        "rem",
        "%",
        "s",
        "px",
        "vh",
        "deg",
        "fr"
      ],
      "no-extra-semicolons": true
    }
  },

This has been a good base setup in our experience, but you can find the documentation for the rules at the linter website linked above if required.

Writing the Gulp Tasks

Now the Gulp tasks for the compilation process need to be written. You can create/edit the necessary file by running the command nano gulpfile.js (note: it is also possible to edit both this and the package.json file in a text editor if preferred) and the following code should be added to the file:

const gulp = require('gulp');
const fs = require('fs');
const gulpStylelint = require('gulp-stylelint');
const tachyonsBuildCss = require('tachyons-build-css');
const rename = require('gulp-rename');
const purgecss = require('gulp-purgecss');
const autoprefixer = require('autoprefixer');
const postcssClean = require('postcss-clean');

gulp.task('lint-css', function lintCssTask() {
  return gulp
    .src('public/assets/src/**/*.css')
    .pipe(gulpStylelint({
      reporters: [
        {formatter: 'string', console: true}
      ],
      failAfterError: true,
      console: true
    }));
});

gulp.task('tachyons', function tachyons() {
  return tachyonsBuildCss(fs.readFileSync('public/assets/src/tachyons.css', 'utf8'), {
    from: 'public/assets/src/tachyons.css',
    to: 'public/assets/css/tachyons-min.css',
    plugins: [autoprefixer(), postcssClean()],
  }).then(result => {
    fs.writeFileSync('public/assets/css/tachyons-min.css', result.css);
  });
});

gulp.task('purgecss', () => {
  return gulp
    .src('./public/assets/css/tachyons-min.css')
    .pipe(
      purgecss({
        content: ['./public/assets/js/*.js', './templates/**/*.html', './templates/**/*.twig'],
        css: ['./public/assets/css/tachyons-min.css'],
        whitelistPatternsChildren: [/.*tns.*/, /.*ow.*/]
      })
    )
    .pipe(rename('main-min.css'))
    .pipe(gulp.dest('./public/assets/css/'));
});

gulp.task('compileCSS', gulp.series('lint-css', 'tachyons', 'purgecss'));

gulp.task('watch', function(){
  gulp.watch('public/assets/src/*.css', gulp.series('compileCSS'));
  gulp.watch(['templates/**/*.html', 'templates/**/*.twig', 'public/assets/js/*.js'], gulp.series('purgecss'));
});

Note the file paths referenced on lines 12, 23-25, 28, 34, 37-38, 43 and 49-50. These assume the uncompiled Tachyons CSS files exist in public/assets/src, the compiled CSS file are in public/assets/css, JS files are in public/assets/js, and HTML/Twig templates are in templates. There is also a whitelist defined with the whitelistPatternsChildren parameter on line 37, which is used during tree shaking to preserve things like classes added with JS that may not be present in template files.

The tasks lint-css, tachyons and purgecss can all be run independently to test the linting, Tachyons compilation and tree shaking processes respectively, and these are all combined in the command compileCSS. To run any of these tasks the SSH command syntax is gulp <task name>, so gulp lint-css for example.

Finally, in order to listen for changes to the CSS or HTML/Twig/JS files and automatically run the compile task, the gulp watch task can be run from a command prompt.

...and that's our process in a nutshell

It's worked well for us over the past couple of years and was a great learning experience to construct our own build process with Gulp and Tachyons as we previously used an app to compile SASS, though we do intend to explore Webpack in the near future. We've also written a similar set of tasks for compiling JavaScript, but that's an article for another time.