
It all begins with the @extend...
It’s probably a safe bet you have heard of Sass, and for good reason too as using it really gives you an opportunity to organise and improve how you develop CSS. Before working at Primate I hadn’t had the chance to use Sass as part of my day job but I had experimented a little outside work. Chances are, quite a few developers are in the same boat right now. It’s also really worth mentioning that you don’t need to be a Ruby/Rails developer to use Sass! There are some great tools out there which are incredibly easy to use and let you use Sass without running Rails. So if you’re a PHP developer, or you build static sites, theres no reason you can’t get involved.
Now after telling you how awesome Sass is, I’m also going to tell you how you can use it to produce some really ugly and bloated CSS, ha! Yes it’s true you can use Sass to produce some nasty CSS… but only if you let it.
One of the cool and useful features of Sass is the @extend keyword. It gives you the opportunity to keep your CSS DRY and avoid the bloat you may experience using mixins. @extends let you define a block of style declarations and then let you apply these styles to other selectors throughout your Sass files. There are two ways this can be achieved in plain CSS – you either copy all the style declarations into multiple style blocks or you add multiple selectors to a generic style block. @extends do the latter. Anytime you use the @extend keyword, the containing selector is added to a style block, along with any other selectors that extend the same thing.
@extends are really handy and they let you introduce code to re-use in your stylesheets in the same way you would do if you were coding straight CSS. If you’re not strict on how you use them, then you’re probably going to introduce a lot of unwanted selectors into your CSS.
Should you @extend a class selector?
When you read the @extend documentation, the majority of the samples give an example of extending a class selector in the following way: @extend .error;. In the long run using a class selector as your style block identifier is not the best idea, especially if it’s quite a generic and regularly used class. A problem of using a standard class selector as your @extend identifier is that you extend any styles that feature that selector anywhere in your Sass.
As an example, let’s imagine you define a base block of styles with the class .standard_button. It’s a generic button used throughout the site which is styled with gradients, rounded corners, shadows, and is generally just pretty awesome. Initially you assign styles by giving elements in your HTML this class and often throughout the build you have to tweak the position of a button so you do this in CSS by using the .standard_button identifier. This is just plain old CSS so far. As a way of making your markup cleaner, you sometimes also use @extend .standard_button to reduce class declarations within your HTML. Perhaps it seems strange to use both @extends and class declarations within your HTML but I believe it’s something quite a few developers might find themselves doing. Unfortunately using both approaches will lead to generated CSS you don’t want.
As an example look at the code sample below which shows both the use of @extend and multiple selectors referencing the base class selector:
.standard_button {
display: block; padding: 10px; background: green; // Other styles...
}
#sidebar .signup .standard_button { margin-top: 22px; }
#registration .standard_button { margin-bottom: 33px; }
.article a { @extend .standard_button; }
When compiled the generated CSS will be like the following (note the selectors for the final two styles):
.standard_button, .article a {
display: block;
padding: 10px;
background: green;
}
#sidebar .signup .standard_button, #sidebar .signup .article a, .article #sidebar .signup a {
margin-top: 22px;
}
#registration .standard_button, #registration .article a, .article #registration a {
margin-bottom: 33px;
}
The selectors applied to the final two blocks of styles are just wrong and the chances are pretty high that you don’t want it in your CSS. I bet when you added .article a { @extend .standard_button; } you only wanted to extend the base definition (which it did as you can see on line 1). Unfortunately you have also @extended #sidebar .signup .standard_button and #registration .standard_button. Sass picks up that they are both definitions of .standard_button, it just happens that they have more specific selectors.
When I realised Sass handled @extends this way, it was one of those moments of satisfaction that comes with understanding a tool a little more. I’m not convinced I like that @extends work like this but that’s how it is and it’s better to know exactly how it works. To me, I think it would be better that when you extend a selector, you only extend that specific selector. For example, if I wanted to @extend the final two code blocks in the example above, I would have used @extend #sidebar .signup .standard_button; or @extend #registration .standard_button;.
If you’re thinking that doesn’t look too bad, keep in mind that the above is just a small example. If you’re working on a decent size site then the problems really balloons. Any time you @extend a class declaration, two additional sets of selectors are added to any selectors that feature that class declaration. So in the example above, if we added 5 extra @extends .standard_button; we would add an additional 10 selector lists to both of the others! It really can add up.
@extend placeholders for CSS Zen
The best way to avoid these problems is to use placeholder selectors in your @extends rather than using class selectors. The crux of the problem above is that you’re extending a class selector that may appear multiple times in your Sass file. To remove the problem we need to @extend something that only occurs once and placeholders allow us to do just that. Let’s rework the previous example, and use placeholders instead (note %standard_button on line 1 and @extend %standard_button on line 5):
.standard_button, %standard_button {
display: block; padding: 10px; background: green; // Other cool styles
}
#sidebar .signup .standard_button { margin-top: 22px; }
#registration standard_button { margin-bottom: 33px; }
.article a { @extend %standard_button; }
When compiled, the CSS we generate is more in keeping with what we were trying to achieve:
.standard_button, .article a {
display: block;
padding: 10px;
background: green;
}
#sidebar .signup .standard_button {
margin-top: 22px;
}
#registration .standard_button {
margin-bottom: 33px;
}
As a rule of thumb, it’s better to never extend a class selector and always to use a placeholder selector in it’s place instead. You can define the placeholder right at the same time you define your normal class selector, it keeps your Sass nice and readable. In the Sass reference, placeholders are described as being useful when you “run the risk of colliding with other classes that are being used in the HTML”. Why run the risk, use placeholders instead.
Wrap up
The examples in this article are basic (and perhaps almost trivial) but hopefully they make their point. What may seem simple can lead to a lot of confusion down the line, especially as your site and CSS grows. Ideally you want your CSS selectors to be specific and concise, which in turn results in CSS which is easy to read and to work with. Just as importantly, concise CSS leads to a smaller file sizes, which is vital for our mobile browsing buddies. There is also the funny (but surprisingly worrying) case of IE’s selector intolerance in version 8 and below which sets a maximum of 4095 selectors in any stylesheet.
There are nuances to how you choose to use @extends and perhaps you will come across an example of where you want to @extend selectors that are defined multiple times throughout your Sass. Either way keep an eye on your generated CSS because that at the end of the day is the final product.

[...] styles. It is like a variable on speed – since it’s more than just a string – but be careful about the [...]