Picture of Brian Love wearing black against a dark wall in Portland, OR.

Brian Love

LESS to SASS

Auf wiedersehen LESS, Hallo SASS! In this post I am going to cover:

Why LESS to SASS?

I’m switching from LESS to SASS, and here’s why:

How to go from LESS to SASS

Migrating from LESS to SASS is fairly easy due to the similarity of the syntax. You could run a bunch of regular expressions, but it’s even easier to use the less2sass ruby gem.

Install less2sass:

$ gem install less2sass

Convert your less files to scss:

$ less2sass variables.less _variables.scss

Next, you will want to be sure that you have the SASS Ruby Gem installed. This is required to compile your SASS to CSS. There is a new libsass C library that is being released, which is a high performance library for compiling SASS, but we will be using the Ruby Gem until libsass is stable. You can install it via the command line:

$ sudo gem install sass

Bootstrap 3 SASS

Although Bootstrap 4 is built using SASS, Bootstrap 3 was built using LESS. Thankfully, there is an official port from LESS to SASS.

I’ve added the bootstrap-sass repository as a submodule in my git project:

git submodule add https://github.com/twbs/bootstrap-sass

I then modified my main.scss file to import the Bootstrap SASS file:

@import '/lib/bootstrap-sass/assets/stylesheets/bootstrap';

There are some differences between using Bootstrap with LESS versus the SASS version. These are just a few of the ones that I ran into with my current project.

Compiling SASS

There are a lot of options when it comes to compiling SASS to CSS, so I will not even try to cover them all here. Instead, I will focus only on using Grunt and the grunt-contrib-sass package.

First, we need to install the grunt-contrib-sass node package. To do so, I have added the following dependency to my package.json file.

{
  "name": "My Application",
  "version": "1.0.0",
  "author": {
    "name": "Brian Love",
    "email": "foo@bar.com"
  },
  "dependencies": {
    "grunt-cli": "latest",
    "grunt-contrib-watch": "latest",
    "grunt-contrib-sass": "latest"
  }
}

Now that I have specified the grunt-contrib-sass package dependency for my application, I can install/update the necessary modules.

$ npm update

Using the grunt-contrib-sass node package we can set up a sass task in our Gruntfile.coffee file. The task compiles the main.scss and ie-8.scss files. Note that I am using the grunt-contrib-sass package. The node-sass node package is a wrapper around the high performance libsass C library, but it is not quite ready for prime time (at the time of this writing).

Here is what my Gruntfile.coffee file looks like:

gruntFunction = (grunt) ->

 gruntConfig =
  sass:
  dist:
  files:
   'css/main.css': 'css/src/main.scss'
   'css/ie-8.css': 'css/src/ie-8.scss'
 watch:
  sass:
   files: ['css/src/*.scss']
   tasks: ['sass']

 grunt.initConfig gruntConfig

 grunt.loadNpmTasks 'grunt-contrib-sass'
 grunt.loadNpmTasks 'grunt-contrib-watch'

 grunt.registerTask 'default', [
  'sass'
 ]

 null

module.exports = gruntFunction

Now, it’s easy to compile my SASS via the default task:

$ grunt

Or, to let the watch task run the sass< task when a .scss file is modified:

$ grunt watch

Adding the PostCSS Autoprefixer

The PostCSS autoprefixer is required when using bootstrap-sass. The autoprefixer will prepend the necessary browser prefixes to your CSS based on the browser list you specify (and based on your business needs). I have decided to target the following browser list:

This browser list profile will instruct the autoprefixer as to the level of prefixes that are necessary. You would be surprised how few CSS3 properties need to be prefixed still. For example, there is no real reason to prefix box-shadow or border-radius. The best part of the autoprefixer is that it uses the data from caniuse.com, so it’s always up to date. And, now you just write pure W3C CSS3 code without the worry of vendor prefixes!

The autoprefixer is part of the PostCSS library, so we need to specify the package via our package.json file:

{
  "author": {
    "email": "foo@bar.com",
    "name": "Brian Love"
  },
  "dependencies": {
    "autoprefixer-core": "latest",
    "grunt-cli": "latest",
    "grunt-contrib-sass": "latest",
    "grunt-contrib-watch": "latest",
    "grunt-postcss": "latest"
  },
  "name": "My Application",
  "version": "1.0.0"
}

Now we need to update the installed node modules so that the grunt-postcss and autoprefixer-core packages are installed.

$ npm update

Next, we need to update our Gruntfile.coffee file to include a postcss task, which uses the autoprefixer-core processor. The browsers property is an array of values based on the browserslist project.

gruntFunction = (grunt) ->

gruntConfig =
 pkg:
  grunt.file.readJSON 'package.json'

 sass:
  dist:
   files:
    'css/main.css': 'css/src/main.scss'
    'css/ie-8.css': 'css/src/ie-8.scss'

postcss:
 options:
  map: true
  processors: [
   require('autoprefixer-core')(
    browsers: [
     'last 2 versions'
     '> 5% in US'
     'iOS 7'
     'Firefox ESR'
    ]
   )
  ]
 dist:
 src: 'css/*.css'

 watch:
  sass:
   files: ['css/src/*.scss']
   tasks: ['sass', 'postcss']

 grunt.initConfig gruntConfig

 grunt.loadNpmTasks 'grunt-contrib-sass'
 grunt.loadNpmTasks 'grunt-postcss'
 grunt.loadNpmTasks 'grunt-contrib-watch'

 grunt.registerTask 'default', [
  'sass'
  'postcss'
 ]

 null

module.exports = gruntFunction

Running the grunt command again will re-build the main.css file with the autoprefixer processing the CSS for any necessary browser prefixes.

$ grunt

LESS Hat to Bourbon

Bourbon is a nice lightweight mixin library for SASS. So, the last step for me was to switch from LESS Hat to Bourbon. I personally chose to use Bourbon over Compass because I am using Bootstrap and do not need many of the features in Compass.

git submodule add https://github.com/thoughtbot/bourbon

And then we import Bourbon into our main.scss project file:

@import '/lib/bourbon/app/assets/stylesheets/bourbon';

There were some differences between LESS Hat and Bourbon that I will briefly point out. I’m sure there are others, but here are a couple of necessary changes that I ran into.

Well, my experience migrating from LESS to SASS was a ton of fun, and I’m really excited about using SASS going forward!