Module 4

The Sass CSS Preprocessor

What are CSS Preprocessors?

CSS preprocessors such as Sass and Less are great tools for managing CSS stylesheets, because they allow you to define variables and functions that can be applied throughout your stylesheet. This is particularly useful for changing the style "theme". For instance, variables can be used to represent repeated values such as primaryColor, secondaryColor, etc. Then if you want to change the overall look, these variables can be changed and the preprocessor can be run to generate a new stylesheet.

Another advantage of using variables, is that it makes refactoring your stylesheets easier, because you can just change the value of the variables instead of copying and pasting code. And your stylesheets will be easier to understand, because you can use descriptive names for the variables.

Here is a summary of features available in Sass (syntactically awesome style sheets), as described in the article Getting started with Sass :

  • Ability to Nest Selectors
  • The Parent Selector: &
  • Variables
  • Nesting Properties
  • Nesting Media Queries
  • Inheritance with @extends
  • Mixins (Resusable Snippets)
  • Functions

Syntaxes: Format differences between SASS and SCSS

There are 2 styles of Sass Syntax:

  • SCSS: curly braces separate selectors and rule blocks, and semi-colons are required at the end of lines
  • SASS: curly braces are replaced by indentation, and there are no semi-colons.

Some people think the SASS is easier to read, similar to indentation in Python vs. JavaScript. SCSS seems more familiar to others, since all CSS code is also valid SCSS. Here the examples will be in the SCSS syntax.

Once you have added all your rules to your SCSS (or SASS) file, it needs to be "compiled" with a Sass compiler. I prefer to use the Node (Dart) version sass. Install it globally using the node package manager:

npm i -g sass

Then run it on the command line by specifying your input file and output file:

sass some-file.scss some-file.css

How to define and use variables in SCSS

Variables are defined similar to regular CSS properties. A colon separates the variable name from the value. Variables must begin with a $. Then in your CSS rules, you replace the value with your variable. Here is an example:

  $accentColor: rgba(48, 128, 20, 1);
  $accentBackground: lightgreen;
  $accentFont: italic 16px "Lucida Console", Courier, monospace;
  $accentPadding: 1em 1em;
  $accentMargin: 10%;

  .accent {
    color: $accentColor;
    background-color: $accentBackground;
    font: $accentFont;
    padding: $accentPadding;
    width: calc(80% - 2em);
    margin: 0 $accentMargin;
  }
        

Save this in a file test.scss, then run node-sass:

node-sass test.scss test.css

And here is the result in test.css

  .accent {
    color: #308014;
    background-color: lightgreen;
    font: italic 16px "Lucida Console", Courier, monospace;
    padding: 1em 1em;
    width: calc(80% - 2em);
    margin: 0 10%; }
        

The Sass compiler does not always preserve line breaks. See how the result has the ending curly brace on the same line as the last property rule.

Due to historical reasons, there is a quick in how Sass interprets variable names: underscores and hyphens are equivalent. A variable named my_padding is treated tje same as a variable named my-padding. This happened because CSS did not used to allow hypens, so people used underscores. When CSS allowed hypens, the people that wrote Sass thought it would make like easier to make underscores in Sass code to convert to hyphens.

Let's use the above accent class in some HTML:

  <div class="accent">
    Sass is a powerful tool which enables developers to create much cleaner and more maintainable styling for their sites.
  </div>
        

and view the result:

Sass is a powerful tool which enables developers to create much cleaner and more maintainable styling for their sites.

Sass Variable Types

In the previous example, we assigned Sass variable names to values of color, string, and list. This article on Sass - Data Types describes all 7 data types:

  • number: Sass recognizes the CSS length types px and em, and automatically converts types when doing math operations, such as 16px + 0.5em
  • string: A string can contain single or double quotes, that will be preserved when the variable is used. If you need to remove them, then used the interpolation operator #{$your-sass-variable} to remove them.
  • color: You can use hex strings, and standard CSS color functions such as rgb, rgba, hsl, and hsla
  • list: In the previous example, the variable $accentFont was assigned to a series of strings separated by spaces and commas. A list can even include another list.
  • map: A map is similar to a JavaScript object. It is a series of key-value pairs wrapped in ()'s. Here is an example: $red-map: (light: #e57373, medium: #f44336, dark: #b71c1c);
  • booleans and nulls: While these variable types are not used in CSS properties, they can be useful in Sass functions

Sass Operators

There are several operators you can use on Sass variables or property values:

  • Equality == and Inequality !=
  • Comparison: <, <=, >, and >=
  • Boolean: and, or, and not
  • Numeric: +, -, *, /, %. Note, a - before a number without a space will make it negative (not subtract).
  • String: strings can only be added with +.
  • Color Operations: Sass used to support addition and subtraction of colors, but now you need to see the built-in color functions, such as color.mix(#ff0000, #00ff00)

Mixins for Reusable Blocks

Often there is is a block of style rules that are repeated in different selectors. Mixins allow you to declare that block of rules in a mixin, and use that in other selectors. A Mixin is declared using @mixin followed by the mixin name and the rules. Let's create a mixin called disable, that prevents a user from clicking an element:

  @mixin disable {
    pointer-events: none;
    cursor: default;
    color: #aaaaaa;
  }

Now if there is a selector that you want to apply these rules, you use @include. Here is an example, where we have a button with class next-page that we want to disable.

  button.next-page {
    @include disable;
    padding: 1em 1em;
    font-size: .8em;
  }

Creating and Using Functions

While mixins can return a block of style rules, a function returns a single value. Both functions and mixins can take a list in input parameters, and can contain control flow. Here is a function that returns a different value for padding, depending on the number of columns. Note that control operators begin with an @ symbol.

  @function columnPadding($num-columns) {
    @if $num-columns < 4 {
      @return 1em 4em;
    }
    @return 1em 0;
  } 

Then we can use this function in a style rule:

  $ncol: 4;
  .column-container {
    padding: columnPadding($ncol)
  } 

which produces this CSS output

  .column-container {
    padding: 1em 0;
  } 

How to use CSS Custom Properties in SCSS

You can write SCSS code that produces Custom CSS Properties. An article on the SASS web site Property Declarations explains how to do this. First you declare the SASS variable, then use it in a rule selector. The SASS variable is enclosed in #{} to interpolate the variable. Here is an example using the :root pseudo selector:

  $errorColor: #ff0000;

  :root {
    --errorColor: #{$errorColor};
  }

Since the variable interpolation removes quotation marks, a special function is required if your property has quotes, such as a 2 word font name. To do this, you add the Sass meta.inspect function.

  @use "sass:meta";

  $code-font: 16px "Lucida Console", Courier, monospace;

  :root {
    --code-font: #{meta.inspect($code-font)};
  }