Installation
- confirm you have installed sass using
sass --version or npx node-sass --version
- if not, then install via
- brew for mac,
brew install node-sass
- pacman for arch,
pacman -S dart-sass
Getting Started
Here we try to use sass for styling html for the first time by changing the html background
color.
- create files and folder with following structure
1
2
3
4
5
6
|
.
βββ css
β βββ main.css
βββ index.html
βββ input
βββ main.scss
|
- add standard boilerplate to
index.html with this line to the main.css
1
|
<link rel="stylesheet" href="css/main.css">
|
- add content to
main.scss
1
2
3
|
body {
background-color: blue;
}
|
- run
sass --watch input:css
input is the folder where sass or scss files stored.
css is the target folder to store compile result. If the folder missing, the compiler will create it.
--watch is the flag to watch for changes in the input folder.
- open the browser and you’ll see the background color is changing.
Using npm
- run
npm init -y to create package.json file
- add
sass as dev dependency npm install sass --save-dev
- add script to
package.json
1
2
3
|
"scripts": {
"sass": "sass --watch input:css"
}
|
- run
npm run sass to compile scss files
Variable and Nested Sass
Here is the example of using variables to store color and font-size values
- add content to
main.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
$color-primary: orange;
$color-secondary: grey;
$color-tertiary: royalblue;
$font-lg: 40px;
$font-md: 30px;
$font-sm: 20px;
.nav {
background-color: $color-primary;
ul li {
list-style: none;
}
a {
text-decoration: none;
font-size: $font-sm;
color: $color-secondary;
&:hover {
color: $color-tertiary;
}
}
}
.banner h1 {
font-size: $font-lg;
color: $color-secondary;
text-align: center;
}
.footer h3 {
font-size: $font-md;
color: $color-secondary;
text-align: center;
}
|
note:
- without prefix ampersand
& the css will be compiled like this .nav a :hover {...}
- the ampersand prefix
& is used to remove the space between the parent and child selector
- so, with the ampersand prefix, the result will be
nav a:hover {...}
Mixin
Mixin is a block of code, which group bunch of reusable CSS styles. To get started, modify the previous main.scss file with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// same as previous
@mixin headingStyles($fontSize: 50px) {
font-size: $fontSize;
color: $color-secondary;
text-align: center;
}
@mixin transition($param...) {
transition: $param;
}
.banner h1 {
@include headingStyles;
}
.footer h3 {
@include headingStyles($font-md);
@include transition(color .5s, background-color 1s);
&:hover {
color: $color-tertiary;
background-color: $color-primary;
}
}
|
note:
- the colon + value
50px in the headingStyles($fontSize: 50px) is optional and used for default value
- if default value stated, then it can be omitted when calling the mixin like
@include headingStyles;
- the three dots
... in the context of the mixin ($param...) are called the splat operator. It allows you to pass an arbitrary number of arguments to the mixin as a list.
- the splat operator is not only used in mixin, but also in function
Extend
Extend allows one selector to inherit styles of another selector. Let’s practice
- remove the previous code in
main.scss regarding mixin
- replace with this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
...
.heading {
color: $color-primary;
font-size: $font-lg;
background-color: $color-secondary;
text-align: center;
}
h1 {
@extend .heading;
&:hover {
background-color: green;
}
}
.footer h3 {
@extend h1;
}
|
note
- the extend should be followed by single element like
@extend h1, cannot @extend banner h1
Function
Function allows us to run code over and over again when we call it.
Let modify the code in the main.scss file above
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
...
@use "sass:color";
.nav {
background-color: color.adjust($color-tertiary, $alpha: -0.9);
ul li {
list-style: none;
}
a {
text-decoration: none;
font-size: $font-sm;
color: $color-secondary;
&:hover {
color: $color-tertiary;
}
}
}
.heading {
color: $color-primary;
font-size: $font-lg;
background-color: #{$color-tertiary};
text-align: center;
}
@function fontSize($size: 25px) {
@return $size * 2;
}
h1 {
@extend .heading;
&:hover {
background-color: green;
}
}
.footer h3 {
@extend h1;
}
.banner p {
font-size: fontSize($font-sm);
}
.footer p {
font-size: fontSize(30px);
}
|
note
Placeholder Selectors %
Placeholder selector allows us to create cleaner and concise code in case of creating class. It creates more readable code because when you see it, you get that it’s created specifically to extend some styles to element(s).
Without placeholder selectors
the main.scss file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// code truncated
.heading {
color: $color-primary;
font-size: $font-lg;
background-color: #{$color-tertiary};
text-align: center;
}
h1 {
@extend .heading;
&:hover {
background-color: green;
}
}
// code truncated
|
the compiled css file
1
2
3
4
5
6
7
8
9
10
11
12
|
/* code truncated */
.heading, h1, .footer h3 {
color: orange;
font-size: 40px;
background-color: royalblue;
text-align: center;
}
h1:hover, .footer h3:hover {
background-color: green;
}
|
With placeholder selectors %
the main.scss file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// code truncated
%heading {
color: $color-primary;
font-size: $font-lg;
background-color: #{$color-tertiary};
text-align: center;
}
h1 {
@extend %heading;
&:hover {
background-color: green;
}
}
// code truncated
|
the result of compiled css file
1
2
3
4
5
6
7
8
9
10
11
12
|
/* code truncated */
h1, .footer h3 {
color: orange;
font-size: 40px;
background-color: royalblue;
text-align: center;
}
h1:hover, .footer h3:hover {
background-color: green;
}
|
Import and partials
structure file and folders to this
1
2
3
4
5
6
7
|
.
βββ css/
βββ index.html
βββ input/
β βββ _footer.scss
β βββ main.scss
βββ README.md
|
in the file _footer.scss put
1
2
3
4
|
.footer h3 {
font-style: italic;
border: 5px solid blue;
}
|
import the code to the main.scss using @use "footer"
1
2
3
4
5
6
7
8
9
10
11
12
|
$color-primary: orange;
$color-secondary: grey;
$color-tertiary: royalblue;
$font-lg: 40px;
$font-md: 30px;
$font-sm: 20px;
@use "sass:color";
@use "footer";
// code truncated
|
note
- The underscore _ prefix at the beginning of a file name has a specific meaning related to partials
- The underscore _ tells SCSS that the file is a partial and should not be compiled directly.
- The file can be imported into other SCSS files for modularity and reusability.
- The
@import rule is deprecated in favor of the @use rule
Sass Datatype
Numbers
1
2
3
4
5
|
.numbers {
font-weight: 400;
line-height: 1.5;
font-size: 20px;
}
|
Strings
1
2
3
4
5
|
.strings {
font-family: 'Helvetica', Arial, sans-serif;
font-weight: bold;
font-style: italic;
}
|
Lists
1
2
3
4
5
|
.lists {
margin: 10px 15px 5px 20px;
font-family: 'Raleway', 'Dosis', 'Lato';
border: 1px solid red;
}
|
Maps
The key for maps can be string or number.
1
2
3
4
5
6
7
8
9
10
|
$colors: (
primary: red,
'secondary': green,
3: blue,
);
h1 {
color: map-get($colors, primary);
background-color: map-get($map: $colors, $key: secondary);
}
|
for Dart Sass 1.33+, it is recommended to use map.get instead of map-get and import the module sass:map
1
2
3
4
5
6
|
@use "sass:map";
h1 {
color: map.get($colors, primary);
background-color: map.get($map: $colors, $key: secondary);
}
|
Boolean
Null
1
2
3
4
|
$theme-colors: (
primary: #3498db,
secondary: null
);
|
Interpolation
1
2
3
4
5
6
7
8
9
|
$b: "border";
$c: "color";
h2 {
box-sizing: #{$b}-box;
#{$b}: 1px solid blue;
#{$c}: red;
background-#{$c}: green;
};
|
Looping
For Loop
Suppose we have repeated styles for different paragraph and we would like to apply different background color.
1
2
3
4
5
6
|
<body>
<p class="paragraph-1">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-2">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-3">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-4">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
</body>
|
We can use looping on scss to reduce the code.
1
2
3
4
5
6
7
8
9
10
11
12
|
$paragraph-color: (
1: red,
2: green,
3: blue,
4: orange,
);
@for $i from 1 through 4 {
.paragraph-#{$i} {
background-color: map.get($map: $paragraph-color, $key: $i);
}
}
|
Each Loop
docs: https://sass-lang.com/documentation/at-rules/control/each/
Besides, for loop in SASS, we have each loop which like for loop executes block of code over and over again until elements are expired.
in main.html, put
1
2
3
4
5
6
|
<body>
<p class="paragraph-red">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-green">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-blue">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
<p class="paragraph-yellow">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Deleniti, cum.</p>
</body>
|
in main.scss, put
1
2
3
4
5
6
7
|
$paragraph-color: red green blue yellow;
@each $color in $paragraph-color {
.paragraph-#{$color} {
background-color: $color;
}
}
|
If directive
ref: https://sass-lang.com/documentation/at-rules/control/if/
example usage:
- control size of element
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@mixin headingSize($size) {
@if($size == large) {
font-size: 45px;
} @else if($size == medium) {
font-size: 30px;
} @else {
font-size: 15px;
}
}
h1 {
@include headingSize(large);
}
|
- control dark mode
1
2
3
4
5
6
7
8
9
10
11
|
$dark-mode: false;
body {
@if $dark-mode {
background-color: #111;
color: #fff;
} @else {
background-color: #fff;
color: #000;
}
}
|