Boost Sass & Compass efficiency

Many say CSS pre-processors create bloated code, lacking the efficiency of handwritten CSS. Ben Frain looks at techniques in Sass and Compass to streamline outputted CSS

This article first appeared in issue 233 of .net magazine – the world's best-selling magazine for web designers and developers.

While the authoring environment is certainly more favourable when using Sass and Compass as opposed to standard CSS, a common concern is that the resultant code will be more bloated than if it was written ‘by hand’. This could lead to CSS that is harder to manage with elements written and overwritten a number of times, but also code that has a larger footprint than it needs. Here, we’ll employ features of Sass and Compass that can trim excessive code and possibly even generate CSS that is more efficient than if you’d written it yourself.

Including frameworks

When starting a project in Sass and Compass many users have their own ‘base’ template. It might be a handcrafted set of partial files or a Compass version of the HTML5 boilerplate or the Foundation Framework. One benefit of using the Sass and Compass versions of these frameworks is that they are modular, so it’s easy to switch off elements that aren’t needed. So, when using the HTML5 boilerplate as a starting point, if support for lists, embeds or any other modules isn’t needed, comment them out or remove them entirely. For example:

@include h5bp-display;@include h5bp-selection;@include h5bp-base;@include h5bp-links;@include h5bp-typography;//@include h5bp-lists;//@include h5bp-embeds;//@include h5bp-figures;@include h5bp-forms;//@include h5bp-tables;//@include h5bp-helpers;

The benefit of modular frameworks such as Foundation is that you only need to include the parts you actually require

Only use one reset

It’s a similar story for resets. If starting with a framework, there is usually a reset included, or Normalizer might be being employed to serve that purpose (there’s a good Sass version here). Either way, if there is already a reset of some sort, there is little point including Compass’s own reset, which is included by default when creating a project from the command line:

compass create <project name>

Look for the following line and comment it out if it’s not needed:

@import "compass/reset";

Output format

Sass and Compass provide the ability to compile CSS in a number of ways (expanded, compressed and so on). The settings for this are defined in the config.rb file in the root of the project. When you are ready to move code to production, look for the following lines:

output_style = :expanded

Then, to create the smallest possible CSS file, change it to be:

output_style = :compressed

It’s essential to change the setting to ‘compressed’ when producing CSS for production. By compressing the CSS and having the server send it gzipped (Google Page Speed will warn if your server isn’t sending the CSS gzipped), it can offer a huge economy. Sass core team member Chris Eppstein advises that “CSS in particular, due to all the redundancy and verbosity of the language compresses extraordinarily well. It can become 30 per cent down to 10 per cent of the original size”.

Use Compass? Consider what features you can live without in order to generate leaner code

If developing a site using one setting (such as ‘nested’ or ‘expanded’), you can force a change as a one-off from the command line (for example, if you were developing using the expanded setting but wanted to check the compressed file size of the exported CSS). To force a different export setting, run this command:

compass compile --output-style compressed --force

Alternatively, if you are producing a CSS file with Sass and Compass to hand over to someone else to work with, then you can retain CSS comments but remove Sass comments and line number debugging comments in the expanded setting by changing the following value in config.rb:

line_comments = true

Change the value to:

line_comments = false

Finally, it’s worth knowing that you can add a ‘loud’ comment. These comments are never removed, regardless of output mode. Do this by adding an exclamation mark as the first character of a CSS comment:

/*! This will not be removed. Useful for copyright notices and similar */

LiveReload supports Sass 3.2 Alpha from 3.2.8 onwards. A graphical interface for selecting custom compilers is promised for a future version

Browser support

One draw of Sass is using the Compass ‘authoring framework’ to take some labour out of writing the various CSS3 syntaxes (gradients can be a real burden). But by default Compass has support for a large number of browsers. In instances where a specific vendor prefix isn’t needed (such as an internal project) it can be removed. But it’s a micro optimisation so isn’t recommended for public websites.

Here are some of the defaults:

$experimental-support-for-mozilla : true !default;$experimental-support-for-webkit : true !default;$support-for-original-webkit-gradients : true !default;$experimental-support-for-opera : true !default;$experimental-support-for-microsoft : true !default;

You can switch off support by adding the variable like this:

$experimental-support-for-opera : false;

It’s preferable to include the variable before calling the Compass CSS3 module:

$experimental-support-for-opera : false;@import "compass/css3";

Note that among more obvious variables there is one, included by default, for the original WebKit gradient syntax – do you need it? Great if you do, but if not it’s a prime candidate for removal: gradient code is often quite verbose. Similarly, there are variables for legacy IE support. If you don’t care about supporting IE6 or 7 hacks, include this variable in the same manner as before:

$legacy-support-for-ie: false;

For a full list of support that can be toggled in this manner, there’s a handy page on the Compass site.

Want to use the Alpha version of Sass with CodeKit? The Preferences panel enables you to specify the correct compiler

Extend

If you have used Sass for any length of time, you’ll be familiar with the @extend directive. It enables one rule to inherit the styles of another. For example, first let’s create some colour variables:

// Colour variables$grey: #bfbfbf;$dark: #999;$red: #ff0b13;

Now let’s add our first rule, a standard box we might use throughout a site:

// Box.box { padding: 2em; background-color: lighten($grey, 20%); color: $dark;}

Here, we’ve just added some padding, used the colour function of Sass to create a background colour 20 per cent lighter than the $grey variable and then set the colour to be the $dark variable. Here’s what that compiles to:

.box { padding: 2em; background-color: #f2f2f2; color: #999999;}

If we were writing standard CSS, and wanted to use that box as the basis of another box for another style we might just copy and paste that rule below, rename and add any other declarations. For example:

.warningBox { padding: 2em; background-color: #f2f2f2; color: #999999; border: 2px dotted #ff0b13;}

It’s not the best way to do it. It’s more efficient to only define any extra declarations that differ from the first. But how many of us have been guilty of this when writing standard CSS in a rush? In this instance, only the border property and value pair differ from the .box rule. Thankfully, if you are using Sass and make use of the @extend directive it does the heavy lifting for you, for example adding the following below our existing .box style in a Sass file…

// Warning Box.warningBox { @extend .box; border: 2px dotted $red;}

…would result in the following compiled code:

.box, .warningBox { padding: 2em; background-color: #f2f2f2; color: #999999;}.warningBox { border: 2px dotted #ff0b13;}

Sass will combine styles where appropriate and generate the most efficient code. While we are always capable of producing an error ‘between the keyboard and chair’, Sass is not. This necessitates there being a pre-existing rule we can lean on. But the placeholder feature in Sass 3.2 takes this abstraction up a level.

Placeholder selectors in Sass 3.2 enable the creation of classes that are only used for extending. If they are not extended with the @extend directive in a rule, they create no output. For instance, perhaps in our prior example we need a few classes for different boxes (warning box, success box, information box) that are based on the same styles with subtle variations. With a placeholder, there is no need to create a style for the ‘base’ box style if it will never be used. Instead create a class with % at the beginning instead of a the usual full stop:

// Box%box { padding: 2em; background-color: lighten($grey, 20%); color: $dark;}// Warning Box.warning-box { @extend %box; border: 2px dotted $red;}// Warning Box.success-box { @extend %box; border: 2px dotted $green;}// Information Box.info-box { @extend %box; border: 2px dotted $blue;}

This would result in the following CSS being compiled:

.warning-box, .success-box, .info-box { padding: 2em; background-color: #f2f2f2; color: #999999;}.warning-box { border: 2px dotted #ff0b13;}.success-box { border: 2px dotted #11c909;}.info-box { border: 2px dotted #091fff;}

Placeholder styles add convenience and a level of abstraction harder to achieve via CSS alone. Combined with variables they provide code snippets that can be used across projects to create common interface patterns with little effort.

Unless your Google Page Speed Insights score is around 95, Paul Irish doesn’t feel worrying about CSS optimisation represents a sensible use of time

A note on nesting

Sass provides the ability to nest rules, but over-nesting can mean bloated code. Eppstein notes, “This is an anti-pattern and should be avoided. Comments make a better grouping mechanism. A user should ask: Does this li need to be nested in the ul selector? Are there other li elements that might exist outside this ul?”

It can be particularly problematic when extending existing rules. For example:

// terrible over-nesting example.container .link-wrapper ul li a.link { color: $red;}footer ul li a.footerLink { @extend a.link;}

…would compile to the following in CSS:

.container .link-wrapper ul li a.link, .container .link-wrapper footer ul li a.footerLink, footer .container .link-wrapper ul li a.footerLink {color: #ff0b13;}

Conclusion

Using a pre-processor to generate style sheets needn’t result in bloated code. By taking note of Sass and Compass’s finer details and features such as placeholder styles, outputted files can perform better, with smaller footprints. And those working with them in future should find them DRY-er, so easier to work with.

Thanks to Chris Eppstein for his peer review of this tutorial

Discover 30 inspiring examples of CSS at our sister site, Creative Bloq.