Sass preprocessors have reached critical mass to consider them a mainstream technology. Nowadays almost nobody that does some serius frontend still uses plain old css, but some people that uses sass (or less) are using it like if it where just regular css with nesting and some sintax sugar, without squeezing all the power that those technologies put in our hands.
This a summary of the main 3 features o SASS, pointing out its differences.
Mixins are the most known feature of sass. They allow us to create a sort of functions to share similar styles among our selectors (well, sass also has functions, but I can’t find a better word). The most evident use case is the mixins that apply vendor prefixes:
1 2 3 4 5 6 7 8 9 10 11
Mixins are the first feature that a sass beginner learns, but is surprising how often I see them used the wrong way.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Whats wrong with that? It’s not DRY.
This is the generated output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
We see the exact same 6 lines repeated over and over in our css.
The golden rule of where a mixin is a good choice is just a few line above:
They allow us to […] share similar styles among our rules
The keyword here is similar.
A mixin is used to reuse rules, not values. In this case to create rounded borders of different radius, but if your ever find yourself writting a mixin that don’t take arguments, you are doing it wrong.
@extends directive, on the other hand, is the static cousin of
It is designed for sharing rules and values between selectors while avoiding repetitions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
This time, the generated CSS looks like this:
1 2 3 4 5 6 7 8 9 10
It has just a fraction of the lines that the mixin approach, which is nice because lighter stylesheets means faster loading times, specially with slow connections (mobiles), and for the browser is also much more efficient to parse one single rule applied to several selectors than apply the same rule once for each selector.
This is awesome because thanks to
@extend we can have human-readable sass stylesheets (you know, split stylesheets in
several files, put together rules that apply to the same sections or components of the design, …) and at the
same time have machine-optimized css (all selectors that extend the same parent are chained in one single rule, no
matter in which file or how conceptually unrelated they are) and at the same time we can keep clean our html because
we don’t need to add all over the markup classes like
.highlighted-text that have no
meaning from the point of view of the application’s domain.
I know that some people disagree on what html classes are, but I am a big fan of use classes
to represent what that element means (
.selected-day by example) and not
how they must look (
After reading this you might wonder why if
@extend are so cool, is not so popular and used as mixins.
@extend can be dangerous.
The problem with this directive extending classes or id’s, is that when that rules you are extending appears nested on the application, sass must generate all the posible combinations between the nesting classes and the rules that includes them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
.button is a class that is very likely to be customized depending on its containing form, so if with
just 3 appearances generates this dissaster, with 10 appearances just let your imagination fly.
So the rule of thumb is: “Only extend a selector if you are absolutely sure that it is never reused in several places”.
But the bad part is that you can’t always be sure of this, and even if you are sure that at this moment you satisfy that rule, in the future, you or one of your coworkers can, inadvertently, screw things up.
Placeholders are an killer-feature added in sass 3.2, and they come to fix the mess I described before.
Unlike normal selectors, like
#ids, placeholders won’t be never compiled. In other words, this little piece of sass
1 2 3 4 5 6
There is no reference to
%button because placeholders are just named sets of styles meant to be extended by
other selectors, and don’t have existence on its own.
Since they don’t have existence on its own, they can’t be nested, so you can use
@extend %placeholder-name with complete safety.
The previous messy example that used
@extend on a class could have been written using placeholders this way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
and you only get the rules you intended to get:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
After reading about the differences between mixins, extending classes and extending placeholders, these are some of the golden rules that I follow when writing stylesheets:
- NEVER declare mixins that don’t accept params: This are not mixins, the are classes/placeholders
- NEVER (or almost never) extend normal selectors. You can get unexpected results if that selector appears nested somewhere else on the stylesheets. Use placeholders instead.
- Don’t over-nest selectors. With sass is easy to forget about the chain an create infamous selectors with 6-7 chained rules.
- Don’t use tag names in selectors if you can avoid it. That not a taxative rule, but the are less efficient that classes or ids.
- Don’t use inheritance operator(“>”). It is VERY unefficient.
- Don’t trust blindly on what you think that sass is generating. Check the generated css from time to time. You can discover mistakes than are unnoted in sass.
- Create a colour pallete using variables from the beginning. If you don’t do so, you can easily end with 18 different tones of gray thar are only used in one or two places.
- Refactor. While most people cares about its backend/frontend code, the percentage of people that just open existing stylesheets and adds some new rules to style that new widget he created without trying to reuse existing styles is much higher.