CSS pre-processors are very popular because they let you write CSS in a custom syntax to later be compiled to the vanilla CSS that our browsers require. Because of this compilation, the pre-processor can add a whole bunch of advanced features that help us write more efficient and modular styles with the peace of mind that in the end the browser will be able to support it.

For this tutorial, we will be using node-sass to compile our Sass into CSS files.


  1. Node and NPM installed. If you don't have them installed, follow our how to install Node guide.

Installing node-sass

Now let's get started. To install node-sass, run this command:

npm install node-sass

Here is the confusing part, Sass has two syntaxes, one named Sass, and another named SCSS. For the purposes of the this tutorial, we will be working with the SCSS syntax. Feel free to learn about the differences between the two if you're curious.

With node-sass installed, you should be able to run this command to get a CSS file from a SCSS file:

node-sass input.scss output.css

Alternatively, you can use the --watch option to continuously watch a file or directory for changes and automatically compile if changes are detected:

node-sass input.scss output.css --watch


It wouldn't be a CSS pre-processor without variables. Variables in SCSS function pretty similarly to programming languages where they hold whatever data you want in them like a string or number.

Here's how variables look like in SCSS:

$text-font: "Open Sans", sans-serif; $success-green: #00a55e; .heading { font-family: $text-font; background-color: $success-green; border-radius: 0.25rem; }

And here's the resulting CSS:

.heading { font-family: "Open Sans", sans-serif; background-color: #00a55e; border-radius: 0.25rem; }

No surprises here, when you define a variable and then use it later on, the variable will be replaced by the value of the variable at compilation time.


Mixins in SCSS are comparable to functions in programming. When you define a mixin, you can optionally have it accept parameters that you can use to build your styles. Let's look at an example:

@mixin circle($size, $color) { width: $size; height: $size; border-radius: 50%; background-color: $color; } .small-green-circle { @include circle(2rem, green); } .big-purple-circle { @include circle(4rem, purple); }

Which compiles to:

.small-green-circle { width: 2rem; height: 2rem; background-color: green; } .big-purple-circle { width: 4rem; height: 4rem; background-color: purple; }

Ever find yourself constantly using vendor prefixes? You can included them all in a single mixin so you don't need to keep repeating yourself, like so:

@mixin transform($property) { -webkit-transform: $property; -ms-transform: $property; -moz-transform: $property; transform: $property; } .box { @include transform(rotate(90deg)); }
.box { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); -moz-transform: rotate(90deg); transform: rotate(90deg); }

Pretty time-saving if you find yourself using these very often!


The extend feature in Sass exists for situations where you want inherit common styles but then add more styles.

Let's say you have styles around images but some you want to the left, and others to the right. Your styles could look something like this:

.image { box-shadow: 0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.25); padding: 0.5rem; } .image--left { @extend .image; float: left; } .image--right { @extend .image; float: right; }

This compiles to:

.image, .image--left, .image--right { box-shadow: 0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.25); padding: 0.5rem; } .image--left { float: left; } .image--right { float: right; }

Now in your HTML, you would only need to apply the classes image--left or image--right to get the full effect.


As you might have noticed, CSS doesn't natively support nesting of styles. If you want styles to only apply when inside other styles, you must write something like this:

.class1 .class2 { color: red; }

That is hard to maintain, especially as the codebase gets bigger. Sass offers much nicer syntax in that you can literally nest one inside another, like so:

.class1 { .class2 { color: red; } }

Now you can visually see that the styles on class2 will only apply when it is nested inside an element with class1 as a class.

As expected, this compiles to this:

.class1 .class2 { color: red; }

Ampersand Character

Alternatively, you can use the & character, which in Sass refers to the parent selector, you rewrite the previous Sass but in reverse, like so:

.class2 { .class1 & { color: red; } }

It might be confusing when you first see it, but if you replace the & with the parent selector, you will see that we get the original styles back.

Here is a potentially more eye-opening example of using &, imagine you have these button styles:

.button { &:visited { color: red; } &:hover { color: blue; } &:active { color: green; } }

Look how easy it is to style a button's pseudo classes. You can just nest each class under .button and add the styles you want inside.

It will be compiled to this:

.button:visited { color: red; } .button:hover { color: blue; } .button:active { color: green; }


Because Sass already offers the use of variables, it is only natural that in addition to simply outputting the variables, that if you're working with numbers, that you can perform operations using them.

$container-width: 40rem; .container { width: $container-width; } .container--half { width: $container-width / 2; } .container--quarter { width: $container-width / 4; }

As expected, this compiles to:

.container { width: 40rem; } .container--half { width: 20rem; } .container--quarter { width: 10rem; }


Sass offers built-in functions to do calculations and operations on your behalf. They range from color calculations, math-related ones like rounding and getting random numbers, and manipulating strings.

Let's look at one of their color-based ones, lighten:

$primary-color: red; .darkened-red { background-color: darken($primary-color, 30%); }

This compiles to:

.darkened-red { background-color: #660000; }


Sass is a very popular CSS pre-processor because of how powerful and flexible it is. It supports two different syntaxes so you can even pick your favorite. Learning a pre-processor is worth the time investment because it makes writing styles in general much faster and more efficient.


Recommended Tutorial »
Copyright © 2017 - 2024 Sabe.io. All rights reserved. Made with ❤ in NY.