Intro to Sass | SCSS101

The following is an outline of what I cover in my Sass101 workshop in San Francisco.

Basics

  • "Sass" stands for Syntactically Awesome Style Sheets
  • The proper capitalizations are Sass and SCSS. In fact, there's a whole website dedicated to it appropriately named SassnotSASS.com
  • Why would I want to learn Sass?
    • you like writing CSS and didn't know it can get even cooler
    • you don't like writing CSS and wish it could be easier
    • helps DRY up your code {DRY: Don't Repeat Yourself}
    • if you want to be employed as a front-end or full-stack engineer, your workplace will use a preprocessor, which is what Sass is. This simply means that Sass compiles to CSS for the browser to use
  • Sass is just a powerful tool for developers to make writing stylesheets easier. There is nothing in Sass that can't be written in CSS; it just provides a much simpler way to write it.

Tools

  • SassMeister preprocesses for you and give you live side-by-side preview of your Sass/SCSS and CSS. I particularly like it because of the ability to connect to your Github account and save Gists, as well as customization settings. I use SassMeister as a debugging tool to make sure my Sass is compiling as expected.
  • Codepen is super fun! It's also a great tool for learning. You can customize your settings, including setting your CSS to Sass or SCSS (you can do it for one pen or set it as a default).
  • Sass Docs, need I say more? You'll probably be most interested in the Learn Sass and Documentation tabs.

Comments

You can use regular CSS /* */ but can also use //. // can be nice because it will only show up in your Sass and will not be compiled, whereas /* */ can be nice for multi-line comments.

Sass vs SCSS

The main difference between the two is syntax. Make sure to give your file the proper extension (.sass and .scss). SCSS looks more like CSS and uses the same syntax. Curly braces and semicolons are very important, and Sass/SCSS will fail to compile if there is a syntax error. Sass respects white space and indentations and doesn't use {} or ;. The major downfall to Sass is that it is not CSS compatible, whereas you can write CSS in an SCSS file and it would be fine. As far as I've seen, SCSS is now more common than Sass. Keep in mind that when I usually say "Sass", I am talking about both, as this section is the only diversion between the two.

  /*Sass*/
.class,
#id
    color: aliceblue

  /*SCSS*/
.class,
#id {
    color: aliceblue;
}

Nesting

For those of you unfamiliar with nesting entirely, it is a way to structure your code using indentation to denote relation between selectors or properties. If you are now studying Sass, it's likely you have written HTML, in which case a great example of nesting would be li elements are always nested in ul or ol elements, like so:

  <ul>
    <li>Item</li>
    <li>Item</li>
</ul>

Selectors

In SCSS, nesting selectors look like this:

  .nav {
    a {
        text-decoration: none;
    }
}

which compiles to:

  .nav a {
    text-decoration: none;
}

Though you can nest infinitely, it's good practice not to nest more than three or four levels deep.

&

& can be used as shorthand for parent selectors. Let's look at some examples that show how this is handy:

  a {
    text-decoration: none;
    &:hover {
        color: red;
    }
}

which compiles to:

  a {
  text-decoration: none;
}
a:hover {
  color: red;
}


It stands for all parent selectors that it is nested in:

  li {
    text-decoration: none;
    &.menu-item {
        color: hotpink;
        font-weight: 500;
        .nav & {
            display: inline-block;
        }
    }
}

will compile to:

  li {
  text-decoration: none;
}
li.menu-item {
  color: hotpink;
  font-weight: 500;
}
.nav li.menu-item {
  display: inline-block;
}


The & takes the parent literally, so you could also do something like this:

  .nav {
    &--link {
        display: inline-block;
    }
    &--title {
        font-size: 18px;
    }
}

which in CSS will look like:

  .nav--link {
  display: inline-block;
}
.nav--title {
  font-size: 18px;
}

Cool, right?

Properties

Like selectors, you can nest properties as well. This works for properties that have similar namespaces, for example border, background, font, and padding to name a few. Nested properties are much like nested selectors, except a : is also needed. For example:

  .sweet {
    background: {
        color: ghostwhite;
        position: center;
        size: contain;
    }
    margin: {
        bottom: 1rem;
        left: 0;
        top: 0;
    }
}

compiles to:

  .sweet {
  background-color: ghostwhite;
  background-position: center;
  background-size: contain;
  margin-bottom: 1rem;
  margin-left: 0;
  margin-top: 0;
}

Media queries

In CSS, the media query must have all styles nested within in. In Sass it can go both ways. In fact, you can even nest media queries within other media queries, though I wouldn't recommend it because this could get confusing for other developers. Regardless, let's look at some code:

  .selector {
  color: blue;
  @media screen and (min-width: 300px) {
    color: purple;
    @media screen and (max-width: 700px) {
      color: red;
    }
  }
}

compiles to:

  .selector {
  color: blue;
}
@media screen and (min-width: 300px) {
  .selector {
    color: purple;
  }
}
@media screen and (min-width: 300px) and (max-width: 700px) {
  .selector {
    color: red;
  }
}


Your Nesting Challenge

Reverse engineer the following by writing Sass that will compile to this CSS. I recommend trying it on Sassmeister, using this code as a reference.

Variables

A variable is, like in many other programming and logic-based languages, something you can assign a value to. You only have to assign it once (though it can be reassigned later). This can be great for colors. Just think, you have a color scheme and want to change one of the colors. Instead of hunting through your code to change every instance, you change it in one place!

The format for assigning Sass variables is like this: $ + your logical name + : + value. Let's see what this looks like:

  // VARIABLES
// colors
$brand-color: #C69;
$accent-color: #4286f4;
$white-color: ghostwhite;
// z-indecies
$z-background: 1;
$z-menu-trigger: 50;
$z-menu: $z-menu-trigger + 1; //aka 51

.main-container {
    background-color: $white-color;
}

All that will end up in the CSS is:

  .main-container {
    background-color: ghostwhite;
}

Put your variables at the top of your SCSS file. If you have enough of them, place them in their own _variables.scss file.

Note: Any z-index value should be stored in a variable. This is not only best practice but allows you to create layers.

The Variable Playground

Play and see the power of variables for yourself. Also, when you hover over the SCSS, you have the option to view the compiled CSS.

Math

  • Sass returns up to 5 digits by default
  • operators:
    • + addition
    • - subtraction
    • / division
    • * multiplication
    • %, called "modulo", gives a remainder and 5 % 2 is read "five mod two".
  • It isn't perfect
    • / not always recognized to imply division
    • ways to trigger division:
      • use variable: $size / 10
      • parenthesis, including in functions: (100px /20)
      • another operator: 1px * 5 / 2
    • - can also be added before a variable to make the value (if numeric) negative
  • cannot add relative units to non-relative units (ex. 1px + 1rem will not work)
  • this is all without using CSS's calc()

@extend

@extend can be used with a selector to pass all defined styles to another selector:

  a {
    color: yellow;
    display: list-item;
    text-decoration: none;
}
button {
    @extend a;
}

compiles to:

  a, button {
    color: yellow;
    display: list-item;
    text-decoration: none;
}

Note that it will copy all instances of what is being extended and not just exact matches. This is best described through another example:

  a {
    color: yellow;
    display: list-item;
    text-decoration: none;
    &:hover {
        color: purple;
    }
    &.link {
        border: 1px solid yellow;
    }
}
div a {
    position: relative;
}
button {
    @extend a;
}

will compile to:

  a, button {
  color: yellow;
  display: list-item;
  text-decoration: none;
}
a:hover, button:hover {
  color: purple;
}
a.link, button.link {
  border: 1px solid yellow;
}

div a, div button {
  position: relative;
}

Mixins

Mixins allow you to write a chunk of reusable code to be later inserted using @include. A great use case for this is vendor prefixes, but for the first example let's look at the inline-block:

  @mixin inline-block() {
    display: inline-block;
    position: relative;
    vertical-align: top;
}

.class {
    @include inline-block();
    font-weight: bold;
}

looks like:

  .class {
  display: inline-block;
  position: relative;
  vertical-align: top;
  font-weight: bold;
}

Arguments

Mixins get even sweeter with the use of arguments. Like variables, use $ when naming your arguments. They go in the () after the name of the mixin. When you include it later, define what value you want to be filled in correspondingly.

  @mixin columns ($column-count, $column-gap, $column-fill) {
  -webkit-column-count: $column-count;
     -moz-column-count: $column-count;
          column-count: $column-count;
  -webkit-column-gap: $column-gap;
     -moz-column-gap: $column-gap;
          column-gap: $column-gap;
  -webkit-column-fill: $column-fill;
     -moz-column-fill: $column-fill;
          column-fill: $column-fill;
}

.main-content {
    @include columns (2, 1em, auto);
}

: in arguments

When writing the mixin, a : can be added after each argument to give it a default value, like this:

  @mixin columns ($column-count:2, $column-gap:1em, $column-fill:auto) {
  -webkit-column-count: $column-count;
     -moz-column-count: $column-count;
          column-count: $column-count;
  -webkit-column-gap: $column-gap;
     -moz-column-gap: $column-gap;
          column-gap: $column-gap;
  -webkit-column-fill: $column-fill;
     -moz-column-fill: $column-fill;
          column-fill: $column-fill;
}

If all arguments have a default value, you don't need to add anything when including the mixin (meaning you could write @include columns(); for the above). Or, when you include a mixin you can use : to specify which argument you are defining without having to write values for all arguments, which would look like @include columns($column-gap:2em);.

Your Mixin Challenge

Reverse engineer the following by writing Sass that will compile to this CSS. I recommend trying it on Sassmeister, using this code as a reference.

Functions

Writing functions in Sass is much like writing a mixin, but we'll save writing custom functions for a different lesson. However, Sass comes with lots of built-in functions! Functions can do all sorts of things, for instance, lighten, darken, or make a color greyscale. Here's a list of all the Sass functions and how to use them.

Fin

Sass is the best, and now your stylesheets are about to be a whole lot less tedious and more fun to write. You should now have some basic tools to get started, but keep in mind this is just the beginning. Sass has a whole lot more to offer.

Final Challenge

Reverse engineer the following by writing Sass that will compile to this CSS. I recommend trying it on Sassmeister, using this code as a reference.


11,759 3 221