- Sass 101
- Preprocessing
- Working with basic variables
- Fonts stored in variables & use
- Nesting your styles
- Using Partials
- Using basic mixins
- Using the @extend method
- Referencing parent selectors with
&
- Using comments and hidden comments
- Working with math operators
- Modifying colors
- Creating list elements
- Using the @content container
- Conditional @if statements and argument lists
- Looping through lists with @for
- Looping through lists with @each
- Working with the map data type
- Learning objectives
- Skills covered in this course
- Resources
- Preprocessing
Once you start tinkering with Sass, it will take your preprocessed Sass file and save it as a normal CSS file that you can use in your website.
The most direct way to make this happen is in your terminal. Once Sass is installed, you can compile your Sass to CSS using the sass command. You'll need to tell Sass which file to build from, and where to output CSS to. For example, running sass input.scss output.css
from your terminal would take a single Sass file, input.scss, and compile that file to output.css.
sass --watch input.scss output.css
You can also watch individual files or directories with the --watch
flag. The watch flag tells Sass to watch your source files for changes, and re-compile CSS each time you save your Sass. If you wanted to watch (instead of manually build) your input.scss file, you'd just add the watch flag to your command, like so:
sass --watch app/sass:public/stylesheets
If there's one reason to learn to use Sass, it's variables. It made working with CSS a lot easier.
$offwhite: #eee8d6;
$darkblue: #022933;
$yellow: #ffba00;
$blue: #0076a3;
$green: #548c27;
$orange: #f39856;
$red: #d14348;
$purple: #6d73c2;
Example of use
body {
color: $darkblue
background-color: $offwhite;
}
$color-main: $darkblue;
$color-backgrounds: $offwhite;
$color-headlines: $red;
Example of use
body {
color: $color-main
background-color: $color-backgrounds;
}
@import url(http://fonts.googleapis.com/css?family=Roboto+Slab|Merriweather|Josefin+Slab|Oswald|Bree+Serif);
$color-main: $darkblue;
$color-backgrounds: $offwhite;
$color-headlines: $red;
Example of use
body {
font-family: $font-main;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: $font-highlight;
color: $color-headlines;
}
Another really popular Sass feature is called nesting. It allows you to put CSS rules inside other rules and it's a great way to organize your styles so that they're super easy to find.
NOTE: Only go to a max of 4 levels deep when nesting styles
HTML layout to style
<h1>Media</h1>
<ol class="media">
<li class="item">
<a href="#">
<img src="http://placehold.it/90x90" alt="thumbnail" />
<h2 class="head">Title one</h2>
<p>
Atque suscipit, neque quisquam laboriosam enim officiis, nam nemo
cupiditate ipsam eveniet id eaque optio facere! Maxime accusamus
repellendus nisi veniam saepe explicabo, voluptatum quod obcaecati,
possimus quis expedita? Dignissimos.
</p>
</a>
</li>
</ol>
... ...
Nested SASS reflecting html layout
$color-item-border: $red;
$color-media-head: $blue;
.media {
margin: 0;
padding: 0;
list-style: none;
.item {
margin-bottom: 20px;
border-top: 1px dotted $color-item-border;
padding-top: 10px;
}
.head {
margin: 0;
padding: 0;
color: $color-media-head;
font-size: 2rem;
}
p {
margin: 0;
font-size: 1.5rem;
}
img {
float: left;
margin-right: 10px;
}
a {
text-decoration: none;
color: $color-main;
}
}
Rendered CSS
.media {
margin: 0;
padding: 0;
list-style: none;
}
.media .item {
margin-bottom: 20px;
border-top: 1px dotted #d14348;
padding-top: 10px;
}
.media .head {
margin: 0;
padding: 0;
color: #0076a3;
font-size: 2rem;
}
.media p {
margin: 0;
font-size: 1.5rem;
}
.media img {
float: left;
margin-right: 10px;
}
.media a {
text-decoration: none;
color: #022933;
}
Sass allows you to break up your CSS into modules called partials. That also helps you organize your code into logical groups. So it's quite easy to do. You simply add an @import command just like you would do in CSS. However, what is different is that the CSS gets actually combined into a single file when it is output.
When you have made your separate .scss files you use the @import
command to reference each file in the order to be imported and processed in to one file, any files in sub folders should also be referenced correctly relative to the main style.scss file.
NOTES:
- When using
@import
make sure each reference does not have.scss
file extension - it is not required - if it is left it each file will be processed into a separate.css
file. - Make sure each
.scss
file that will be imported as a partial has a filename beginning with an underscore e.g._somesassfile.scss
. - If you do want to make sure that something gets imported in the traditional way where it's another server call, then you can import a document that has a
.css
extension. It will treat it just like a normal import or give Sass a URL that begins withhttp://
or give it a file name that is a URL like we have done here invariables.scss
.
Example filenames for partials
- _base.scss
- _normalize.scss
- _variables.scss
- style.scss
@import "variables";
@import "normalize";
@import "base";
@import "modules/media";
Another powerful feature in SASS is the ability to create JavaScript-like functions called mixins. If you're familiar with JavaScript, these are going to make a lot of sense.
/* background image mixin */
/* backImage ($var, $var, $var: fallback, $var: fallback) {} */
@mixin backImage($image, $height: 100vh, $bgPos: center center) {
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6)),
url($image);
background-repeat: no-repeat;
background-position: $bgPos;
background-size: cover;
height: $height;
}
/* clearfix mixin */
@mixin clearfix {
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
}
/* @include backImage ( 'imgurl', 'var', [falls back] ) {} */
.jumbotron {
@include backImage("../images/water.jpg", 600px);
}
/* @include backImage ('imgurl', 'var', var) {} */
.bridge {
@include backImage("../images/bridge.jpg", 300px, center center);
}
/* using the clearfix mixin on &:last-of-type*/
.item {
padding-bottom: 10px;
padding-top: 10px;
padding-left: 10px;
border-top: 1px dotted $color-item-border;
&:hover {
background: $yellow;
}
&:last-of-type {
border-bottom: 1px dotted $color-item-border;
}
@include clearfix;
}
This uses one style as the basis for a second style. To define the code to act as a basis for other @extend
styles you use the %
(invisible class) before the name of the style:
/* variables */
$color-btn-text: $color-backgrounds;
$color-btn-default: $color-main;
$color-btn-hot: $red;
$color-btn-cool: $blue;
/* extends style */
%btn {
display: inline-block;
padding: 6px 12px;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: none;
border-radius: 4px;
font-family: $font-highlight;
user-select: none;
color: $color-btn-text;
}
Then when you want to extend using the above you'd used @extend
like in the examples below:
.btn-default {
@extend %btn;
background: $color-btn-default;
}
.btn-hot {
@extend %btn;
background: $color-btn-hot;
}
.btn-cool {
@extend %btn;
background: $color-btn-cool;
}
Sass uses the ampersand character as a special selector that can be used to reference the parent of an element. And you can use this type of selector to solve a variety of problems.
Using the &
allows you to select the parent of the current style code block you are in an add styles to that e.g. when you hover on the parent and want a background colour to show.
$color-item-border: $red;
$color-media-head: $blue;
.media {
margin: 0;
padding: 0;
list-style: none;
.item {
padding-bottom: 10px;
padding-top: 10px;
padding-left: 10px;
border-top: 1px dotted $color-item-border;
/* the below style will add a yellow hover when parent is hovered on */
&:hover {
background: $yellow;
}
/* the below style will add a border to the bottom of the last item inside the parent */
&:last-of-type {
border-bottom: 1px dotted $color-item-border;
}
@include clearfix;
}
The below is saying "if there is an element with #typography
and inside a nested element with .head
then apply this style:
.head {
margin: 0;
padding: 0;
color: $color-media-head;
font-size: 2rem;
#typography & {
color: $red;
}
Using comments and hidden comments
/* this is a normal comment */
/*! this is a force comment */
// this is an invisible comment
SASS has operations like addition, multiplication, division, and others, these can help to create more complex CSS styles.
NOTE:
- Make sure when using operations that there is correct spacing, if not then these may be compiled as names rather than operations.
/* @mixing imageGrid($var, $var) {} */
@mixin imagegrid($qty, $margin) {
// set the width to 100%
// set amount of items
// deduct one item
// mutliply that with the margin value that is specified when user passes var in
// take that whole thing and divid by amount of items from user
// Defines proper width of the element with margins only inside the element items.
width: ((100% - (($qty - 1) * $margin)) / $qty);
// then use & to call parent and ask for nth-child operator
// This says on every element, go ahead and give it the margin that we're specifying when we pass this variable called margin along
&:nth-child(n) {
// set margins on bottom and right to what user sets
margin-right: $margin;
margin-bottom: $margin;
}
// then use #{$var} to insert a variable
// this targets the last item
// Then on the last one just set the margin of that last element to zero.
&:nth-child(#{$qty}n) {
margin-right: 0;
margin-bottom: 0;
}
}
.grid {
@include clearfix;
.item {
float: left;
// @include imageGrid($var, $var)
@include imagegrid(3, 2%);
}
img {
display: block;
border-radius: 10px;
max-width: 100%;
}
}
SASS allows you to work with colours in new ways with various functions.
// applies transparentize() to $yellow with a setting of .8
$color-even-cells: transparentize($yellow, 0.8);
.table {
font-size: 1.5rem;
text-align: left;
width: 100%;
caption {
font-size: 2.5rem;
text-align: left;
padding-bottom: 5px;
}
> thead,
> tbody,
> tfoot {
> tr {
&:hover {
// applies darken( adjust-hue ( ) ) to $color-backgrounds with a setting of -20deg, 10%
background-color: darken(adjust-hue($color-backgrounds, -20deg), 10%);
}
&:nth-child(even) {
background-color: $color-even-cells;
&:hover {
// applies opacify( ) to $color-even-cells with a setting of .3
background-color: opacify($color-even-cells, 0.3);
}
}
> th,
> td {
padding: 10px;
border-bottom: 1px dotted $blue;
}
}
}
> thead > tr {
background-color: $blue;
color: $color-backgrounds;
&:hover {
// applies complement() to $blue
background-color: complement($blue);
}
> th {
border-bottom: 0;
}
}
}
SASS has a special version of arrays called lists, these are unlike any other type of array structure.
// this is in essence a list
$roundness: 20px 0 20px 0;
// this is how it can be used
img {
display: block;
// this uses nth() to reference the variable but take only the first value = 20px
border-radius: nth($roundness, 1);
max-width: 100%;
}
When calling a mixin it is possible to call some code to be processed within the mixin. A practical example of this would be media queries.
In the example below inside the break
mixin, it uses the @content
directive to ask this media query to be passed along some content.
This content directive allows us to pass this mixin some CSS that we want to stick inside this media query.
// @mixin break($var) {}
@mixin break($length) {
@media (min-width: $length) {
// @content is where CSS is passed to this mixin when referenced
@content;
}
}
// using the mixin
nav {
header & {
background-color: darken($blue, 15%);
}
.branding {
float: left;
display: none;
// call break mixin and set width to 1000px to show the branding
@include break(1000px) {
display: block;
}
}
.branding h1 {
font-size: 2.75rem;
overflow: hidden;
margin: 0;
color: $yellow;
}
ul {
list-style: none;
margin: 0;
padding: 0;
@include clearfix;
}
ul li {
// call break mixin and set width to 760px to float nav right
@include break(760px) {
float: right;
}
padding: 10px 5px;
}
ul li a {
text-decoration: none;
padding: 10px 5px;
color: $color-backgrounds;
&:hover {
color: $yellow;
}
header &:hover {
background-color: darken($blue, 20%);
}
footer & {
color: white;
}
}
footer & {
margin-top: 20px;
min-height: 200px;
background-color: darken($blue, 15%);
}
}
Conditional statements allow you to create styles that react to changes in your CSS.
There is a special operator that can be used to create a mixin that takes up any number of values ...
.
Below is a modified version of the mixin from Using the @content container.
// @mixin break($var, ... (other x$var) ) {}
@mixin break($args...) {
// if call has one param use this option
@if length($args) == 1 {
@media (min-width: nth($args, 1)) {
// @content is where CSS is passed to this mixin when referenced
@content;
}
}
// if call has two params use this one
@if length($args) == 2 {
@media (min-width: nth($args, 1)) and (max-width: nth(args, 2)) {
// @content is where CSS is passed to this mixin when referenced
@content;
}
}
}
// If Else example
/*
@mixin breakExampleIfElse($args...) {
// if call has one param use this option
@if length($args) == 1 {
@media (min-width: nth($args, 1)) {
// @content is where CSS is passed to this mixin when referenced
@content;
}
}
// if call has two params use this one
@else {
@media (min-width: nth($args, 1)) and (max-width: nth(args, 2)) {
// @content is where CSS is passed to this mixin when referenced
@content;
}
}
}
*/
// using the mixin
footer & {
margin-top: 20px;
min-height: 200px;
background-color: darken($blue, 15%);
// if width is between 0 and 500px display none
@include break(0, 500px) {
display: none;
}
}
Loops are a type of structure that can help you go through a series of items, the below example shows how to use the @for
loop in SASS.
$color-headlines: $blue, $purple, $green, $red, $orange, $yellow;
@for $item from 1 through length(@color-headlines) {
h#{$item} {
color: nth($color-headlines, $item);
}
}
Generates this CSS
h1 {
color: #0076a3;
}
h2 {
color: #6d73c2;
}
h3 {
color: #548c27;
}
h4 {
color: #d14348;
}
h5 {
color: #f39856;
}
h6 {
color: #ffba00;
}
Lists can become much more powerful when you can use them to go through a series of values. The below example shows how to use the @each
loop in SASS.
// set up variables
$color-btn-names: "default", "hot", "cool";
$color-btn-values: $color-main, $red, $blue;
// setup @each loop function
// =========================
// for each name in $color-btn-names do the following
@each $name in $color-btn-names {
// set index of $colour-btn-names and look for the $name, finds which item name is in that loop cycle
$i: index($color-btn-names, $name);
// use .btn prefix with a dash and `#`
// this is going to be a calculated element that is going to be based on the name
// generates a style for each item in the variable being looped
.btn-#{$name} {
@extend %btn;
// gets the color value from the list based on the number generated by the loop cycle
background-color: nth($color-btn-values, $i);
}
}
Many programming languages have a really useful data type called associative arrays. Now, they allow you to create complex lists that have both a key for each element as well as a value. Unlike arrays, the keys aren't just numbers but can also have names. Sass has a beautiful implementation of this, so we're going to use that to make creating a series of buttons a breeze.
// set up variables
$color-btn-names: "default", "hot", "cool";
$color-btn-values: $color-main, $red, $blue;
// set up map
$color-btns: (
default: $color-main,
hot: $red,
cool: $blue,
);
// setting up use of the map with @each
@each $key, $value in $color-btns {
.btn-#{$key} {
@extend %btn;
background-color: $value;
}
}
- Working with variables
- Nesting styles
- Creating mixins
- Conditional statements and loops in SassScript
- Extending your mixins
- Working with lists and maps
- SASS
- Front-end Development
- Tools: Node JS
- Tools: Git SCM
- Resource: The Sass Way
- Tools: sass-lang.com
- Tools: Gulp JS
- Tools: Normalize.css
- Sass Docs: Syntax
- Sass Docs: Style Rules
- Sass Docs: Variables
- Interpolation
- Sass Docs: At-Rules
- Sass Docs: Values
- Sass Docs: Operators
- Sass Docs: Built-In Modules
- Sass Docs: Breaking Changes - CSS Variables Syntax
- Sass Docs: Command Line