Getting Started with Sass, Part 3

In Part 1 of this series, I introduced you to CodeKit and Sass basics like partials, variables, comments and errors. In Part 2, I showed you how to achieve vertical rhythm using variables and math operators, and demonstrated how the Sass nesting syntax makes media queries easier to maintain.

In this Part 3, I’m going to explore mixins and placeholders, and demonstrate how to use frameworks to import useful mixins and make development faster.

Mixins

Mixins are another key element of Sass, and they can be very powerful. Mixins are essentially formulas of different CSS or Sass rules grouped together. The same mixin can be used in multiple places throughout a stylesheet. If the mixin rules are changed, the output CSS will be changed wherever that mixin is used, which can save a lot of time and repetition.

You define a mixin with the @mixin directive, followed by a unique name of your choice. The curly brackets contain the style declarations for that mixin:

@mixin mixin-name {
  margin: 0;
  padding: 0;
}

You can then reference the mixin in your Sass by including it in a rule:

ul {
  @include mixin-name;
}

Which compiles to the CSS:

ul {
  margin: 0;
  padding: 0;
}

Mixins with Variables

You can use variables in mixins to create reusable chunks of CSS that can vary slightly each time they appear. Consider these navigation buttons, which share some fundamental styles with a few variations:

These buttons are similar in style, but with different text and background colors

With traditional CSS, the button rules might look something like this:

.button {
  border-radius: 10px;
  padding: 0 15px;
  text-decoration: none;
  text-transform: uppercase;
}

.active-button {
  background: #637a3d;
  color: #c0d0aa
}

.inactive-button {
  background: #3f5526;
  color: #f9f9f9;
}

And the HTML would reference two classes in order to have both the base and variant styles:

<a class="button active-button" href="">Button</a>

With Sass mixins, you can bring these common rules together in one mixin, specifying their different text and background colors using variables. First, define the mixin with a name, then list the variables that the mixin will use, separated by commas, inside parenthesis:

@mixin button($text, $background) {
}

Next, within the curly braces for the mixin rule, add the common properties and values:

@mixin button($text, $background) {
  border-radius: 10px;
  padding: 0 15px;
  text-decoration: none;
  text-transform: uppercase;
}

For the styles that will vary, use variables for the property values:

@mixin button($text, $background) {
  background: $background;
  border-radius: 10px;
  color: $text;
  padding: 0 15px;
  text-decoration: none;
  text-transform: uppercase;
}

Then apply the mixin to each unique button rule using the @include directive, replacing the $text and $background variable names with the actual values you’d like to use, which can themselves be variables defined elsewhere in your Sass. Here I’m using the color variables I defined in Part 1:

.active-button {
  @include button($green-mid, $green-light);
}

The values must occur in the same order as they are defined in the mixin so Sass can apply them in the proper order when it compiles the CSS. Here, the first value is for the text color and the second value is the background color. Our two button variations can now use the same mixin with different color values:

.active-button {
  @include button($green-mid, $green-light);
}

.inactive-button {
  @include button($grey-light, $green-dark);
}

Which compiles to:

.active-button {
  border-radius: 10px;
  background: #637a3d;
  color: #c0d0aa
  padding: 0 15px;
  text-decoration: none;
  text-transform: uppercase;
}

.inactive-button {
  border-radius: 10px;
  background: #3f5526;
  color: #f9f9f9;
  padding: 0 15px;
  text-decoration: none;
  text-transform: uppercase;
}

Mixins vs. Placeholders

In the Web Talk Dog Walk site, I might use a mixin to hide content visually but allow screen readers to access it (screen readers won’t read content hidden with display:none):

@mixin hide {
  height: 0;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

The hide mixin is a handy set of rules, and not specific to any HTML element. This means I could use it for many elements on the site:

.site-title {
  @include hide;
}

.skip-link {
  @include hide;
}

Unfortunately, this results in the same set of declarations output twice:

.site-title {
  height: 0;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

.skip-link {
  height: 0;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

Not only is this is unnecessarily repetitive, it adds bloat to the CSS file. This is where placeholders come in handy.

Placeholders

Placeholders are much like mixins, but they don’t work with variables. Most importantly, placeholder output is grouped together into one rule in the compiled CSS. Define a placeholder with a % followed by a unique name. The curly braces contain the style declarations for that placeholder:

%hide {
  height: 0;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

To include the placeholder’s styles within a rule, use the @extend directive:

.site-title {
  @extend %hide;
}
.skip-link {
  @extend %hide;
}

This approach is very similar to including the mixin, but the difference is that the %hide placeholder CSS will be compiled as one rule:

.site-title, 
.skip-link { height: 0; margin: 0; overflow: hidden; padding: 0; }

Sass collects all the selectors for every rule where the placeholder appears and puts them into one rule, applying the placeholder’s styling to all of those elements. This results in less repetition than using a mixin, giving you a smaller, faster stylesheet.

Using Mixins for Prefix Support

One popular use of mixins is to automatically include vendor prefixes. There are many properties in CSS3 that will only work in some browsers with the correct prefix. CSS transitions, for example:

a {
  background-color: #ff3000;
  -webkit-transition: background-color 1s ease;
  -moz-transition: background-color 1s ease;
  -ms-transition: background-color 1s ease;
  -o-transition: background-color 1s ease;
  transition: background-color 1s ease;
}

a:hover {
  background-color: #ff9500;
}

Staying up-to-date with the changes in all modern browsers is a lot of work. There’s loads of prefixes to remember, subtle differences in the prefix syntax, and a lot of repetition. Luckily there are Sass frameworks and libraries that keep up with the changes browsers are making. Sass libraries are collections of mixins that you can use in your stylesheets. Two of the most well-known Sass libraries are Compass and Bourbon.

Adding Bourbon to a Project

You can install Bourbon as a Ruby gem with a few commands, but if you’re using CodeKit it’s already included. It’s easiest to add Bourbon to a project in CodeKit; all you need to do is import it:

@import "bourbon";

I usually include Bourbon above my partials in my main Sass file:

@import "bourbon";
@import "mixins.scss";
@import "variables.scss";
@import "reset.scss";
@import "fonts.scss";
@import "base.scss";
@import "header.scss";
@import "illustration.scss";
@import "layout.scss";

When Bourbon is imported, you can make use of all the mixins found in the Bourbon Docs, such as CSS transitions:

a {
  background-color: #ff3000;
  @include transition (background-color 1.0s ease);

  &a:hover {
    background-color: #ff9500;
  }
}

Which compiles to:

a {
  background-color: #ff3000;
  -webkit-transition: background-color 1s ease;
  -moz-transition: background-color 1s ease;
  -ms-transition: background-color 1s ease;
  -o-transition: background-color 1s ease;
  transition: background-color 1s ease;
}

a:hover {
  background-color: #ff9500;
}

Start Small, But Start!

Sass is very powerful, and there are new features being added frequently. But it’s very easy to start small and get used to how it works, before exploring more complex functions and features. I recommend that you start by adding color variables (Part 1) or nesting your media queries to make your styles easier to read (Part 2). Soon you’ll be writing your own mixins like a pro.

Going the Extra Mile

Sass allows you to write your own custom functions. These can be useful for integrating Sass into other languages and technologies, and the syntax is straight-forward for those with programming experience. However I don’t use custom functions in my work, as I find the programming abstracts the readability out of the stylesheets. I primarily use Sass to prevent repetition and make stylesheets easier to maintain, so adding complexity seems to defeat the point!

However, there are many smart people creating custom functions if you want to dive deeper into Sass. One of those people is Hugo Giraudel, who has a huge list of his Sass-related links on Github.

Pitfalls to Avoid

  • Avoid using mixins where placeholders could be used. Repetitive use of the same mixin with the same variables will result in very long and bloated CSS.

Things to Do

  • Use a framework such as Compass or Bourbon for ready-made mixins.
  • Understand the difference between mixins and placeholders to prevent unnecessary repetition and bloat in your stylesheets.

Further Reading