My Sass and CSS Best Practices

Modularization, Nesting, Variables, Mixins, Specificity, Etc

In the week since I tweeted this, I’ve been asked about what I meant by it a half-dozen times. As with any dev tool, Sass’s power can be both a boost to productivity and a source of scorn because of misuse. I’ve even been told by a couple of people that they don’t allow their staff to use Sass/Less/CSS preprocessors because of the horrible¬†unmaintainable CSS that it generates. Looking back at the Sass I wrote when I first started using it vs the Sass that I write now, I’m 100% certain that the problems these dev shops have lie 100% with the way the tools are being used, not the tools themselves.

Let’s take a look at some of the lessons I’ve learned and methods I use to write Sass that compiles to clean CSS.

  • Indentation vs. Nesting
  • Modularization
  • Variables
  • Mixins
  • Classes vs. IDs

Nest if Necessary – Indent the Rest

While looking back at the first CSS I wrote with Sass, I have to fight the urge to projectile vomit on my keyboard. Everything is nested ten selectors deep, which creates beautiful Sass but very, VERY ugly CSS. It’s the main reason why so many shops don’t use CSS preprocessors. This is what typical Sass and CSS looks like the first time someone uses it:

/* Sass */
body {
  .wrapper {
    .content {
      #top-story {
        .title {
          a {
            /* STYLES HERE */
          }
        }
      }
    }
  }
}

It’s so organized. You can read it just like you do the HTML. But this, of course, outputs a selector that looks like this:

body .wrapper .content #top-story .title a {
  /* STYLES HERE */
}

This selector is far too specific to be useful. At this point, you might as well ID everything (also not a good idea). Going far in the opposite direction is also not desirable:

body {
}
.wrapper {
}
.content {
}
#top-story {
}
.title {
  a {
    /* STYLES HERE */
  }
}

While writing sass like this improves the CSS that is output, it is fairly unreadable. That’s why I nest if necessary (.title a {}) and indent the rest:

body {
}
  .wrapper {
  }
    .content {
    }
      #top-story {
      }
        .title {
          a {
            /* STYLES HERE */
          }
        }
    .sidebar {
    }
      .widgets {
        hr {
        }
      }
    footer.main {
    }

Nesting if necessary and indenting the rest keeps your code very readable, as well as outputting beautiful CSS. Remember you can see this in action in my responsive WordPress boilerplate, Squeaky Clean, in any of the scss files.

Modularize Your Sass for Maintainability

One awesome benefit of Sass is it’s ability to take multiple files, all of which contain media queries (if that’s your sort of thing), and compile them into one CSS file. Breaking them apart greatly improves maintainability of your code. You no longer are working in the one-stylesheet-to-rule-them-all world where the attribute you’re looking to change is on line 8,405 and overwritten on line 5,336. This division of files also allows multiple developers to work together on a site with far fewer problems. My typical style.css looks like this:

@import "variables";
@import "mixins";
@import "reset-normalize";

/* PAGE LAYOUT */
@import "structure";
@import "header";
@import "navigation";
@import "content";
@import "posts-comments";
@import "footer";

The structure of Squeaky Clean's scss filesEach @import statement imports one Sass file. Name these modules “_structure.scss”, “_header.scss”, etc, with each name starting with an underscore. Sass is smart enough to know @import “footer”; needs to import _footer.scss.

This naming convention also creates a file tree (as you can see to the right) that is easily navigated with the eye, no matter how many files you’ve created.

You can see an example of this used in Squeaky Clean.

Variables

I can’t say enough amazing things about Sass variables. As you can see in my responsive WordPress boilerplate, I’ve used variables to store the site colors, standard greys, and typography, link, form, button, and table styles. This makes referencing these values far easier. I haven’t copied and pasted a color hex value in 2 years, and that’s wildly liberating.

/* SAMPLE OF VARIABLES FROM SQUEAKY CLEAN */
// Site Colors
$green: rgb(102,122,97); //#667a61

// Greys
$black: rgb(0,0,0); //#000000
$darkergrey: lighten($black, 10%);
$darkgrey: lighten($black, 25%); //#404040
$midgrey: lighten($black, 50%); //#808080
$lightgrey: lighten($black, 75%); //#bfbfbf
$lightergrey: lighten($black, 90%); //#e6e6e6
$white: rgb(255,255,255); //#ffffff

// Root
$bodycolor: $white;
$textcolor: $black;
$columnmargin: 10px;
$gutter: 20px;
$warningcolor: red;

Keep in mind when using a boilerplate like Squeaky Clean, these values are all meant to be customized to fit your site. If $midgrey on your site is actually #777777, change it in the _variables.scss file. Make it yours.

Mixins

Mixins are the most powerful part of any CSS preprocessor. Sass can use a mixin library called Compass, which is an amazingly powerful tool. There is a fairly steep learning curve to Compass, and it’s a little much for anything I’ve done, so I took the best parts of it, combined them with mixins I wrote or found, and created a mixins library for me.

What is a mixin? A mixin is a set of CSS attributes that can be added to the selector that the mixin is included in. A mixin looks like this:

/* MIXIN IN LIBRARY */
@mixin css3-calc($property, $operation) {
  #{$property}: -moz-calc(#{$operation});
  #{$property}: -webkit-calc(#{$operation});
  #{$property}: calc(#{$operation});
}

/* MIXIN IN USE */
.content {
  @include css3-calc('width','100% - 200px');
}

/* CSS OUTPUT OF MIXIN */
.content {
  width: -moz-calc('100% - 200px');
  width: -webkit-calc('100% - 200px');
  width: calc('100% - 200px');
}

This mixin takes two values, the attribute you want to calculate(ie ‘width’) and the operation you want to calculate(ie ‘100% – 200px’). This gives you the flexibility to reuse large chunks of CSS without having to memorize syntax or prefixes.

The best part? It doesn’t matter how large your mixin library is (or variable collection, for that matter). They are all removed at compile-time, so they do not impact the size of the final CSS file.

I’m slowly moving more of my code into mixins. Using them is so easy and leaves your Sass clean and maintainable. They also allow you to make large changes to your codebase in seconds. Firefox no longer requires the -moz- prefix for vertical gradients? Just remove it from the mixin and recompile.

My next mixin I’ll include in Squeaky Clean? Probably will be centering a block element:

@mixin center-block() {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Writing mixins is that easy. Using them is even easier. Want more mixins? A quick search on Google for “Sass mixin library” will give you everything you’ll ever need.

Selectors and Specificity

This final section is a difficult one to write, because it’s something that may sound silly to some, but stick with me. I’ll explain it all and you’ll probably want to high-five me before the comments.

I think we’d all agree with this: If you’re not writing reusable CSS, you’re doing it wrong. That’s the point of CSS. You no longer have to put styles on every element on your page. Instead, you write styles for all navigation links, search boxes, or post summaries one time and the styles apply to all of them. A logical extension of this is: don’t use IDs as CSS selectors.

“But Josh,” you say, “I know what objects are going to be unique on my page. Why would I also give them a class?”

When you create an element on a page with an ID, you’re saying you’ll never duplicate that element. That’s a fair assumption. You’re the developer, so you control that. What you cannot assume or control, however, is that the design or content team will never want another element on the page that requires the same styling. If you use IDs, you’ll have to add it to the list of selectors on an attribute set every time you add another element to the page. That’s inefficient and unmaintainable.

/* TOO SPECIFIC */
#article1,
#article2,
#postSummary1 {
  /* STYLES HERE */
}

/* SO MUCH CLEANER */
.story-summary {
  /* STYLES HERE */
}

A great example of my practices can be found in any of the Squeaky Clean stylesheets. All classes with a few nested elements where appropriate. The only time I nest classes is if 95% of styles apply in all cases, and in one case (like :last-child) a certain style needs to be different. This is both readable and maintainable (and dare I say, beautiful). Writing DRY CSS should also be a goal, but start with the other suggestions above and work your way to DRYer code.

A Word to CSS Novices and Their Mentors

I’ve heard speakers at conferences suggest that if you’re a CSS novice, the best way to learn is to just skip CSS and dive into Sass. DON’T DO THAT. Learning Sass but not the underlying CSS is a recipe for disaster, especially if you make liberal use of mixins. If you’re a front-end web developer, you’ll run into situations where you need to edit vanilla CSS almost daily, and all you’ll know is @include clearfix() without understanding the underlying CSS. Learn CSS first. If you want to use CSS on a project now, write a style block in CSS and then convert it to Sass. It will be of great benefit to your career to do so… just ask all the jQuery writers who can’t get jobs as JavaScript developers; they’ll confirm it.

Let me know if you have thoughts, comments, advice, tools you like, etc, in the comments.