Using Gulp to Compile Sass Liquid Tags

How to use Gulp to compile Sass liquid tags while using Autoprefixer without any syntax errors using only a couple gulp plugins.

Goals

Using gulp:

  • Compile sass to a style.css.liquid file
  • Compile sass Liquid tags
  • Run Autoprefixer with liquid tags

Tools needed

See the complete gulpfile here

Compile Sass to Liquid

By default sass will compile to the file ‘style.css’ in the destination directory you specify. That’s not what we want, instead we want a file called ‘style.css.liquid’ in the assets folder. The gulp-concat plugin will work for this, it’s generally used for taking multiple files and concatenating them into one but it can also be used to just rename a file. Basically what we’ll do is compile sass, gulp-concat the compiled file to ‘style.css.liquid’, then pipe it to the assets folder.

Simple gulp task to compile a regular sass file to ‘style.css.liquid’.

gulp.task('compilesass', function() { // root sass file (contains all your includes) return gulp.src('./sass/style.scss') // compile SASS to CSS .pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError)) // change the file name to be a liquid file .pipe(concat('style.css.liquid')) // save the file to the theme assets directory .pipe(gulp.dest('./assets/')); });

Sass escape string

Adding liquid tags like this can cause a syntax error while compiling. The following line of sass will not compile:

background-image: url({{ \'awesome-hero-image.jpg\' | asset_url }});

Luckily sass has a built in method for escaping strings to allow them to be compiled out to CSS. To escape a string wrap it in:

#{' ... '}

Escape string for liquid tag in sass:

background-image: url(#{'{{ \'awesome-hero-image.jpg\' | asset_url }}'});

The CSS output will be:

background-image: url({{ \'awesome-hero-image.jpg\' | asset_url }});

Now the previous gulp task will successfully compile sass to CSS.

More about escaping strings in sass

Autoprefixer escape string

Now that the sass compiler can handle liquid tags we want to use Autoprefixer for adding vendor prefixes to help with browser support. Using the gulp-autoprefixer plugin it’s easy to pipe the CSS output from sass into autoprefixer, but the same problem as before comes up. The liquid tags are escaped as strings in sass, but the CSS output of those strings will cause syntax errors again but this time while autoprefixer runs. The string needs to be escaped again to successfully run autoprefixer.

Sass compiles this, but autoprefixer fails:

background-image: url(#{'{{ \'awesome-hero-image.jpg\' | asset_url }}'});

To get around this we need to wrap an additional set of double quotes around the liquid tag so that the output from sass will still be a string wrapped in double quotes.

background-image: url(#{'"{{ \'awesome-hero-image.jpg\' | asset_url }}"'});

Sass will compile this to (note the quotations and escaping characters):

background-image: url("{{ \'awesome-hero-image.jpg\' | asset_url }}");

The output from autoprefixer will be the same:

background-image: url("{{ \'awesome-hero-image.jpg\' | asset_url }}");

Gulp Replace

This is almost what we want, everything compiles and runs, but our final style.css.liquid output isn’t quite valid CSS. The extra double quotes around the liquid tag need to be removed in order to make it valid. When Liquid compiles to CSS on shopify it will turn

{{ \'awesome-hero-image.jpg\' | asset_url }}

into a url pointing at the awesome-hero-image.jpg, but those extra double quotes will remain in the output from liquid causing an invalid value.

The gulp-replace plugin allows us to pipe in the output from autoprefixer and replace every instance of a string with another string, just like the `string.replace` method in Javascript. So in our gulp task, after sass, autoprefixer, and concat run, we’ll add a replace method to replace every instance of “{{ with just {{ and every instance of }}” with }}.

// remove the extra set of quotations used for escaping the liquid string .pipe(replace('"{{', '{{')) .pipe(replace('}}"', '}}'))

We end up with a simple gulp task that looks like this:

gulp.task('compilesass', function() { // root SASS file (contains all your includes) return gulp.src('./sass/style.scss') // compile SASS to CSS .pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError)) // add vendor prefixes .pipe(autoprefixer()) // change the file name to be a liquid file .pipe(concat('style.css.liquid')) // remove the extra set of quotations used for escaping the liquid string .pipe(replace('"{{', '{{')) .pipe(replace('}}"', '}}')) // save the file to the theme assets directory .pipe(gulp.dest('./assets/')); });

Now the final output from the gulp task will be able to be compiled by liquid and end up being valid CSS. It feels like a lot of unnecessary steps at first but it’s quite straightforward once you get your head around the way the different environments handle things.