Learn SASS. From Beginner to Master !

In this article you will find examples with explanation so you can learn and master SASS.

Click to change themes.

Easily achieved with SASS.

SASS is a preprocessor that makes CSS more powerful since you can work with variables, partial, mixin, nesting,arguments and many other amazing features that you find only in programming languages.

In SASS we can use use SASS or SCSS syntax. Most people use SCSS syntax since it uses exactly the CSS syntax.

Why you should use it?

As you master CSS and your projects become bigger you will notice that you 'll have some repeating stuff all over your CSS code. SASS will give you power and simplicity as I said above.

For example let's say your client wants the color of some specific articles to be changed. Those articles have classes with many properties.
If you had stored the color in a variable thanks to SASS instead of changing it everywhere you just change the variable value .

Who should use it?

You should use it, if you believe you are in a pretty good level in CSS.

Also if you want to work as front-end developer in a company, since many companies require it.

Installing SASS for sublime text

Installing SASS for phpstorm with file watchers

Variables

In SASS we define a variable by adding the $ in front and then we call it normally as we would in a programming language COOL! So if the variable value changes it changes everywhere. No need for repeating.

//Variable :
$text-color : white;

We now can use this variable :

body {
    font-family: sans-serif;
    color: $text-color;
}

Partial(separating content into smaller files)

Also we can use partial and get content from another underscored scss file .We just put @import rule what to get.

We create a file that will hold all variables called : _variables.scss

SCSS @import works like javascript require and PHP include.We call the file where we will use it like that:

@import "variables" ;
		

Mixin

Mixin is a very important feature of SASS. We combine a lot of stuff together. We name it like this :

@mixin warning{
    background-color: orange;
    color: white ;
}

And we call it :

.warning-button{
    @include warning;
}

or to get multiple properties by this syntax

@mixin large-text{
    font:{
    size: 40px;
    weight: bold ;
	}
}

Nested mixins and classes/tags

We can nest a mixin or multiple mixing inside other mixins.

@mixin rounded{
    border-radius:6px;
    }

@mixin box{
    @include rounded;
    background-color: #000088;
}

Another powerful feature is that you nest a class/tag inside class instead of :

.navigation h2{
	color:white;
}

You write :

.navigation {
	h2 {
		color:white;
	}
}

Also you can use &. for the direct class the tag has :


.navigation{
  padding:10px;
  background-color: $nav-bg-color;
  color:$white;

  h2{
    text-align: left;
    margin: 0;
    color:$white;

    &.site-name{
      display:none;
    }
    &.nav-title{
      display:block;
    }
  }

Mixin Arguments

We can have mixins with arguments like in a programming language.

@mixin rounded($radius) {
    border-radius:$radius;
}

And we take it by passing the parameter we want at parenthesis :

@mixin box{
    @include rounded(5px);
	background-color: #000088;
}

Or a little more complicated with default values so you don't have to pass arguments :

@mixin rounded($radius : 6px) {
    border-radius:$radius;
}

@mixin box($radius : 6px, $border :1px solid black){
    @include rounded($radius);
	background-color: #000088;
    border: $border;
}

And if we call it we can only pass the argument we want and the other will be our default :

#header{
    @include box($border :1px solid pink);
}

Variable argument/arglist

With the syntax below we don't predefine how many arguments and we can pass as many as we want.Check the three dots after the argument.

@mixin box-shadow($shadows...){
    box-shadow: $shadows;
	-moz-box-shadow: $shadows;
	-webkit-box-shadow: $shadows;
}

And it works like this:


$shadow1 : 10px 10px 5px #888888;
$shadow2 : -5px 5px 3px green;

#header{
    @include box-shadow($shadow1,$shadow2);
}

Browser hacks with mixin

Using mixin you can apply specific attributes to each browser with browser hacks.

@mixin apply-to-ie-6{
    * html{
	@content ;
    }
}

So we are taking the mixin and we will apply it only to ie6.

@include apply-to-ie-6{
    body{
        color: #000088;
	}
}
Find all the browser hacks here

Switching themes with mixin

As you saw at the top with button click you can switch themes. Let' s see the code :

First, our mixins :

@mixin dark-theme{
    //Variables for dark-theme
    text-color: white;
    $theme-color:  rgb(39,40,34);
    $footer-color : black;
    $menu-item-color: white;
    $navbar-color:black;

    //Where To
    background-color: $theme-color;
    color: $text-color;
    #navbar{
    background-color: $navbar-color;
    }
    .dropdown-menu{
    background-color: $navbar-color;
    }
    #footer{
    background-color: $footer-color;
    }
    }

    @mixin light-theme{
    //Variables for light-theme
    $text-color: black;
    $theme-color: white;
    $footer-color : #53c653;
    $menu-item-color: white;
    $navbar-color:   #53c653;

    //Where To
    background-color: $theme-color;
    color: $text-color;
    #navbar{
    background-color: $navbar-color;
    }
    .dropdown-menu{
    background-color: $navbar-color;
    }
    #footer{
    background-color: $footer-color;
    color: white;
    }
    }

    @mixin default-theme{
    //Default Colors
    $text-color: black;
    $theme-color: white;
    $footer-color:#1a1aff;
    $menu-item-color: white;
    $navbar-color:#1a1aff;

    //Where To
    background-color: $theme-color;
    color: $text-color;
    #navbar{
    background-color: $navbar-color;
    }
    .dropdown-menu{
    background-color: $navbar-color;
    }
    #footer{
    background-color: $footer-color;
    color: white;
    }
    }

Then we will add our mixins to classes :

.darkTheme{
    @include dark-theme;
    }

    .lightTheme{
    @include light-theme;
    }

    .defaultTheme{
    @include default-theme;
    }

Finally the jQuery code for the button clicks :

//With those clicks we are removing the previous classes for themes
    //and we add the class we want for theme
    $('#darkButton').click(function() {
    $('body').removeClass('lightTheme defaultTheme').addClass('darkTheme');
    });

    $('#lightButton').click(function() {
    $('body').removeClass('darkTheme defaultTheme').addClass('lightTheme');
    });

    $('#defaultButton').click(function() {
    $('body').removeClass('darkTheme lightTheme').addClass('defaultTheme');
    });

@import fonts

We create a mixin that will have one argument and it's gonna @import from url the font.

Using interpolation with #{$variableHere} only.Can only be used with import.

@mixin google-fonts($font){
    $font:unquote($font);
	@import url(https://fonts.googleapis.com.css?family=#{$font});
}

Then we will store to variables the fonts :

$text-font: "Alegreya Sans", Arial, sans-serif;
$headline-font : "Titillium Web", Georgia, serif;

Finally we will call the mixins two times and pass the parameters. We then insert the font-family at h1, h2, h3, h4 with the variable :

@include google-fonts("Alegreya+Sans");
@include google-fonts("Titillium+Web");

h1, h2, h3, h4 {
    font-family: $headline-font;
}

Media queries

Same syntax as CSS media queries but more powerful since we can nest them where we want.

#main{
    width: $content-width;
	@media only screen and (max-width: 960px){
		width: auto;
		max-width: $content-width;
	}
}

Using mixins for multiple media queries

We can use mixins with multiple media queries so if we want to change something everywhere we can do it really easily.

@mixin xsmall-screens{
    @media only screen and (max-width:320px){
	    @content;
	}
}

@mixin small-screens{
    @media only screen and (max-width:480px){
		@content;
	}
}

@mixin medium-screens{
	@media only screen and (max-width:680px){
		@content;
	}
}

@mixin large-screens{
	@media only screen and (max-width:960px){
		@content;
	}
}

And we call the mixin we want where we want simple like that:

body{
    @include large-screens{
		font-size: 120%
	}
}

Using calculations with SASS

In SASS we can use arithmetic calculations.But to do so it has to be CSS syntax else it won't work correctly.Also you can do calculations between different types but they must be compatible each other.

Open your command prompt and type sass --interactive.

In some calculations you must put parenthesis or make them with variables.Also some units don't work together.

SASS functions

In CSS we already have some functions which you probably know like rgb, rgba, hsl and hsla. SASS gives us more power with more functions and the ability to create our own. 4 of the most used ones are darken, lighten, transparentize and opacify.

With the code below we are using the darken function and we are saying make the $link-color darker by 15% when we hover on it.

a{
    color: $link-color;

	&:hover{
		color: darken($link-color,15%);
	}
}

Lighten function:

@mixin warning{
    background-color: orange;
	color: white ;

	&:hover{
		background-color: lighten(orange,30%);
	}
}

Hover on the orange button below to see what we did easily with the above mixin.

Also we have transparentize and opacify functions.Opacity is just the opposite of transperency. If something is 100% opaque,then it's 0% transperent.

#main-menu {
    a{
        color:$menu-item-color;
		padding: 6px 8px;
		border-bottom: 1px solid transparentize(#fefefe,1);
		transition: border-bottom 0.5s;
		transition-timing-function: ease-in-out;

		&:hover{
			border-bottom: 1px solid opacify(#fefefe,0.5);
		}
	}
}

Hover at menu bar at top to see how it works.

Creating our own SASS functions

Just create a file _functions.scss and call it at main.scss @import "functions" ; . Then like mixins by saying @function name and we return value with @return.Let's see them in action :

Here with this function we will have em if we give pixels :

@function em($pixels,$context:16px){
	@return ($pixels/$context)*1em;
}

A function that has default 12 columns 100% page width and 1% gap between the columns and return equally split columns.

@function col-width($columns:12,$page-width:100%,$gap:1%){
	@return ($page-width - $gap*($columns)) / $columns;
}

Below we have at main.scss six equally split columns by using the function col-width we created:

.sidebar {
	display: inline-block;
	width:2 * col-width();
	background-color: lightgray;
}

Inheritance with @extend

Sometimes we need to have a class that also has something similar with another class. We need to to remember using both classes or more to achieve that.SASS makes that easy with inheritance by using @extend inheritFrom.

.error{
	color: red;
}

.critical-error{
    @extend .error;
	border: 1px solid red;
	font-weight: bold;
}

Or we can use any combination we want for example @extend + @include, inheritance and mixin :

.cta-button{
	@extend .warning-button;
	@include rounded;
}

Side note for extend :

You can't have extend inside a media query if the class is NOT in the same media query.

Wrong

.cta-button{
	@extend .warning-button;
	@include rounded;
}

@media screen and (min-width: 960px) {
	.super-cta-button{
		@extend .cta-button;
	}
}

Correct

@media screen and (min-width: 960px) {
	.foo{
		border-bottom-color: blue;
	}
	.super-cta-button{
		@extend .foo;
	}
}

@extend only selectors

We can use selector that is not going to be generated in CSS but only in SASS. We use that if we don't want to use this class anywhere in CSS but only to extend it. Instead of using . or # we use % at start.

%highlight{
	font-style: italic;
}

.sub-title{
	@extend %highlight
}

Also we can say to SASS if this class exists use it else do nothing with this syntax :

.sub-title{
	@extend %highlight;
	@extend .doIExist !optional;
}

@extend vs @mixin

A lot of people say that they work almost the same so why to use each of them? That's true but let's see what code @extend generates and what @mixin at CSS.

SASS code and @extend

.error{
	color: red;
}
.critical-error{
    @extend .error;
	border: 1px solid red;
	font-weight: bold;
}

Generated code at CSS :

.error, .critical-error {
	color: red;
}

.critical-error{
	border: 1px solid red;
	font-weight: bold;
}

SASS code and @mixin :

@mixin warning-button{
    @include warning;
}

.warning-button{
	@include warning-button;
}

.cta-button{
    @include warning-button;
}

Generated at CSS with @include :

.warning-button {
    background-color: orange;
    color: white;
}

.warning-button:hover {
    background-color: #ffdb99;
}

.cta-button {
    background-color: orange;
	color: white;
}

.cta-button:hover {
    background-color: #ffdb99;
}

Conclusion @extend too many selectors but not replicated styles. On the other side @mixin fewer selectors but duplicated styles. Don't forget that @extend has some limitations as we said above at inheritance. Though @mixin generates more code with gzipping you won't have any performance problems but choose what is more comfortable for you.

@if and @else directives

In SASS we have if and else directives that work exactly like programming languages. If you are not familiar with these conditions you can understand it below.

We are setting a variable $contrast : high. If $contrast == high then color: black. Else if $contrast == low then color #999. In all other cases color: $text-color .

$contrast : high;
body {
	@if ($contrast==high){
		color : black;
	}
	@else if $constrast == low{
		color : #999;
	}
	@else{
		olor:$text-color;
	}
}

@for loops

If you are familiar with programming languages you probably understand how loops work. In any case a loop is fundamental for all programming languages.

If you had for example 10 clients and wanted to see on screen all their names instead of showing one by one manually you just create a loop that will search and show all of them.

Let's see it in SASS how it works :

So in our main.scss file we are saying for variable $i start from 1 though 6 which will count 1,2,3,4,5,6 create classes .textsize-1,.textsize-2,.textsize-3,.textsize-4,.textsize-5,.textsize-6 with font-size increment by 5px for each class.

@for $i from 1 through 6 {
    .textsize-#{$i}{
    font-size: $i * 5px;
    }
}

And the result in CSS will be :

.textsize-1 {
    font-size: 5px; }

.textsize-2 {
    font-size: 10px;
}

.textsize-3 {
    font-size: 15px;
}

.textsize-4 {
    font-size: 20px;
}

.textsize-5 {
    font-size: 25px;
}

.textsize-6 {
    font-size: 30px;
}

See that with three lines in SASS we created 12 lines in our CSS.

@each loops with lists

Each loops are the most common used in SASS. We use them with lists, which in SASS is a variable that has more than one values separated by commas.

$images: cat, dog, bird;
@each $image in $images{
    .#{$image}-animal{
    background-image: url('images/#{$image}.png');
    }
}

CSS result :

.cat-animal {
    background-image: url("images/cat.png");
}

.dog-animal {
    background-image: url("images/dog.png");
}

.bird-animal {
    background-image: url("images/bird.png");
}

Maps with each loop(they are like associative arrays/dictionaries)

After version 3 SASS was added map data structure. In simple words map is a box, container whatever you want to call it that you have keys in it with values.

Imagine you have a box that you store your keys. Inside we have 3 keys with names for 3 different purposes.

//Name of the box
$map : (
    //Key  / Value
    garage : blue,
    house : red,
    cellar : green
);

So let's say your house is ultra futuristic and by writing HTML/CSS you can open doors when you add the correct color to a class :

.garage{
    color : map-get($map,garage);
}
.house{
    color : map-get($map,house);
}

.cellar{
    color : map-get($map,cellar);
}

If we wanted to open all your doors in your amazing house we will do :

@each $key, $keyColor in $map{
    .#($key){
        color: $keyColor;
    }
}

And at CSS with the final loop the result would be :

.garage {
    color: blue;
}

.house {
    color: red;
}

.cellar {
    color: green;
}

@while loops

While loop is another kind of loop that says as long as the condition is true continue the loop.

Below we have $j : 2 and we are saying while $j <= 10 increase width by $j * 10% and $j by 2. So when we reach at $j : 10 the loop will stop.

WARNING!If you don't increase $j also the loop won't stop.

$j : 2;
@while $j <= 10{
    .picture-#{$j}{
    width: $j *10%;
    }
    $j: $j + 2;
}

CSS result :

.picture-2 {
    width: 20%;
}

.picture-4 {
    width: 40%;
}

.picture-6 {
    width: 60%;
}

.picture-8 {
    width: 80%;
}

.picture-10 {
    width: 100%;
}
George Tourtsinakis
I'm George Tourtsinakis a Full Stack Developer. I hope you enjoyed this article and feel free to contact me at www.besmartbesimple.com.