If you want to DRY your CSS, the easiest way is to start using a pre-processor like Sass. Specially in the beginning though, you need to regularly look at what your Sass compiles to. By using mixins for instance, you can seriously scale back the amount of code you need to write. But if you don’t know how things compile, you’ll end up with DRY Sass and bloated CSS. Since that’s what gets send to the user agent eventually, you should try to prevent that.
Let me illustrate what goes wrong with a simple example (this code visually hides some text while keeping it available to alternative user agents, such as screen readers):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@mixin hide-text { text-indent: -9999px; overflow: hidden; } .foo { @include hide-text; } .bar { @include hide-text; } .baz { @include hide-text; } |
That looks like pretty clean Sass, right? Until you look at the compiled CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.foo { text-indent: -9999px; overflow: hidden; } .bar { text-indent: -9999px; overflow: hidden; } .baz { text-indent: -9999px; overflow: hidden; } |
So much for not repeating ourselves. Imagine doing this with embedded files for instance, using the inline-image()
Compass helper, and you’re in serious trouble.
The better solution
In this case using a %placeholder
and @extend
would have produced less CSS, with the same number of selectors (so it doesn’t make a difference in hitting the IE selector limit):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
%hide-text { text-indent: -9999px; overflow: hidden; } .foo { @extend %hide-text; } .bar { @extend %hide-text; } .baz { @extend %hide-text; } |
Which gets us this CSS:
1 2 3 4 |
.foo, .bar, .baz { text-indent: -9999px; overflow: hidden; } |
Ain’t that nice and clean!
So when should you use a mixin?
When you want the output of the mixin to change depending on how you call it. If you need to take arguments or a @content
block, a placeholder isn’t going to help you. Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@mixin border-radius($radius) { border-radius: $radius; } .foo { @include border-radius(5px); } .bar { @include border-radius(7px); } .baz { @include border-radius(9px); } |
It’s a subtle difference when writing Sass, but it can make a huge difference in your compiled CSS. Any questions, let me know in the comments and I’ll try to answer them.