4 Sass Features You May Not Have Tried

Share this article

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.

Frequently Asked Questions about Advanced SASS Features

What is the purpose of the @at-root directive in SASS?

The @at-root directive in SASS is used to break out of the current scope and make styles appear at the root of the generated CSS. This is particularly useful when you want to define keyframes or other global styles inside a module or mixin, but you want them to appear at the root of your CSS file. It helps in maintaining the cleanliness and organization of your SASS files.

How does the ‘not’ selector work in SASS?

The ‘not’ selector in SASS is a powerful tool that allows you to exclude certain elements from a selection. It works by selecting all elements that do not match a certain condition. For example, :not(.class) will select all elements that do not have the specified class. This can be incredibly useful for applying styles to a broad range of elements, while excluding a few specific ones.

Can I use logical operators in SASS? How?

Yes, SASS supports logical operators like and, or, and not. These can be used in conditions to control the flow of your styles. For example, you can use the ‘and’ operator to apply a style only if two conditions are met. Similarly, the ‘or’ operator can be used to apply a style if either of the conditions is met. The ‘not’ operator is used to reverse the result of a condition.

What is the use of the ‘&’ operator in SASS?

The ‘&’ operator in SASS is used to reference the current parent selector. This can be incredibly useful when you want to create complex nested rules. For example, if you have a rule like .parent & { color: red; } inside a .child selector, it will compile to .parent .child { color: red; }. This allows you to write more maintainable and readable code.

How can I use interpolation in SASS?

Interpolation in SASS is done using the #{} syntax. It allows you to insert the value of a variable or the result of a function into your styles. For example, if you have a variable $color: red;, you can use it in a property like color: #{$color};. This will compile to color: red;. Interpolation can be used in any part of your styles, including selectors, property names, and URLs.

What is the purpose of the @content directive in SASS?

The @content directive in SASS is used to inject styles into a mixin. When you include a mixin and pass a block of styles to it, those styles can be inserted into the mixin using the @content directive. This allows you to create reusable and customizable styles.

How can I use the @debug and @warn directives in SASS?

The @debug and @warn directives in SASS are used for debugging purposes. The @debug directive prints the value of a variable or expression to the console. The @warn directive does the same, but it also highlights the message as a warning. These directives can be incredibly useful when you’re trying to figure out why your styles are not working as expected.

Can I use loops in SASS? How?

Yes, SASS supports both for and each loops. The for loop is used to repeat a block of styles a certain number of times, and the each loop is used to iterate over a list or map. These loops can be incredibly useful for generating repetitive styles or for working with complex data structures.

What is the use of the @if and @else directives in SASS?

The @if and @else directives in SASS are used to apply different styles based on a condition. The @if directive applies a block of styles if a certain condition is true, and the @else directive applies a block of styles if the condition is false. This allows you to create dynamic styles that adapt to different situations.

How can I use the @function directive in SASS?

The @function directive in SASS is used to define a reusable function that can return a value. This can be incredibly useful for complex calculations or for encapsulating a piece of logic that you want to reuse throughout your styles. To use a function, you simply call it by its name and pass any required arguments to it.

M. David GreenM. David Green
View Author

I've worked as a Web Engineer, Writer, Communications Manager, and Marketing Director at companies such as Apple, Salon.com, StumbleUpon, and Moovweb. My research into the Social Science of Telecommunications at UC Berkeley, and while earning MBA in Organizational Behavior, showed me that the human instinct to network is vital enough to thrive in any medium that allows one person to connect to another.

Sass Extendssass variablesStuR
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week