Mastering Advanced Sass & Workflow with Zurb Foundation (Part 1)

By Harry Manchanda

You know CSS; you got into Sass as someone told you that it is that better CSS with wings. I get to tell you that you heard it right! Then you started learning it, explored through this Starter Guide and learned basic topics like variables, mixins, nesting, and imports.

After learning Sass basics, the question’s on your mind might be,

  • What are the advanced topics moving ahead?
  • How do I implement all of this in a web framework?
  • How do I create websites out of it?
  • How do I create WebApps out of it?
  • Does Sass have those conditional, loops, functions like other languages?

This is a two part article series where in the first half, we will look to cover advanced Sass topics like data types, maps, if directive, loops, and most importantly Vanilla functions such as colors, strings, lists and numbers. If you are just starting out in Sass, then also please follow along as I have some links in the below section which will help you get started

Take a look at our other Sass articles

Moving ahead, to the second half we will cover about on how to implement all of this learning within the workflow of the most advanced responsive front-end framework, Zurb Foundation.

Basics & Installation

Sass is a preprocessor that will produce clean and efficient CSS code and will cut your development time to half (if not more). Sass has more functionality than traditional CSS. Yes, it’s true that Vanilla CSS has its own fun, but you can’t reject the fact that stylesheets are getting larger, complex and harder to maintain day by day.

Please note that this article assumes you to have basic knowledge of Sass in general. If that’s not the case with you, then you should start here with this Basic Guide for starting out. For Sass Mixins, you can check out this tutorial here by Samuel Oloruntoba

If you are looking to Install Sass, then click here.

Sass Data Types

Sass is a Programming Language. Isn’t it? Data types exist in most of the programming languages, and Sass is no exception to that. A data type is a way to classify data into specific categories for different purposes.

Sass data types may not seem very useful to you right now, but their’s main strength is when they applied to other features that Sass offers. Let’s look into all the eight data types that exist in Sass.

/* Strings */
$a: harry; // Unquoted string
$b: 'harry'; // Single Quoted string
$c: "harry"; // Double Quoted string

/* Numbers */
$d: 1; // Integer
$e: 1.5; // Float
$f: 1rem; // rem Values (CSS units)
$g: 2em; // em Values (CSS units)
$h: 5px; // px Values (CSS units)

/* Booleans */
$i: true; // True
$j: false; // False

/* Null */
$k: null; // Null

/* Lists */
$l: 'Raleway','Open Sans','Lato'; // comma separated elements
$m: 3px 4px 8px; // space separated elements
$n: 'Roboto' 'Ubuntu', 15px 1.3em; // multi-list with two lists

/* Maps */
$o: (
'font-family': 'Open Sans',
'font-size': 2rem,
'color': blue
); // We will talk about maps later on. 

/* Colors */
$p: DarkBlue; // Color Name
$q: #00008B; // Hex
$r: rgba(255, 0, 0, 0.5); // RGB/RGBA
$s: hsl(10, 30%, 50%); // HSL/HSLA

/* Function References */
$t: darken($q); // We will talk about functions later on.

Sass Maps

Version 3.0 Sass brought a new data type called map. It may be confusing for some but merely think of it as key value pairs. There are a lot of functions by default (which we will discuss later on) that lets you manipulate maps.

Please note that the keys must be unique and values can include any of Sass data-type, including lists and other maps nested within it.

$map1 : (
  'Key': 'Value',
  'AnotherKey': 3rem
); // Key Value Pair

$map2 : (
  'key1' : 'value1',
  'key2' : 'value2',
  'key3' : 'value3'
); // Another Key value Pair

$map3 : (
  'KeyName': 'You can't escape me',
  'String':  string,
  'Number':  234,
  'List':  ( width 2s, height 2s, transform 2s ),
  'NestedMap':  (
    'NestedKey':  'I am deeply nested',
    'url':  './images/harry.svg',
    'Width':  300px
  ); // Nested Map
); // Key value pair with lists and map's nested in it

@If control directive

Ability to evaluate the boolean logic is an essential feature of every programming language, and Sass is no exception. The @if control directive takes a Sass expression to process it’s block of styles if the expression manages to return anything other than false or null.

Relational operators (<, >, <=, >=) are supported for numbers data types, whereas equality operators (==, !=) are supported for all data types. According to official docs,

The @if statement can be followed by several @else if statements and one @else statement. If the @if statement fails, the @else if statements are tried in order until one succeeds or the @else is reached.

@if ($prop == margin) {
  margin: $spacer * $global-margin;
} @else if ($prop == padding) {
  padding: $spacer * $global-padding;
} @else {
  @warn 'No Property Specified';
}

If() function

You can also use if else condition like a ternary operator also thanks to the Sass if function. According to official docs,

The built-in if() function allows you to branch on a condition and returns only one of two possible outcomes. It can be used in any script context. The if function only evaluates the argument corresponding to the one that it will return — this allows you to refer to variables that may not be defined or to have calculations that would otherwise cause an error (E.g. divide by zero).

Check out this below example in which we see whether the condition has met or not. If yes, then we will show green background color, or else it will be a purple background.

@mixin item-styles($condition) {
  // if true then green, else purple
  $color: if($condition, green, purple);
  .items li {
    background-color: $color;
  }
}

// Show for true condition aka green
@include item-styles(true);

@media screen and (min-width: 800px) {
  // Show for false condition aka purple
  @include item-styles(false);
}

And here is the Generated CSS output,

.items li {
  background-color: green;
}

@media screen and (min-width: 800px) {
  .items li {
    background-color: purple;
  }
}

Loops in Sass

A loop statement allows you to iterate a statement or group of statements multiple times, which allows the code to execute repeatedly. Again, Loops in Sass is not any exception from other languages. Sass provide us with three different kinds of loops to iterate over collections

  1. @for loop
  2. @each loop
  3. @while loop

If you know the iteration index, then you should be using a @for loop. But when you are iterating over a list or a map or a map with nested lists/map, the @each loop should be used.

According to developers (which includes me), @while has no exclusive use and should not be utilized so that you stay away from any confusions.

For Loop

This handy @for loop comes with two options. First is to use @for $var from $start through $end. Second is to use @for $var from $start to $end.

Please note that once the directive hits the $end, it just ends the looping process and stops there. Here is the simple example for the @for loop which makes a block grid with iteration.

// Maximum number of cells to display per direction
$max: 7; 

.grid {
  display: flex;
  flex-wrap: wrap;

  > div {
    height: 25px;
    background: #ccc;
    border: 1px solid #aaa;
  }
}

// Looping through the code
@for $i from 1 through $max {
 $equ: 100% / $i ;
 .grid.block-#{ $i } > div {
    flex: 0 0 $equ;
 }
}

And here below is the generated CSS output. As you can see we have looped through the maximum number of cells to display per direction to create a block grid. See how quickly Sass calculates everything by itself.

.grid {
  display: flex;
  flex-wrap: wrap; }
  .grid > div {
    height: 25px;
    background: #ccc;
    border: 1px solid #aaa; }

.grid.block-1 > div {
  flex: 0 0 100%; }

.grid.block-2 > div {
  flex: 0 0 50%; }

.grid.block-3 > div {
  flex: 0 0 33.33333%; }

.grid.block-4 > div {
  flex: 0 0 25%; }

.grid.block-5 > div {
  flex: 0 0 20%; }

.grid.block-6 > div {
  flex: 0 0 16.66667%; }

.grid.block-7 > div {
  flex: 0 0 14.28571%; }

Each Loop

The @each loop is commonly used for maps or lists so that you can loop through them, rather than addressing each key separately. Here is an example for a @each loop which makes buttons based on provided color palette map.

$button-palette: (
  primary: #1779ba,
  secondary: #767676,
  success: #3adb76,
  warning: #ffae00,
  alert: #cc4b37
);

@each $name, $color in $button-palette {
  .#{$name} {
    background-color: $color;
    &:hover, &:focus {
      background-color: darken($color, 20%);
    }
  }
}

See the output below where you can see how this looped through the given map and added the colors to specific classes as per the key and values provided to the tool.

.primary {
  background-color: #1779ba; }
  .primary:hover, .primary:focus {
    background-color: #0c3e5f; }

.secondary {
  background-color: #767676; }
  .secondary:hover, .secondary:focus {
    background-color: #434343; }

.success {
  background-color: #3adb76; }
  .success:hover, .success:focus {
    background-color: #1b9448; }

.warning {
  background-color: #ffae00; }
  .warning:hover, .warning:focus {
    background-color: #996800; }

.alert {
  background-color: #cc4b37; }
  .alert:hover, .alert:focus {
    background-color: #7d2c20; }

While Loop

As I said above that @while loops has no significant usage, but still, there is one thing about them that makes perfect sense about them. In our daily life, it’s common to use or hear such words like Do this while I do this or. Don’t open Computer until I clean the room, etc.

Precisely, this is what @while loop does. Check out this simple heading type scale that lets you iterate over different header sizes. Also, look how the program is adding 1 to the index after the code get executed every time.

$headerSizes: 48px 40px 31px 25px 20px 16px;
$index: 1;

@while $index <= 6 {
  h#{$index}, .h#{$index} {
    font-size: nth($headerSizes, $index);
  }
  $index: $index + 1;
}

Here below in the CSS, you can see how these header sizes get’s generated through the list thanks to @while loop.

h1, .h1 { font-size: 48px; }
h2, .h2 { font-size: 40px; }
h3, .h3 { font-size: 31px; }
h4, .h4 { font-size: 25px; }
h5, .h5 { font-size: 20px; }
h6, .h6 { font-size: 16px; }

Again will remind you that you should be using @for or @each as per the requirements. @while feels a bit useless, may this is just why Foundation Framework doesn’t use a single while in their codebase.

Vanilla Functions in Sass

This is my favorite of the lot. A Sass function, just like every other language is that so called “subprogram” that can be called from external code. Sass does include some Vanilla functions by default in which you can give Sass the arguments for a particular function and the function will return you the value. Apart from these below, there are some extra functions that are provided by Foundation which we discuss later on in Part 2.

This section below is on how to use vanilla functions provided by Sass that you can use. If you are looking for creating your own functions, this tutorial may help you.

Color Functions

Colors! When used correctly, can be incredibly powerful. This is where Sass comes in. Sass lets you control your colors with ease without needing you to choose and manipulate the colors. It does all that job for you.

$color: #0EA29D;

$a: darken($color, 10%); // Darken a color by 10%
$b: lighten($color, 15%); // Lighten a color by 15%
$c: saturate($color, 20%); // Saturate a color by 20%
$d: desaturate($color, 20%); // Desaturate a color by 20%
$e: adjust-hue($color, 15%); // Adjust hue of a color by 15%
$f: rgba($color, .7); // Adding Alpha Transparency
$g: grayscale($color); //  Converts a color to grayscale.
$h: complement($color); // Returns the complement of a color.

// Mix two colors, weight 50% by default.
// mix($color1, $color2, $weight:50%)
//
// 25% means that a quarter of the first color and three quarters of the second color should be used.
$mix: mix(#f00, #00f, 25%);

/* Just for demo */
.a { content: $a; }
.b { content: $b; }
.c { content: $c; }
.d { content: $d; }
.e { content: $e; }
.f { content: $f; }
.g { content: $g; }
.h { content: $h; }
.mix { content: $mix; }

The Generated CSS is here below, Sass just calculates all by itself.

.a { color: #0a7370; } /* Darken */
.b { color: #14e8e1; } /* Lighten */
.c { color: #00b0aa; } /* Saturate */
.d { color: #20908d; } /* Desaturate */
.e { color: #0e82a2; } /* Adjust hue */
.f { color: rgba(14, 162, 157, 0.7); } /* Alpha Transparency */
.g { color: #585858; } /* Grayscale */
.h { color: #a20e13; } /* Complement */
.mix { color: #4000bf; } /* Mixing two colors */

Alternatively, you can Debug the color too for different purposes. Stop! Big Word Alert, for now, think of @debug as console.log of javascript. We will talk about it later on in Part 2.
In this below example, we are debugging the red, green, and blue component of the variable $color.

$color: #0EA29D;

/* Debugging a color */
$red: red($color); // Gets the red component of a color.
$green: green($color); // Gets the green component of a color.
$blue: blue($color); // Gets the blue component of a color.

%debug {
  @debug 'Red: #{$red} | Green: #{$green} | Blue: #{$blue}';
}

And here is what I got in my console,

DEBUG: Red: 14 | Green: 162 | Blue: 157

String Functions

If you’ve done anything with strings in any language, you would be quite comfortable with these Sass string functions. But hey there is one exception: Please be careful that Sass strings are NOT zero-based arrays.

The first character in a Sass string is at index 1, not 0. If you are coming from a programming background, you will just hate this (includes me). Find the below examples which would help you in your upcoming Strings in Sass journey.

$a: unquote("hello world"); // Removes the quotes, if any, around a string
$b: quote(hello); // Adds quotes to an unquoted string
$c: quote("hello harry"); // Returns a quoted string unmodified
$d: str-length("hello world"); // Returns the number of characters in a string
$e: str-index("Hello", "H"); // Returns the index of the first occurrence of $substring in $string.
$f: str-index("hello", "H"); // If there is no such occurrence, returns null.
$g: to-upper-case("hello"); // Converts a string to upper case.
$h: to-lower-case("Hello"); // Converts a string to lower case.

// Inserts the string specified as $insert at the specified index position inside string
// str_insert($string, $insert, $index)
$insert: str-insert(" harry", "hello", 0);

// Extracts a substring from $string.
// The substring will begin at index $start-at and optionally ending at position $end-at.
// str_slice($string, $start-at, $end-at:-1)
$slice: str-slice("hello, world", 8);
$slice-end: str-slice("hello, world", 8, 9);

/* Just for demo */
.a { content: $a; }
.b { content: $b; }
.c { content: $c; }
.d { content: $d; }
.e { content: $e; }
.f { content: $f; }
.g { content: $g; }
.h { content: $h; }
.insert { content: $insert; }
.slice { content: $slice; }
.slice-end { content: $slice-end; }

The Generated CSS output looks like this below

.a { content: hello world; }
.b { content: "hello"; }
.c { content: "hello harry"; }
.d { content: 11; }
.e { content: 1; }
.g { content: "HELLO"; }
.h { content: "hello"; }
.insert { content: "hello harry"; }
.slice { content: "world"; }
.slice-end { content: "wo"; }

List Functions

Lists in Sass are immutable, and all list functions would return a new list rather than updating the existing list in-place. All the list functions will work for maps as well, treating them as lists of pairs. According to the one and only Hugo Giraudel,

Lists have to be the most complicated and vicious thing in the whole Sass language. The main problem with lists -if a problem it is- is that the syntax is way too permissive. You can do pretty much whatever you want. Here are some examples.

$list1 : 200px;
$list2 : 1px 2px 3px black,;
$list3 : Helvetica, Arial, sans-serif;

$zip1: 1px 2px 3px 4px;
$zip2: 4em 3em 2em 1em;
$zip3: black green blue red;

$nested-list: 1px 2px 3px green, 6px 7px 8px blue, 3px 2px 1px yellow;

html{
  // Returns the length of a list.
  // => length($list)
  width: length($list2);

  // Returns a specific item in a list.
  // => nth($list, $n)
  box-shadow: nth($nested-list , 2);

  // Replaces the nth item in a list.
  // => set-nth($list, $n, $value)
  text-shadow: set-nth($nested-list , 3 , 0em 1em .5em orange);

  // Returns the separator of a list.
  // => list-separator($list)
  height: list-separator($list3);

  // Joins together two lists into one.
  // => join($list1, $list2, $separator:auto, $bracketed:auto)
  line-height: join($nested-list , $list3,  comma);

  // Appends a single value onto the end of a list.
  // => append($list, $val, $separator:auto)
  font: append($zip3 , gray);

  // Returns the position of a value within a list.
  // => index($list, $value)
  font-size: index($nested-list , 3px 2px 1px yellow);

  // Combines several lists into a single multidimensional list.
  // => zip($lists...)
  background: zip($zip1 , $zip2 , $zip3);
}

And, here is the Generated CSS

html {
  width: 1;
  box-shadow: 6px 7px 8px blue;
  text-shadow: 1px 2px 3px green, 6px 7px 8px blue, 0em 1em 0.5em orange;
  height: comma;
  line-height: 1px 2px 3px green, 6px 7px 8px blue, 3px 2px 1px yellow, Helvetica, Arial, sans-serif;
  font: black green blue red gray;
  font-size: 3;
  background: 1px 4em black, 2px 3em green, 3px 2em blue, 4px 1em red; 
}

Number Functions

STOP! Let’s understand Math/Arithmetic operators: Before I move ahead, let’s have a little revisit to these math operators. SASS allows mathematical operations for addition, subtraction, multiplication, division, and remainder.

I hope you by now would be able to understand this below code. Let’s move ahead!

// Math Variables
$a : 16px; $b : 32px; $c : 4.5px; $d : -12px;

// Styling
.button { width: 5 + 10 + $a - ($b * 2) / $c % $d; } // 40.7777777778px;

Sass lets you add calculations in such a way that CSS would bow down and just write down the output. But would it mean that you should go around adding and dividing just anywhere? Here I will help you understand how to make calculations more useful and your Sass files more understandable.

$a : 16px;
$b : 32px;
$c : 4.5px;
$d : -12px;

// Rounds a number to the nearest whole number.
// => round($number)
.a { width: round( 5 + 10 + $a - $b * 2 / $c % $d ); }

// Rounds a number down to the previous whole number.
// => floor($number)
.b { width: floor( 5 + 10 + $a - $b * 2 / $c ); }

// Rounds a number up to the next whole number.
// => ceil($number)
.c { width: ceil( 5 + 10 + $a - $b * 2 / $c - .4 ); }

// Converts a unitless number to a percentage.
// => percentage($number)
.d { width: percentage( 4.5 ); }

// Returns the absolute value of a number.
// => abs($number)
.e { width: abs( $d ); }

// Finds the minimum of several numbers.
// This function takes any number of arguments.
// min($numbers...)
.f { width: min( 10, 20, 50, 50.1, $a ); }

// Finds the maximum of several numbers.
// This function takes any number of arguments.
// max($numbers...)
.g { width: max( 10, 20, 50, 50.1, $a ); }

// Return a decimal between 0 and 1, inclusive of 0 but not 1.
// or, if limit specified, then returns an integer between 1 and $limit
// => random | random($limit)
.h { width: random( 100 ); }

And, this below is the code which CSS has to say for all these Maths Calculations

.a { width: 41px; } /* round( 5 + 10 + $a - $b * 2 / $c % $d ); */
.b { width: 16px; } /* floor( 5 + 10 + $a - $b * 2 / $c ); */
.c { width: 17px; } /* ceil( 5 + 10 + $a - $b * 2 / $c - .4 ); */
.d { width: 450%; } /* percentage( 4.5 ); */
.e { width: 12px; } /* abs( $d ); */
.f { width: 10; } /* min( 10, 20, 50, 50.1, $a ); */
.g { width: 50.1; } /* max( 10, 20, 50, 50.1, $a ); */
.h { width: 95; } /* random( 100 ); */

For a full list of all the available functions, check out the official docs.

To be Continued: Foundation Workflow

We will wrap up this part and move into the second part, where we will look to apply our learnings within the Foundation’s Workflow. We will learn about some of the Sass Functions and Mixins (Generic, Prototype, Flexbox, Components, XY Grid) that foundation provides and how to use them so check them out at Part 2.

Thanks a lot…

  • If you liked my article and also my passion for teaching and want to say hello… my twitter handle is @harmanmanchanda for getting in touch! My DM’s are open to the public so just hit me up.
  • All the code discussed in the article can be found here.

Source:: scotch.io