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 :
There are 2 styles of Sass Syntax:
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
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:
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:
There are several operators you can use on Sass variables or property values:
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;
}
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;
}
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)};
}