Episode 5 of 6

Compiling SASS

Install and configure the grunt-contrib-sass plugin to automatically compile SASS files into CSS.

Compiling SASS

SASS (Syntactically Awesome Style Sheets) is a CSS preprocessor that adds variables, nesting, mixins, and more to CSS. But browsers cannot read SASS — it must be compiled into regular CSS. In this episode you will set up the grunt-contrib-sass plugin to compile your SASS files automatically.

Why Use SASS?

SASS FeatureWhat It DoesExample
VariablesStore reusable values$primary: #3498db;
NestingNest selectors inside each other.nav { a { color: #fff; } }
MixinsReusable blocks of styles@mixin flex-center { ... }
PartialsSplit CSS into modular files@import 'variables';
MathPerform calculationswidth: 100% / 3;

Prerequisites: Ruby SASS or LibSass

The grunt-contrib-sass plugin requires Ruby and the sass gem installed on your system. Alternatively, you can use grunt-sass which uses LibSass (the C/C++ implementation) and does not require Ruby.

# Option A: Ruby SASS
gem install sass

# Option B: Use grunt-sass with node-sass instead
npm install grunt-sass node-sass --save-dev

We will use grunt-contrib-sass (Ruby SASS) in this tutorial, but the configuration is nearly identical for grunt-sass.

Step 1: Install the Plugin

npm install grunt-contrib-sass --save-dev

Step 2: Configure the Task

Add the sass task to your Gruntfile.js initConfig:

sass: {
    dev: {
        options: {
            style: 'expanded',
        },
        files: {
            'dist/css/styles.css': 'src/scss/styles.scss',
        },
    },
    prod: {
        options: {
            style: 'compressed',
        },
        files: {
            'dist/css/styles.min.css': 'src/scss/styles.scss',
        },
    },
},

Understanding the Configuration

The files property uses a destination: source format (the reverse of src/dest used in concat). Each key is the output file path and the value is the source SASS file.

TargetOutput StyleOutput FileUse Case
devexpanded (readable)dist/css/styles.cssDevelopment — easy to read and debug
prodcompressed (minified)dist/css/styles.min.cssProduction — smallest possible file size

SASS Output Styles

StyleDescription
nestedIndented to reflect SASS nesting structure
expandedStandard CSS formatting — each property on its own line
compactEach rule on a single line
compressedFully minified — all whitespace removed

expanded output

body {
    font-family: Arial, sans-serif;
    background: #ecf0f1;
    color: #333;
    margin: 0;
    padding: 20px;
}

compressed output

body{font-family:Arial,sans-serif;background:#ecf0f1;color:#333;margin:0;padding:20px}

Step 3: Load the Plugin and Register Tasks

grunt.loadNpmTasks('grunt-contrib-sass');

grunt.registerTask('default', ['concat', 'sass:dev']);
grunt.registerTask('build', ['concat', 'sass:prod']);

The default task compiles SASS in expanded (readable) mode for development. The build task compiles in compressed mode for production.

Step 4: Run It

# Development build
grunt

# Production build
grunt build

# Just compile SASS (dev target)
grunt sass:dev

# Just compile SASS (prod target)
grunt sass:prod

Compiling Multiple SASS Files

sass: {
    dev: {
        options: { style: 'expanded' },
        files: {
            'dist/css/main.css': 'src/scss/main.scss',
            'dist/css/admin.css': 'src/scss/admin.scss',
            'dist/css/blog.css': 'src/scss/blog.scss',
        },
    },
},

Each key-value pair in the files object compiles one SASS file to one CSS file. You can have as many pairs as you need.

Using Dynamic File Mappings

sass: {
    dev: {
        options: { style: 'expanded' },
        files: [{
            expand: true,
            cwd: 'src/scss/',
            src: ['*.scss'],
            dest: 'dist/css/',
            ext: '.css',
        }],
    },
},
PropertyPurpose
expand: trueEnable dynamic mapping
cwdCurrent working directory for source files
srcGlob pattern to match source files
destOutput directory
extChange the file extension on output files

Dynamic mappings automatically compile any .scss file found in the source directory. Add a new SASS file and it is compiled without changing the Gruntfile.

Updated Gruntfile So Far

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        concat: {
            options: { separator: ';\n' },
            dist: {
                src: ['src/js/*.js'],
                dest: 'dist/js/bundle.js',
            },
        },

        sass: {
            dev: {
                options: { style: 'expanded' },
                files: {
                    'dist/css/styles.css': 'src/scss/styles.scss',
                },
            },
        },
    });

    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-sass');

    grunt.registerTask('default', ['concat', 'sass']);

};

Key Takeaways

  • grunt-contrib-sass compiles SASS/SCSS files into regular CSS
  • The files property uses destination: source format (reversed from src/dest)
  • Four output styles: nested, expanded, compact, compressed
  • Use different targets for development (expanded) and production (compressed) builds
  • Dynamic file mappings with expand: true automatically handle new files without config changes
  • Run specific targets with grunt sass:dev or grunt sass:prod