Sass provides many useful features. It gives web designers and developers the ability to DRY up our code with mixins, maps and loops. It gives us a way to split up large files, but yet still cascade our stylesheets. And most importantly, it gives us variables.

Sass variables allow developers to build flexible, modular and consistent stylesheets. However, at the same time, they can cause just as much harm as they do good.

“Thanks, Kurt. But I knew this already.” You're probably thinking this right now. That's fair. What I'm writing about is not a new concept. Variables for Sass have been around since the languages initial release in 2006. But as CSS variables gain steam, it's an important topic worth revisiting and discussing.

What Are Sass Variables

A variable, defined by a $ and proceeded by a name, contains a value to an argument. In Sass, they typically contain a CSS property value such as a hexadecimal color, unit of measurement or Sass function. A few examples:

  // Variable Examples
  $black-base:   #2A2A2A;
  $border:       1px solid;
  $border-color: darken($black-base, 10%);

As you can see from these examples, the variables hold a defined value that can be used throughout your stylesheets. Let's take a look at how we might use the above variables to style a selector. For the purpose of this blog post I will write my examples in SCSS.

  // Variables In Use Example
  .button {
    background-color: $black-base;
    border: $border;
    border-color: $border-color;
  }

The above example, however, does have a few problems. One of the most notabled issues, they do not take into consideration the cascade of CSS. Meaning, we broadly defined our variable names. What happens if we need to define another $border variable? By using the same name we could override our first variable and cause unintended outcomes to our code. Let's look at a few ways we can write variables to ensure we don't have leaky code.

Better Naming Conventions

First, we can start by writing more descriptive variable names. In the example above we broadly defined our variable names. Take for instance $border this name doesn't accurately describe the scope of this variable. Does it live in a component, module, page or global stylesheet?

Let's say we scope these variables to a button component. We can then create more descriptive names for these variables by using the parent selector. It might looks something like this:

  // Variable
  $button-background-color:   #2A2A2A;
  $button-border:             1px solid;
  $button-border-color:       darken($black-base, 10%);

  // Button Component
  .button {
    background-color: $button-background-color;
    border: $button-border;
    border-color: $button-border-color;
  }

As you can see, we have now scoped our variable names to the parent selector button. This helps us avoid leaky variables because we have become more descriptive with our naming conventions. Additionally, we would not use these variables outside of the button component file as they would not make sense from a naming convention standpoint.

Understanding Global vs Local Variables

Understanding the difference between local and global variables can help to contain unintended outcomes as well. They also help us to deteremine what we consider reusable and what is not.

First, let's take a look at global variables.

What makes a global variable global? This type of variable is not scoped to a parent selector. Usually defined at the top of a stylesheet or in a stylesheet reserved for theme varables, these values are often reserved for colors, typography, borders, etc. While there are no hard or soft rules, we should think of them as theme related variables. If the variable directly effects the outcome of a site's or applicaiton's core visual design then it should be consider global.

  // Colors Variables
  // ========================================

  // Black
  $black-base:    #2A2A2A;
  $black-dark:    #000000;

  // Blue
  $blue-base:     #007BC1;

  // Grey
  $grey-light:    #E8E9EB;
  $grey-base:     #86888B;

  // Grey
  $white-base:    #FFFFFF;

As you can see from the example above, the variables we created directly effect the outcome of the site's color palette. These colors will need to be referenced throughout the site, thus we make them global variables. They do not have a parent selector and as long as they proceed other selectors in the cascade, we can use them to add specific styles. They can also be used to assign values to local variables.

Now on to the second type of Sass variables, local variables. What makes a variable local versus global?

A local variable belongs to a selector. These variables are nested inside of the selector to prevent scope leak and because of this, can only be referenced by this selector and it's nested children. Let's take a look at an example.

  // Button Component
  .button {

    // Local Variable
    $button-background-color:   $black-base;
    $button-border:             1px solid;
    $button-border-color:       $black-dark;

    // Button Structure
    background-color: $button-background-color;
    border: $button-border;
    border-color: $button-border-color;
  }

As you can see, the variables being referenced in the button structure section of our example utilize the locally scoped variables. Let's take a look at one more example.

  // Button Component
  .button {

    // Local Variable
    $button-background-color:   $black-base;
    $button-border:             1px solid;
    $button-border-color:       $black-dark;
    $button-full-width:         100%;

    // Button Structure
    background-color: $button-background-color;
    border: $button-border;
    border-color: $button-border-color;

    &--full {
      width: $button-full-width;
    }
  }

In this example, you can see we have defined a new local variable $button-full-width and we are passing it down to the new selector we created, $button--full. While the $button-full-width variable is not defined directly inside of the selector it styles, we can still call on this local variable because of the parent to child nested relationship between the button selector and button--full selector.

Additionally, you will notice in each of the last two examples we reference $black-base and $black-dark. These variables are not defined locally, but if you refer back to our global variables example, you will see we defined them as global variables. Once again, this means the variable is avaliable for all selectors because it is not nested inside of a specific selector.

The mixture of both global and local variables in a small or large scale web project helps to keep our code extendable and error free. When kicking off a project or refactoring a previously developed project, keep these rules in mind.

Interested in more?

I'll be giving a talk on refactoring stylesheets at Front-end Camp in Chicago on June 3. Check out chicagocamps.org/ for more information. I look forward to seeing you there. Happy refactoring.

Or checkout out a couple of our previous blog posts on Sass development:

More posts
  • InVision's Design Disruptors

    DESIGN DISRUPTORS is a full-length documentary by InVision featuring design leaders and product designers from 15+ industry-toppling companies — valued at more than $1 trillion dollars combined.

    Read More
  • When Do You Know If It Is Time To Refactor

    How do we solve this problem? How do we know if it's time to refactor and fix these hacks / quick implementations? When is it worth it to invest a few extra hours or days to create a better component or module?

    Read More
  • 10 Great Design and Development Resources

    With tight deadlines and the need to make progress, I count on on a number of great resources for assets and inspiration that provide free or open source typography, photography, and more.

    Read More