SASS
- Notes on Marksheet's SASS chapter, with a few additions of my own: https://marksheet.io/sass-scss-less.html
- SASS Documentation: https://sass-lang.com/documentation/syntax/
- CSS preprocessor that extends it; LESS is an alternative, so is SCSS
- These include variables, functions, reusable components, syntax enhancers in general that generate CSS
- We'll use SCSS, since it is very similar to CSS (basically a superset; all valid CSS is valid SCSS)
- Main difference between CSS and SASS is that SASS uses indentation-based syntax (no curly braces)
SASS Features
- variables: instead of repeating #fce473 throughout your CSS file, just set $yellow: #fce473 once (prevents repeating values)
- nesting: CSS rules can be nested within each other (prevents repeating selectors)
- partials: import commonly used properties without extra requests or heavier than needed CSS files
- mixins: custom functions that can accept parameters and will prevent useless repetitions (prevents repeating properties)
- extensions: an easy way to inherit the same properties of another selector (also prevents repeating properties)
- operators: adding/substracting/multiplying/dividing values, like 960px / 4 or $space * 2
SASS Variables
- Variables can be defined and reused
- You can also define a set of variables and then point one variable to another, so say you want to change primary color from yellow to pink, just update $primary-color
// Defining color values $yellow: #fce473; $pink: #c71585; $green: #32cd32; $blue: #1d90ff; // Defining color types $primary-color: $green; .quote{ border-left: 5px solid $primary-color;} .button{ background: $primary-color;} .sidebar a:hover{ border-bottom-color: $primary-color;} .footer a{ color: $primary-color;}
It is possible to change any type of content with variables:
// Colors $yellow: #fce473; $pink: #c71585; $green: #32cd32; $blue: #1d90ff; $primary-color: $blue; $secondary-color: $yellow; // Fonts $serif: "Lora", "Playfair Display", Georgia, serif; $sans-serif: "Roboto", "Source Sans Pro", "Open Sans", Arial, sans-serif; $monospace: "Inconsolata", monospace; $primary-font: $sans-serif; $secondary-font: $serif; // Spacing $mobile-space: 10px; $desktop-space: 35px; // Also possible to add built-in manipulations for easy color transition & others, for instance: $primary-blue: #1d90ff; button { background: $primary; &:hover { background: lighten($primary-blue, 10%); } &:active { background: darken($primary-blue, 15%); } }
SASS Nesting
- Meant to reuse same parent selector
- Attempt to replicate HTML's nesting structure in CSS
- Rule of thumb is to avoid nesting deeper than 3 levels, which would lead to over-specificity and large CSS output
For instance:
//scss .parent{ .child{} } // becomes in css .parent .child{}
So the nested .child
element will be applied to elements nested withing elements with the .parent
class.
What about elements that must have both classes/states at once?
- Note that these generated CSS classes have no space between class names (so it only applies to elements with both classes)
//scss .parent{ &:hover{} &.other-class{} } // becomes in css .parent:hover{} .parent.other-class{}
For reference: Generated CSS alongside SCSS selectors:
| CSS Selectors | SASS Selectors | |--------------------------------------|-------------------------------------| | `.post-content{}` | `.post-content {` | | `.post-content a{}` | ` a {` | | `.post-content a:hover{}` | ` &:hover {}` | | `.post-content aside{}` | ` aside {}` | | `.post-content blockquote{}` | ` blockquote {}` | | `.post-content code{}` | ` code {}` | | `.post-content h3{}` | ` h3 {` | | `.post-content h3 a{}` | ` a {}` | | `.post-content h4{}` | ` h4 {` | | `.post-content h4:before{}` | ` &:before {}` | | `.post-content h4:after{}` | ` &:after {}` | | `.post-content p{}` | ` p {` | | `.post-content p:first-child{}` | ` &:first-child {}` | | `.post-content p:last-child{}` | ` &:last-child {}` | | `.post-content ul{}` | ` ul {` | | `.post-content ul ul{}` | ` ul {` | | `.post-content ul ul ul{}` | ` ul {}` | | `.post-content dl{}` | ` dl {` | | `.post-content dl:before{}` | ` &:before {}` | | `.post-content dl dt{}` | ` dt {}` | | `.post-content dl dd{}` | ` dd {}` | | `.post-content pre{}` | ` pre {` | | `.post-content pre code{}` | ` code {}` | | `.post-content table{}` | ` table {` | | `.post-content table tr{}` | ` tr {` | | `.post-content table tr:nth-child(2n){}` | ` &:nth-child(2n) {}` | | `.post-content table th,` | ` th,` | | `.post-content table td{}` | ` td {` | | `.post-content table th{}` | ` th {}` | | `.post-content table td.empty,` | ` &.empty {}` | | `.post-content table th.empty{}` | ` }` | | `.post-content table code{}` | ` code {}` | | `.post-content table pre{}` | ` pre {` | | `.post-content table pre:before{}` | ` &:before {}` |
SASS Mixins
- A mixin is basically a predefined set of properties and values that can be reused. Example:
@mixin overlay() { bottom: 0; left: 0; position: absolute; right: 0; top: 0; } /** This mixin called within this class... **/ .modal-background{ @include overlay(); background: black; opacity: 0.9; } /** ...will generate the following CSS: **/ .modal-background{ bottom: 0; left: 0; position: absolute; right: 0; top: 0; background: black; opacity: 0.9; }
X.7.4.1 Mixin Parameters
- Mixins can also accept parameters; ex:
@mixin border-radius($radius) { -webkit-border-radius: $radius; -moz-border-radius: $radius; -ms-border-radius: $radius; border-radius: $radius; } /** This mixin called within this class... **/ .box{ @include border-radius(3px); } /** ...will generate the following CSS: **/ .box{ -webkit-border-radius: 3px; -moz-border-radius: 3px; -ms-border-radius: 3px; border-radius: 3px; }
X.7.4.2 Mixins Default Parameters
- It is possible to add default and optional mixin parameters.
- For instance, see this one meant to add labels in the top left of code snippet blocks:
@mixin label($text: "Code", $background: $yellow, $color: rgba(black, 0.5)) { position: relative; &:before{ background: $background; color: $color; content: $text; display: inline-block; font-size: 0.6rem; font-weight: 700; height: 1rem; left: 0; letter-spacing: 0.1em; line-height: 1rem; padding: 0 0.5em; position: absolute; text-transform: uppercase; top: 0; } } /* used here: */ div.highlighter-rouge{ @include label(); /* will use default "Code", $yellow and rgba(black, 0.5) values */ &.css{ /* will have specific values for codeblocks with css class */ @include label("CSS", $blue, white); } &.scss{ /* will have specific values for codeblocks with scss class */ @include label("SCSS", #c69, white); } }
SASS Extensions and Placeholders
- These are very similar to mixins; the difference is that mixins write to css directly, and extensors and placeholders only reference it, so they are "more elegant"
- Placeholders are basically silent classes that do not output to CSS unless extended
- When in doubt, use mixins as they are the most straightforward
- As a rule of thumb, use mixins when you need params and placeholders/extensors when you do not
As a rule of thumb, use extensions when the base class will also be used in HTML and extensions + placeholders when the base class will be absent from the HTML but classes extending from it will be in the HTML
Extend syntax (allows to inherit CSS properties):
// scss .small-uppercase{ color: lightslategrey; font-size: 10px; letter-spacing: 0.1em; line-height: 12px; text-transform: uppercase; } .modal-background{ @extend .small-uppercase; } .product-link{ @extend .small-uppercase; } // generated css .small-uppercase, .modal-background, .product-link,{ color: lightslategrey; font-size: 10px; letter-spacing: 0.1em; line-height: 12px; text-transform: uppercase; }
- Note how .small-uppercase was also generated as a class. What if we don't want to do this, to keep our CSS as flat and clean as possible?
// scss %small-uppercase{ color: lightslategrey; font-size: 10px; letter-spacing: 0.1em; line-height: 12px; text-transform: uppercase; } .modal-background{ @extend %small-uppercase; } .product-link{ @extend %small-uppercase; } .image-pattern{ @extend %small-uppercase; } // generated css .modal-background, .product-link, .image-pattern{ color: lightslategrey; font-size: 10px; letter-spacing: 0.1em; line-height: 12px; text-transform: uppercase; }
Use Mixins When | Use Extends When |
---|---|
Need parameters | Static styles |
Output varies per instance | Reducing duplicated styles |
SASS Control Directives
- SASS offer directives such as loops and conditionals
- These can be used to generate repetitive styles efficiently
// For loops @for $i from 1 through 4 { .mt-#{$i} { margin-top: #{$i * 5}px; } } // Each loops $colors: (primary: blue, secondary: green); @each $name, $color in $colors { .text-#{$name} { color: $color; } } // If statements @mixin theme($dark: false) { @if $dark { background: black; } @else { background: white; } }
SASS Imports & Partials
- The
@import
directive allows you to include content of a file into another - This however can create a new HTTP request every time it is called
- SASS solves this by including the file in the CSS itself
- You can import
.sass
,.scss
and.css
files; it does not even need an extention, SASS will treat it as a compatible file. - Prefix partials with an underscore, like "_filename.scss" so they don't get compiled into their own CSS file.
- Note that every time you import, code will be duplicated, so keep imports to a minimum. See 7-1 Architecture: https://www.easeout.co/blog/2020-08-25-structuring-your-sass-projects/
/* _colors.scss */ $myPink: #EE82EE; $myBlue: #4169E1; $myGreen: #8FBC8F; /* main.scss */ @import "colors"; body { font-family: Helvetica, sans-serif; font-size: 18px; color: $myBlue; }
Top comments (0)