HTML and CSS course Β· Module 7: SASS

Sass: A Guide to the CSS Preprocessor

6 min read
In this lesson7

Imagine that your website about the temple of Karnak has a thousand lines of CSS. You have typed the gold color #D4AF37 in forty places, and you copy the same set of declarations into every new button. When the pharaoh asks for a darker gold, a tedious search through the whole scroll awaits you. These are exactly the troubles Sass solves.

Sass, which stands for Syntactically Awesome Style Sheets, is a CSS preprocessor that significantly extends the capabilities of plain CSS. It offers variables, mixins, inheritance, nesting, operators, functions and flow control, which makes working with stylesheets more efficient and enjoyable.

What you will learn

  • explain what a preprocessor is and why the browser does not read Sass files,
  • tell the SCSS syntax apart from the indented Sass syntax,
  • compile a .scss file into plain CSS,
  • use nesting, variables, mixins and inheritance.

A preprocessor: the architect's scribe

The browser understands only CSS, so you cannot link a .scss file to a page directly. You write code in Sass, and a compiler translates it into a plain .css file, like a scribe copying the architect's shorthand into hieroglyphs that anyone can read on a temple wall. The path therefore looks like this: a .scss file, the Sass compiler, a .css file and only then the browser. The main compiler is Dart Sass, available on npm as the sass package:

1npm install --save-dev sass
2npx sass styles.scss styles.css

The first command adds the compiler to the project, the second reads styles.scss and writes the result to styles.css. The source file stays untouched, and you link only the generated CSS to the page. With the --watch flag the compiler rebuilds the CSS every time you save the file.

Syntax

Sass supports two different syntaxes: SCSS (a syntax close to CSS, with curly braces, .scss files) and Sass (indentation-based, no curly braces, .sass files). SCSS is a superset of CSS: with a few small exceptions, every valid CSS stylesheet is also a valid SCSS file.

SCSS Syntax Example

This is a heading with a nested subheading written in SCSS, which looks almost like plain CSS:

1.naglowek {
2  color: red;
3
4  .podnaglowek {
5    font-size: 16px;
6  }
7}

The braces and semicolons stay exactly where they are in CSS. The only new thing is that the .podnaglowek rule sits inside the .naglowek rule.

Sass Syntax Example

The same fragment in the indented syntax loses its braces and semicolons, and the structure is defined by indentation alone:

1.naglowek
2  color: red
3
4  .podnaglowek
5    font-size: 16px

The compiler generates identical CSS from both versions, because only the notation differs, not the result. I recommend SCSS: it looks like the CSS you already know, and most projects and documentation are written in it.

Nesting

In HTML, a navigation is a ul list, inside it li items, and inside those a links. Sass lets you mirror this hierarchy by nesting selectors, so related rules stay in one place:

1.nav {
2  ul {
3    margin: 0;
4    padding: 0;
5    list-style: none;
6  }
7
8  li { display: inline-block; }
9
10  a {
11    display: block;
12    padding: 6px 12px;
13    text-decoration: none;
14  }
15}

After compilation you get ordinary descendant selectors: .nav ul, .nav li and .nav a. The HTML does not change at all, because the nesting exists only in the source file. Do not go deeper than three levels, though, because each extra level makes the selector longer and raises its specificity.

Variables

A variable stores a value that you use in many places in a stylesheet. In Sass its name starts with a dollar sign, and after the name you put a colon, the value and a semicolon, for example $gold: #D4AF37 for Egyptian gold:

1$primary-color: #333;
2
3body {
4  background-color: $primary-color;
5}

The compiler replaces every $primary-color with #333, so the variable no longer exists in the resulting CSS, only its value remains. That is the difference from CSS variables such as --primary-color, which live in the browser. You change the value in one place, compile again, and the new color appears everywhere.

Mixins

A mixin is a named set of declarations that you define once with the @mixin directive and then insert into any rule with the @include directive. It works like a seal with the pharaoh's cartouche, pressed onto tablet after tablet:

1@mixin reset-list {
2  margin: 0;
3  padding: 0;
4  list-style: none;
5}
6
7ul {
8  @include reset-list;
9}

The compiler pastes the three declarations from the mixin in place of @include, so in the CSS you will see them inside the rule for ul. The mixin itself does not reach the output until you use it.

Inheritance

Sometimes several classes share a common base and differ in one detail, like success and error messages. The @extend directive lets a class inherit all the styles of another class:

1.message {
2  border: 1px solid #ccc;
3  padding: 10px;
4  color: #333;
5}
6
7.success {
8  @extend .message;
9  border-color: green;
10}
11
12.error {
13  @extend .message;
14  border-color: red;
15}

The compiler does not copy the declarations, it adds the selectors to the existing rule, creating the group .message, .success, .error. Each class then overrides only the border color. In large projects, however, @extend can generate surprisingly long selector lists, which is why I usually reach for mixins.

Flow Control

Sass also offers conditional statements and loops, such as @if, @for, @each and @while. With them a stylesheet generates series of classes by itself, for example one for every color in a palette. You will learn them in the upcoming lessons of this module.

Sass is a powerful tool that can significantly increase productivity and the enjoyment of writing CSS. Modern CSS already has its own variables and nesting, which you will meet later in the course, but Sass still wins with mixins, loops and splitting code into modules. In the sandbox below, compare the styles.scss file with the compiled styles.css and check what the compiler did with each variable.

Remember: Sass is a scribe who turns your shorthand into clean CSS hieroglyphs, and the browser reads only the result of his work.

Code for this lesson: index.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>SCSS/Sass - Introduction</title>
7    <link rel="stylesheet" href="styles.css">
8</head>
9<body>
10    <div class="container">
11        <h1>Introduction to SCSS/Sass</h1>
12
13        <section class="demo-section">
14            <h2>Variables in SCSS</h2>
15            <div class="variables-demo">
16                <div class="color-box primary">Primary color ($primary-color)</div>
17                <div class="color-box secondary">Secondary color ($secondary-color)</div>
18                <div class="color-box accent">Accent color ($accent-color)</div>
19            </div>
20            <div class="font-demo">
21                <p class="font-primary">Primary font ($font-primary)</p>
22                <p class="font-secondary">Secondary font ($font-secondary)</p>
23            </div>
24        </section>
25
26        <section class="demo-section">
27            <h2>Nesting in SCSS</h2>
28            <nav class="navbar">
29                <ul>
30                    <li><a href="#">Home</a></li>
31                    <li><a href="#">About us</a></li>
32                    <li><a href="#">Services</a></li>
33                    <li><a href="#">Contact</a></li>
34                </ul>
35            </nav>
36            <p class="description">Navigation was styled using SCSS nesting</p>
37        </section>
38
39        <section class="demo-section">
40            <h2>Ampersand (&) - Parent Selector</h2>
41            <div class="buttons-demo">
42                <button class="btn">Regular button</button>
43                <button class="btn btn--primary">Primary button</button>
44                <button class="btn btn--secondary">Secondary button</button>
45                <button class="btn btn--large">Large button</button>
46            </div>
47        </section>
48
49        <section class="demo-section">
50            <h2>Partials and modules</h2>
51            <div class="modules-demo">
52                <div class="card">
53                    <div class="card-header">
54                        <h3>Modular card</h3>
55                    </div>
56                    <div class="card-body">
57                        <p>This card uses styles from different SCSS modules.</p>
58                    </div>
59                    <div class="card-footer">
60                        <button class="btn btn--primary">Action</button>
61                    </div>
62                </div>
63            </div>
64        </section>
65
66        <section class="demo-section">
67            <h2>Mixins</h2>
68            <div class="mixins-demo">
69                <div class="flex-container">
70                    <div class="flex-item">Element 1</div>
71                    <div class="flex-item">Element 2</div>
72                    <div class="flex-item">Element 3</div>
73                </div>
74                <div class="shadow-box">Box with shadow (mixin)</div>
75                <div class="gradient-box">Box with gradient (mixin)</div>
76            </div>
77        </section>
78
79        <section class="demo-section">
80            <h2>Extend and inheritance</h2>
81            <div class="extend-demo">
82                <div class="message">Basic message</div>
83                <div class="message message--success">Success message</div>
84                <div class="message message--error">Error message</div>
85                <div class="message message--warning">Warning message</div>
86            </div>
87        </section>
88
89        <section class="demo-section">
90            <h2>Mathematical operators</h2>
91            <div class="operators-demo">
92                <div class="grid-container">
93                    <div class="grid-item">Element 1</div>
94                    <div class="grid-item">Element 2</div>
95                    <div class="grid-item">Element 3</div>
96                    <div class="grid-item">Element 4</div>
97                </div>
98                <p class="calculation-info">Width calculated: (100% - 60px) / 4</p>
99            </div>
100        </section>
101
102        <section class="demo-section">
103            <h2>SCSS Functions</h2>
104            <div class="functions-demo">
105                <div class="color-functions">
106                    <div class="color-original">Original color</div>
107                    <div class="color-lighter">Lighter (lighten)</div>
108                    <div class="color-darker">Darker (darken)</div>
109                    <div class="color-saturated">Saturated (saturate)</div>
110                </div>
111            </div>
112        </section>
113
114        <section class="demo-section">
115            <h2>Media Queries with mixins</h2>
116            <div class="responsive-demo">
117                <div class="responsive-box">
118                    <p>This section changes layout depending on screen size</p>
119                    <div class="responsive-grid">
120                        <div class="responsive-item">Item 1</div>
121                        <div class="responsive-item">Item 2</div>
122                        <div class="responsive-item">Item 3</div>
123                        <div class="responsive-item">Item 4</div>
124                    </div>
125                </div>
126            </div>
127        </section>
128    </div>
129</body>
130</html>

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What is SASS?

  2. 2. How do you declare a variable in SASS?

These are 2 of 3 questions for this lesson. Solve the rest in the game.

Hands-on tasks in the game

  • Code editor

    Define: $primary: #2C3E50, $secondary: #D4AF37 (Egyptian gold), $accent: #E74C3C. Use them in .header { background: $primary }, .title { color: $secondary }, .button { background: $accent }. Change $primary and see what happens!

  • Click in order

    Build a SASS variable declaration that stores an Egyptian gold color:

  • Vertical ordering

    Arrange the SASS compilation process from source code to browser display:

Useful articles