Getting DRY With Sass
May 8th, 2012
I really like Sass. Like LESS, Sass is a language / framework which compiles down to CSS and, as its creators so accurately describe, “makes CSS fun again”. Indeed.
The thing I like most about Sass is how it helps you apply the DRY principle to your style sheets. If you use it well, you can drastically cut down “copy-and-paste” code and actually get reasonably maintainable CSS to work with.
So, how does Sass help your CSS get and stay DRY? Let’s go to the videotape.
Define Your Hierarchy
Actually, before getting into the whole DRY thing, let’s first use Sass to get organized.
I always found it really painful to organize large CSS files in a way that makes sense. Do I group by area of the page? Do I separate things into element-based, id-based, and class-based styles? What happens if I try to use the same style rules for different elements? Inevitably, I would get something like this:
/* common */ body {font-family: 'Armata', sans-serif; font-size: 1em; color: #3F3E3A; background-image:url(images/background.png);} article p, article ul, article ol, .comment-body p {font-family:"merriweather", serif;} a {text-decoration: none; font-weight: normal; color: #43B1E1; } p, li {line-height: 1.7em; margin: 0 0 10px 0; font-size: 1em;} ul, ol {padding-bottom: 20px; padding-left: 20px;} h1 a {color: #006794; font-size: 1em; line-height: 1.4em;} h2, h3, h4 {color: #3283A6; font-size: 1.1em; padding: 20px 0 10px 0; line-height: 1.5em; font-weight: normal;} h3, h4 {font-size: 1em; padding: 10px 0 5px 0;} /* header */ #main-header {padding: 30px; background-color: white; border-top: 5px solid #B3B3B3;} #header-container {width: 920px; margin: auto;} #blog-title {font-size: 2em; padding-right: 10px; margin-left: 40px; border-right: 1px solid #B3B3B3; } #blog-title a {color: #323036;} ...
While not terrible, this is pretty noisy and hard to modify, especially if you’re sharing styling rules.
How would I make it better? Well, to me, the most logical way to organize a CSS file is to make it follow the same hierarchy as the HTML it styles. Let’s look at example. Suppose you had to style the following HTML:
<header> <h1>Welcome to my site</h1> </header> <nav> <ul> <li>page 1</li> <li>page 2</li> </ul> </nav> <article> <h2>Lorem ipsum dolor sit amet</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit....</p> <h3>Lorem ipsum dolor sit amet</h3> <p>Vestibulum ante ipsum primis in faucibus orci luctus et...</p> <aside> <h2>did you know?</h2> <p>Duis egestas ornare justo eget iaculis....</p> <ul> <li>important point 1</li> <li>important point 2</li> </ul> </aside> </article> <footer> <section> <h2>Archives</h2> <ul> <li>April 2012 (5)</li> <li>March 2012 (6)</li> <li>February 2012 (9)</li> <li>January 2012 (4)</li> </ul> </section> </footer>
The markup above is semantically sound and follows a logical hierarchy: there is a header, a nav bar, an article, a footer, and so on. Wouldn’t it be great if you could organize the style sheet in a similar fashion?
Unfortunately, this is impossible to do with pure CSS because you can’t nest rules. Fortunately, it’s no problem with Sass:
[sass]
body {
header {
h1 {
}
}
nav {
ul {
li {
}
}
}
article {
h2 {
}
h3 {
}
p {
}
Garlic is nitrates rich food also contains quercetin directly linked to the increased level online purchase viagra of nitric oxide production. Men who have taken the medication to treat their condition effectively and to normalize their sexual health. cialis india online purchased this The inability to gain erection can be a frequent difficulty when guys achieve the buy viagra without prescriptions age of 30-70. Moreover, reports claim that these bankers, lawyers and hedge-fund managers are having the pills delivered to them at brand cialis canada work to the best of their capability.
aside {
}
}
footer {
section {
ul {
li {
}
}
}
}
}
[/sass]
By the way, though I haven’t defined any actual rules yet, the Sass code above is perfectly valid.
A Note About Performance
It’s true that deep nesting of rules negatively impacts CSS rendering performance. For instance, a rule like body footer selection ul li {...}
will get processed slower by the browser than a rule like .menu-option {...}
. Furthermore, using generic selectors like body
is slower than using specific selectors like .post-headline
or, even better, #post-content
.
I should note that you can address some potential performance issues with additional markup. For example, you can tag HTML elements with ids and classes and then use them in your Sass:
<nav> <ul id="site-menu"> <li class="menu-option">page 1</li> <li class="menu-option">page 2</li> </ul> </nav>
[sass]
#site-menu {
.menu-option{
…
}
}
[/sass]
This trick might be especially useful for “leaf” elements because CSS is evaluated right to left by the browser.
So, the bottom line here is this: as is typical in software development, using certain approaches can mean a choice of maintainability over performance. Whether that trade-off is justified is up to you to determine.
On a separate note, there is a whole science on how to optimize your CSS performance. Even if you don’t have performance issues with page rendering, it may still be worth investigating.
Define Your Levers
Once your hierarchy is laid out, you can finally focus on getting DRY. A key enabler of reuse in Sass is variables. For example, I really like to define a small set of “site control” variables for layout, color, and fonts:
[sass]
$base-font-size: 16px;
$body-width: 90%;
$text-color: #44474F;
$main-color: #C46D3B;
$accent-color: #9C9985;
$body-font: ‘Arial’;
$heading-font: ‘Georgia’;
[/sass]
From then on, I only use the variables (or derivations of thereof) to specify actual styling rules:
[sass]
h1 {
font-size: $base-font-size * 1.8;
font-family: $heading-font;
color: lighten($main-color, 10%);
border: 1px solid lighten($text-color, 40%);
}
[/sass]
This is helpful for a number of reasons, but the biggest one is that I can change a whole bunch of aspects of how the page looks by just tweaking a single parameter. Awesome.
Mix in Some Reuse
In addition to variables, Sass lets you define reusable chunks of rules called mixins.
For example, I sometimes need to create a container which is centered inside its parent and automatically expands to contain any floated children. However, because I may use it in different parts of the page, other aspects like width and gutter size (clearance on left and right) might change.
So, I can define a @mixin
for such a container and then @include
it wherever I need it, specifying parameters which differ:
[sass]
/* define mixin */
@mixin centered-container ($width, $gutter) {
margin: auto;
overflow: hidden;
width: $width;
padding-left: $gutter;
padding-right: $gutter;
}
/* use mixin */
header {
@include centered-container(90%, 5%);
}
[/sass]
Modularize Your Code
One of the big problems with CSS is a lack of modularization. Yet, whether you have chunks of CSS you’d like to reuse between projects or because you’d like to break up your project’s CSS into chunks, it’s good to have modularity.
Sass addresses this with the @import
feature. Just as the name implies, you can import styles defined in different files into your main stylesheet. And the best part is that import directives get processed at compile time. This means that you still get only 1 CSS file to include in your page, saving precious round trips to the server (By the way, this feature is the main reason I prefer Sass over LESS).
What About Compass?
Compass is a framework built on top of Sass which does a lot of stuff. It takes the ideas discussed here (along with many others) to a whole other level of sophistication (and perhaps complexity). I personally find Compass to be a bit of overkill for smaller projects and haven’t really used it for larger ones. That said, it may very well be that the additional complexity Compass brings is justified if you have large teams and/or code base.
You may also like:
Did you love / hate / were unmoved by this post?
Then show your support / disgust / indifference by following me on
Twitter!
This post got 2 comments so far. Care to add yours?
I like your blog- but the green is very difficult to read – esp. in the lists and paragraph text. I like your color theme but suggest you go darker on the green.
best —
Thanks for the feedback, I really appreciate it. I did notice that the lighter shades are faint on some monitors.