# Advanced topics
- In Example 1, we used Sass to lay-out a specific webpage/website more efficiently
# Example 2
- In our next example, we will use Sass to start writing our own, simple, Bootstrap-like CSS framework, i.e., TMF (Thomas More Framework)
- The result - after compilation - will be a bunch of CSS classes that can be used on HTML elements for styling purposes
- Below, we will discuss the content of some SCSS files used to setup this framework. By doing so, we can elaborate further on some (more) advanced Sass techniques.
REMARK
The example presented below is only a (small) part of the complete TMF framework, written by Patrick Verhaert as an extensive course example in the spring of 2020.
WATCHING TIP
We refer the interested reader to a series of 19 (Dutch) video's on Canvas > Webdesign Advanced > Modules > TMF - A simple CSS framework with Sass (and jQuery) (opens new window) in which the complete TMF framework is developed from scratch. More than 5 hours of binge watching fun! 😉
# style.scss
// Import fonts & icons @import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap'); @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css'); // Configuration @import "variables"; @import "reset"; // Layout & components @import "type"; @import "grid"; // Helpers @import "helpers/text"; @import "helpers/border";Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- Our main SCSS file only contains
@importstatements (to load the different partials) - As you already know, the order of importing the partials is important
- First, we import the necessary fonts & icons
- Google Font Lato (styles: Regular 400, Bold 700 and Black 900)
- Font Awesome
- Next, we import the variables (
@import "variables";) and execute our (universal) reset (@import "reset";) - Then, we define some general styling rules (
@import "type";) as well a very basic grid system (@import "grid";) - Finally, also some helpers (
@import "helpers/text"; @import "helpers/border";) are included (e.g. to style the text and borders)
- First, we import the necessary fonts & icons
# _variables.scss
// fonts $font-size: 14px; $line-height: 1.5; $ff-arial: Arial, "Helvetica Neue", Helvetica, sans-serif; $ff-lato: 'Lato', sans-serif; // colors $blue: #009cab; $red: #f04c25; $orange: #f7ae19; $green: #8dab3d; $black: black; $gray: #a4a4a4; $darkgray: #6b6b6b; $white: white; $color-map: ( //key: value 'primary': $blue, 'danger': $red, 'success': $green, 'info': $orange, 'black': $black, 'gray': $gray, 'white': $white );Copied!
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
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
- In this partial, we first define some variables related to fonts and colors (lines 1-16)
# Maps
- In addition, we also define a map
$color-mapin which we define several key:value pairs between round brackets (lines 18-27)- This map will be used later on (in the helpers) where we will do something for every (key:value) pair, i.e., we will make a series of similar classes corresponding to these (key:value) pairs
READING TIP
# _reset.scss
SCSS
CSS
* { margin: 0; padding: 0; box-sizing: border-box; } html { font-size: $font-size; } body { font-family: $ff-arial; line-height: $line-height; color: $darkgray; }Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- In this partial, we implement our classical universal reset (lines 1-5)
- We also set the general
font-size,font-family,line-heightand (text)color(lines 7-15)
# _type.scss
SCSS
CSS
h1 { font-family: $ff-lato; font-weight: 900; font-size: 2rem; line-height: 2.5rem; color: $black; padding-bottom: 1rem; } h2 { @extend h1; font-size: 1.75rem; line-height: 2rem; } h3 { @extend h2; font-size: 1.5rem; } p { padding-bottom: 1rem; text-align: justify; }Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- In this partial, we define some (standard) styling for the main headings
h1(lines 1-8) and the paragraphs (lines 21-24)
# @extend
- For the headings
h2, we want to "duplicate" all the style rules written forh1elements, which can be achieved by using@extend h1- Afterwards, we overwrite the
font-sizeand theline-heightwith some specific values
- Afterwards, we overwrite the
- Likewise, for the headings
h3, we duplicate all the style rules ofh2elements with@extends h2, after which we overwrite thefont-size
READING TIP
# _grid.scss
SCSS
CSS
.container { max-width: 768px; margin-bottom: 1rem; margin-left: auto; margin-right: auto; > * { //all child tags margin-left: 1rem; margin-right: 1rem; } }Copied!
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- The partial _grid.scss only includes the code for a centered
.containerclass that is limited in width - The code also contains a nice example of a nested child selector (line 7). That is, all elements (
*) that are immediate descendants/children (>) of.containerget some horizontal margin
# helpers/_text.scss
SCSS
CSS
// .text-primary, .text-danger, ... @each $key, $value in $color-map { .text-#{$key} { color: $value; } }Copied!
1
2
3
4
5
6
2
3
4
5
6
- With this short piece of code, we will define the classes
.text-primary,.text-danger, ... to change the textcolorto the colors (values of the key:value pairs) defined in$color-map, as shown in the resulting CSS
# @each
- The
@eachrule (line 2) results in an iteration over all the key:value pairs ($key, $value) in$color-map
READING TIPS
# Interpolation
- Within each iteration step, i.e., for every
$keyand$valuepair, we define a class.text-...which sets the textcolorequal to$value- To embed the
$key(primary,danger, ...) in the CSS class names, we use interpolation, i.e., we wrap the$keywithin
#{ }
- To embed the
# helpers/_border.scss
SCSS
CSS
@use "sass:color"; .border { //.border-primary, .border-danger, ... @each $key, $value in $color-map { &-#{$key} { border: 1px solid color.adjust($value, $lightness: -10%); padding: 1rem; margin-bottom: 1rem; } } // .border-width-1, .border-width-2, ..., .border-width-10 @for $i from 1 through 10 { &-width-#{$i} { border-width: #{$i}px; } } // .border-radius-25, .border-radius-50, .border-radius-75, .border-radius-100 @for $i from 1 through 4 { &-radius-#{$i*25} { border-radius: #{calc($i / 4)}rem; } } }Copied!
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
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
- We start (lines 3-11) with an
@eachiteration that is similar to the one used above, resulting in the classes.border-primary,.border-danger, ...- These classes add some
paddingand asolid,1pxborderaround an element, as well as some bottom margin - The border colors are slightly darkened versions of the colors in
$color-map
- These classes add some
REMARKS
- Lines 3-11 could also be written as follows:
//.border-primary, .border-danger, ... @each $key, $value in $color-map { .border-#{$key} { border: 1px solid color.adjust($value, $lightness: -10%); padding: 1rem; margin-bottom: 1rem; } }Copied!
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- Yet, we chose to include or nest the
@eachiteration within.border{ ... }and use the parent selector&. As such, the two additional@forloops resulting in more "border" classes (.border-width-5,.border-radius-50, ...) are implemented in the same way (within.border{ ... }).
# @for
- Lines 13-17 use a traditional for loop with the counter
$iranging from1to10- The use of the keyword
throughmeans that the value10will be included in the iteration; you can useto(@for $i from 1 to 10) if you want the loop to stop at$i = 9 - Interpolation (
#{$i}) is used to generate the classes.border-width-1,.border-width-2, ...,.border-width-10(which set theborder-widthequal to1px,2px, ...,10pxrespectively)
- The use of the keyword
- A similar approach is used (in lines 20-25) for the classes
.border-radius-25,.border-radius-50,.border-radius-75and.border-radius-100- As we only want 4 classes where
25,50,75and100stand for the percentage of arem, we iteratefrom 1 through 4and use some interpolated mathematical expressions (#{$i*25}and#{calc($i / 4)}) for the class names and theborder-radiusvalues, respectively
- As we only want 4 classes where
READING TIPS
# A TMF-based example page
- Example 2 also contains a sample HTML page dist/index.html
- In this page, the compiled CSS code of our TM Framework is linked:
<link rel="stylesheet" href="css/style.css"> - We illustrate the styling of a
.container,h1,h2andh3,.text-primary,.text-danger,.border-black,.border-success,.border-danger,.border-width-3,.border-width-5and.border-radius-50
- In this page, the compiled CSS code of our TM Framework is linked:
