Live-updating Sass in Eleventy and WordPress with Gulp and BrowserSync
Tags: sass, 11ty, wordpress, gulp
Published: 2021-09-26 19:52:11

---
title: Live-updating Sass in Eleventy and WordPress with Gulp and BrowserSync
published: true
date: 2021-09-14 00:00:00 UTC
tags: sass, 11ty, wordpress, gulp
canonical_url: https://jonathanland.design/articles/live-updating-sass-in-eleventy-and-wordpress-with-gulp-and-browsersync
---

I love Sass. Not SCSS, mind you. I'm talking about the original Syntactically Awesome Stylesheet syntax, AKA [The Indented Syntax](https://sass-lang.com/documentation/syntax#the-indented-syntax). It's not that I'm particularly old-school, or that I don't see that value in SCSS being a superset of CSS. It's just that I hate looking at extraneous pointy shapes in my code, and Sass gets rid of the sharpest, pointiest ones — `{`, `}`, and of course `;`. It might seem a weird thing to care about, but being a visual designer is, among some wonderful things, a bit of a curse.

Needless to say, I'm always on the lookout for the best way to integrate Sass in whatever environment I happen to be working. The best <abbr title="Developer Experience">DX</abbr>, in my opinion, it when style changes are injected on to the page without needing to reload. It's the kind of thing you get with <abbr title="Hot Module Reloading">HMR</abbr>-capable build tools (Vue CLI, Vite, etc.), and the result is instant feedback with minimal interruption.

## Environment

When I'm building with non-JavaScript-centric tooling, [Gulp](https://gulpjs.com/) has been my trusty go-to for years. I use it to orchestrates the bundling of my CSS and JavaScript, and every time I think to myself "Yeah, I could probably do that in Node scripts", I end up finding a new reason to stick with it.

One tool I consistently use with Gulp is [BrowserSync](https://browsersync.io/). If you're not familiar, BrowserSync is a nodeJS utility that sets up a local server. It's the engine behind [Eleventy's watch mode](https://www.11ty.dev/docs/watch-serve/), and can do a ton of cool things to speed up development. Critically, the [`watch` option](https://browsersync.io/docs/options#option-watch) allows BrowserSync to update the browser, whenever it detects a change to files. An amazing sub-feature of this watcher is that it can inject CSS changes without reloading, very similar to HMR.

## Eleventy

The setup for Eleventy was a bit tricky to figure out, but works very well. The gist of it is to send the bundled files directly to the output folder (Elevnety's default being `_site`), and tell Eleventy's BrowserSync instance to watch for changes. It looks like this:

```js
// gulpfile.js

const gulpSass = require('gulp-sass')(require('sass'))

const sass = () => gulp.src('path/to/sass/files')
  .pipe(gulpSass.sync({ outputStyle: 'compressed' }))
  // ... fun gulp stuff
  .pipe(dest('./_site/assets/css'))


// .eleventy.js

module.exports = (eleventyConfig) => {
  // ... fun eleventy stuff
  eleventyConfig.setBrowserSyncConfig({
    watch: true,
  })
}

```

This extends Eleventy's BrowserSync settings, adding the `watch` option on the project's folder. And the wonderful thing about this is that, by default, BrowserSync will inject CSS changes rather than reload the page.

It took me while to get to this because I was previously using Eleventy's `addPassthroughCopy` to send bundled assets to the `_site` folder. I thought that would be the only way to have the page update every time a change was made. But it turns out all I needed to do was tell the BrowserSync instance itself to watch for changes.

## WordPress

Another great feature of BrowserSync is the ability to [proxy existing local servers](https://browsersync.io/docs/options#option-proxy) and watch their underlying folder for changes. Assuming my local WordPress server is at `http://website.local` (I use [Local](https://localwp.com/) for all my WordPress sites), I can add the following to Gulp:

```js
// gulpfile.js

const browserSync = require('browser-sync').create()

exports.serve = () => {
  browserSync.init({
    proxy: 'http://website.local',
  })
  gulp.watch('path/to/sass/files', sass)
}

const sass = () => gulp.src('path/to/sass/files')
  .pipe(gulpSass.sync({ outputStyle: 'compressed' }))
  // ... fun gulp stuff
  .pipe(dest('output/path/for/css/files'))
  .pipe(browserSync.stream())

```

First I initialize a BrowserSync instance at the top of my `serve` function, and then I pipe the `stream` method to the `sass` stream. Now, instead of pointing my browser at `http://website.local`, I can run `gulp serve` and go to `http://localhost:3000` (the address and port are configurable, but I tend to stick with the default on this). Any time Gulp processes my Sass, it will stream (i.e. inject) the changes automatically in the browser.