HTML & CSS
Article

4 Sass Features You May Not Have Tried

By M. David Green

Once you’ve gone to the trouble of converting your workflow over to Sass, it’s easy to fall into familiar patterns. You may be so pleased with the power of what Sass can do with a few simple techniques that you never bother to explore some of the more advanced features. There are many advantages to using a powerful pre-processor like Sass, and it’s worth exploring some of the less familiar ways to use it.

1. CSS and Inline Comments

When styling a page, you may need to include comments in your CSS to make it clear to someone coming later just what you intended. Depending on how complex or specific your CSS is, leaving comments in the code can be helpful to the next person who steps into it and needs to make a change–and that person may well be you, six months later, when you’ve forgotten how that nifty hack you wrote was supposed to work!

Sass lets you include regular CSS comments with /* at the beginning and */ at the end. Comments like these can span multiple lines, and will be left intact in the final generated CSS. So for the following commented Sass:

a {
  color: #ccc;
  &.halloween { 
    /* This is for seasonal links */
    color: #ff8c00;
  }
}

The generated CSS will look like this:

a {
  color: #ccc;
}

a.halloween {
  /* This is for seasonal links */
  color: #ff8c00;
}

Sass also lets you include inline comments (or Sass comments) that are specific to the way the Sass is written. Unlike the CSS comments, Sass comments will not be printed out in the compiled CSS. Sass comments are single-line only, and start with a // to distinguish them from Sass code to be compiled.

So a commented Sass file like this:

a {
  color: #ccc;
  &.halloween { 
  // Chosen colour below after trying #ff8d00, #ff8b00 & ff8a00.
  /* This is for seasonal links */
  color: #ff8c00;
  }
}

Will still generate clean CSS, without the comment on the colors history:

a {
  color: #ccc;
}

a.halloween {
  /* This is for seasonal links */
  color: #ff8c00;
}

2. Local and Global Variables

Managing scope can be one of the trickiest aspects of working in any language, and Sass is no exception. Sass allows you to define both global and local variables, and override them as needed.

A common use of Sass global variables is the creation of color names, and semantic uses for those colors. For example, at the top of your main Sass file, you might define your $color_success as the accent color to use for successful operations, so it can be inherited and modified by any number of selectors that rely on it.

//defining a global success color
$color_success: #090;

.state_success {
  color: lighten($color_success, 50%);
  background-color: $color_success;
}

This will generate CSS like this:

.state_success {
  color: #9f9;
  background-color: #090;
}

The $color_success variable is a global variable because it was defined outside of any selector, and it will affect anything nested below its own scope. But it is not a constant, so you can change the value at any time, and the new value will start to be used for any selectors you define after that. For example, if the next selector in your Sass file looked like this:

.state_success_particular {
  //overriding the global success color locally
  $color_success: #900;
  color: lighten($color_success, 50%);
  background-color: $color_success;
}

The next selector in your generated CSS would reflect the new value for $color_success:

.state_success_particular {
  color: #f99;
  background-color: #900;
}

In this case, you have only changed the value of your global variable within the local scope of that selector. Any other selector you write after that scope is closed will use the original global value. If, instead, you had changed the variable outside of the selector, like this:

//Overriding earlier globals globally (a bad idea)
$color_success: #900;

.state_success_particular {
  color: lighten($color_success, 50%);
  background-color: $color_success;
}

You would have changed the value of the global variable for every subsequent selector in your CSS. That can be a bad idea, since the same variable will end up meaning different things to multiple selectors just because of the order in which they were processed. Keep that in mind, or you may find yourself expecting changes to global variables that you make inside one selector to apply outside of that selector.

3. Placeholders for Extends

Keeping your source Sass code clean is a great boon for development. Sass lets you nest selectors to help eliminate repetitive code, but the cost is that every level of nesting results in more selectors in your final CSS. Defining a @mixin is also great for @include-ing predefined subsets of styles into multiple selectors, but that can introduce redundancy and weight into your final CSS. While both of these familiar techniques are useful, they need to be handled carefully if you want to keep your CSS files small and efficient.

Fortunately, Sass also allows developers to extend existing selectors, applying all of the style definitions from one selector to another with a simple @extend command. For example, the following Sass allows multiple selectors to take advantage of the same styles in the .prominent selector:

.prominent {
  font-style: bold;
  font-size: 1.5rem;
}

.important {
  color: #900;
  @extend .prominent;
}

.notice {
  color: #090;
  @extend .prominent;
}

to generate this CSS:

.prominent, .important, .notice {
  font-style: bold;
  font-size: 1.5rem;
}

.important {
  color: #900;
}

.notice {
  color: #090;
}

But if you want to define sets of useful style definitions, and don’t want to create separate public selectors in your CSS for each, Sass lets you use placeholder selectors. These are defined just like class selectors, but they use the percentage symbol (%) instead of a period (.) at the start of the selector. So, using placeholder in this Sass:

%prominent {
  font-style: bold;
  font-size: 1.5rem;
}

%subtle {
  font-style: regular;
  font-size: 0.75rem;
}

.important {
  color: #900;
  @extend %prominent;
}

.notice {
  color: #090;
  @extend %prominent;
}

generates the following CSS, with no visible references to %prominent or %subtle anywhere, except in the styles that carry forward:

.important, .notice {
  font-style: bold;
  font-size: 1.5rem;
}

.important {
  color: #900;
}

.notice {
  color: #090;
}

In fact, in this case, we never used the %subtle placeholder style, and it had no impact on the size or selectors in our generated CSS.

One thing to note about extending both styles and placeholder styles when they use global variables is that they do their magic by adding selectors to a base style, rather than duplicating CSS code. This means that the value of the variables that were in effect when the original source style was defined will carry forward, even if the new style redefines the variable locally. For example, the following Sass with a global variable:

$color_highlight: #090;

%prominent {
  color: $color_highlight;
  font-style: bold;
  font-size: 1.5rem;
}

.important {
  @extend %prominent;
}

.notice {
  $color_highlight: #900;
  @extend %prominent;
}

ignores the override in .notice and uses only the original global value when generating the CSS:

.important, .notice {
  color: #090;
  font-style: bold;
  font-size: 1.5rem;
}

4. Ampersands for a Parent Selector

One of the basic features of Sass that developers learn about is the ampersand (&). When you prepend an ampersand to a parameter in a nested Sass selector, that selector becomes attached to the parent selector, instead of being nested below it. This is immediately useful for pseudo class selectors such as :hover or ::after that need to be associated with a selector. For example, this Sass:

.hoverable {
  color: #fff;
  &:hover {
    color: #ff0;
  }
}

results in the following CSS selectors:

.hoverable {
  color: #fff;
}

.hoverable:hover {
  color: #ff0;
}

The cool thing about ampersands is that they don't only have to be at the beginning of a nested style definition. Wherever you put an ampersand into your Sass selector definitions, it is interpreted to mean the parent scope of the current style being defined. Sometimes you need to define a style that takes the context of the existing style, but only applies in a special case. For example, what if we need a different border treatment for our .hoverable element when the parent class is .special:

.hoverable {
  color: #fff;
  &:hover {
    color: #ff0;
  }
}

.special .hoverable {
  border: 1px solid #f00;
}

Doing this required us to step out of our .hoverable selector and then re-define it inside a new selector. If there had been more levels of nesting, or more context that needed to be set, that could have been a fairly complex action.

But with the ampersand, Sass allows us to do the same thing without leaving the scope of the .hoverable selector:

.hoverable {
  color: #fff;
  &:hover {
    color: #ff0;
  }
  .special & {
    border: 1px solid #f00;
  }
}

Both of these Sass snippets will result in the following CSS:

.hoverable {
  color: #fff;
}

.hoverable:hover {
  color: #ff0;
}

.special .hoverable {
  border: 1px solid #f00;
}

Do you see what that line with the ampersand did? Sass replaced the ampersand with the parent selector, defining a new selector inside of the .special selector.

Think about how some of these ideas might be useful when you’re developing your next set of Sass styles. Since these are all part of the Sass core, you can start using them immediately in your projects, and taking advantage of the opportunity for cleaner, more maintainable, and more efficient development.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • Bruno Seixas

    Really learned a lot with this article =)
    Thanks :)

  • geoffyuen

    Is the scoping of variables new?

    • http://www.alwaystwisted.com/ Stuart Robson

      Hi, Geoff. The scoping of variables came into being with the latest stable version of Sass(3.4). Here’s a quick gist on Sassmeister – http://sassmeister.com/gist/dfcb059ed2761e20c071 (swap between 3.4/3.3/3.2 in the settings to see the difference. Although it’s mentioned in the changelog under 3.3s backwards incompatibilities section

  • http://areyouahuman.com Hassan Bazzi

    the % extend is PERFECT! I always wondered if that was possible.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.