Sass (Part 1): Architecture

Sass is great. In comparison to CSS, it’s a sanity saver. All of its abilities are brilliant (actually just most of them, I’m looking at you @extend, why don’t you like playing in media queries?) Anyway, it’s phenomenal at cutting down repetition and it gives us the amazing ability to split our styling up between files without worrying about performance – no more monolithic stylesheets! But, this does bring up the issue of organization. How do we figure out where to put what styles? By page? By Device? What about by how you’re feeling? Nope, nope and nope.

Fortunately there are smart people out there who have already done the groundwork and come up with some pretty fantastic solutions. My personal favorite, and the one our boilerplate project is based on, is the 7-1 idea described in Hugo Giraudel’s Sass Guidelines. When starting with this way of laying Sass out, I looked through the structure but didn’t ‘get’ everything straight away. That was my push for diving into this subject, and now that I’ve run through it and clarified its working parts in my own mind, I thought I’d share!

Before getting sucked in, it’s worth noting that I’m not covering how the various parts of Sass actually work. Dan has already written an article on that so be sure to go check it out if you haven’t already (we could probably call that ‘Sass part 0’ in this series).

First thing’s first: main.scss

The easiest file to understand, this is the ‘1’ from the ‘7-1’ pattern. No styling rules here, only @imports to bring in the rest of the Sass files in the required order. Small note, for the rest of this post I’ll work through everything by requirement order rather than alphabetically, it just makes more sense! Now on to the ‘7’ bit.

The folders

This is our version of 7-1, I guess you could call it 6+1-1? There’s no ‘theme’ folder as in the original, and I’ve added in ‘vendor_extension’ (as mentioned in the Sass guidelines link from above). Now, before any of my colleagues read through the structure below and start wondering what on earth I’m on about, what I’m laying out here isn’t exactly the same as our boilerplate. I’ve put in a few tweaks that are listed at the end of this article, feel free to Disqus!

In @import order:

  • vendor
  • vendor_extension
  • utilities
  • base
  • layout
  • components
  • pages

vendor/ & vendor_extensions/
For all those extra plugins and 3rd party things that get brought in to do their thing. If they come with styling, we put it in the ‘vendor’ folder. If we don’t like their styling, we override it in the ‘vendor_extensions’ folder. This is mainly sugar that gets sprinkled over a site, so lets move on to something more meaningful for our project.

This is for all the Sass that doesn’t result in compiled CSS – at least that’s what I’ve figured out for the definition. This may be a little arbitrary, Disqus? They are the bits of styling that get used repeatedly throughout our components: variables, clearfixing, mediaqueries, etc. First up here are the variables. They’re pretty important, so they get their own file which will be called in _main.scss first as they are usually referred to by almost every other .scss file. We call their home _settings.scss, which I’ll come back to later (in part 2) as there are a few interesting things going on in that file.

I’ve also added in our _fonts.scss file to this folder. It imports webfonts for us and defines the sources for font-families, something that feels more like a set of variables to me, which is why I’m suggesting we (possibly) move it here.

_mixins.scss comes next. I’ve been in two minds about splitting out mixins to their own individual files, but the majority are small enough that having them listed out in this single file is manageable. The exception would be animations, if you’re going down the mixin route to build them. Again, I’ll explain this thought process further in part 2.

The ‘utilities’ folder might also be the place to put in @extend’ed Sass, but I’m leaving them out. There’s a few reasons for that but I’ll not go into it (yet). If you’re interested, there’s plenty on the subject that Google will throw up!

Now we start getting to styles that will be affecting the site. Here we get everything set up to the baseline (hence the name). Use whichever CSS (or Scss) reset you prefer – we use normalize – and set up the basic typography. If a design comes with a style guide, here’s where it goes! We also have a scaffolding file in here. Again, I’ll come back to this later as it contains some interesting tricks.

At this point, if you loaded the site, all the HTML elements would be styled and ready to start building into components. But we’ve got one last step before the component fun begins.

This is where the big stuff goes, your site’s wire-frame. Think of it as the place to define the containers that will eventually be filled up with all our wonderful components. Speaking of which, we’re there at last!

This is where the bulk of the Sass development happens. Keep every component in its own file and check out the BEM naming convention if you haven’t already. A super simple and really great convention.

The final folder. This is for any left over page specific styling that may not have been taken care of by any component modifiers or layout work.

That’s it! The Sass guidelines example has a ‘theme/’ folder which you can add in for obvious reasons. We don’t often have a project with that requirement, so for the boilerplate it’s not included.

SCSS directory structure

So, taking the folders described above, I’ve laid out the boilerplate’s structure in order of execution with a few (hopefully) helpful reminders about what they are for:

  • (explain all this, maybe with bits from this article in it!)
  • main.scss – No rules, just organize imports
  • main-oldie.scss – styles for older versions of IE
  • aboveTheFold.scss – (optional) for first load styles, this is just an idea that popped up while writing
  • print.scss – And then any other environment specific sheets
  • /vendorfor the actual vendor files that we don’t edit
  • /vendor_extensionsoverrides to vendor styles go in here
  • /utilitiesfunction variables – sass that doesn’t output any actual css
    • _settings.scss – All the variables
    • _fonts – @font-face imports
    • _mixins.scss – Commonly modified styles and behaviors
    • _helpers.scss – Helpful & common behaviors: clearfix, pull, keyframe vendor prefixing (although prefixing might be handled with another tool), etc
    • /animations
      • _animation.scss – One file for every set of animation keyframes
  • /base
    • _normalize.scss – Or which ever variation you prefer
    • _typography.scss – Built from the style guide if provided, use for text and tag styling
    • _scaffolding.scss
  • /layoutMajor/Macro layout – the big stuff – site wire-frame
    • _grid.scss
    • _sidebar.scss
    • _main.scss
    • _header.scss
    • _footer.scss
    • _nav-primary.scss
    • _nav-sidebar.scss
    • _nav-footer.scss
  • /componentsMinor/Micro layouts – elements throughout the site in any location
    • _buttons.scss
    • _forms.scss
    • _messages.scss
    • _responsiveTable.scss : just an idea
    • _calloutSidebar.scss
    • _calloutBody.scss
    • _searchSimple.scss
    • _searchAdvanced.scss
    • _postPreview.scss
  • /pagesfor page specific styles
    • _contact.scss
    • _About.scss

In conclusion

As I mentioned earlier, the structure I’ve laid out here differs slightly from our in-house boilerplate. Not by much, but enough to hopefully inspire a wee discussion. In any case, whether you choose this flavour of 7-1, the current Delphic one, or some other completely different structure – I’d bet that architecting your Sass is going to be one of the single best things you could possibly do to improve any styling workflow! Of course, there are a lot more small things you can do to improve it too, that’s the subject of part 2 which should be up soon if it isn’t already!

Finally, in review of all that structure talk again, this is what our main.scss file would look like if everything stood up to inquiry and you decided to go with the architecture I’ve described:

@import "vendor/**/*"
@import "vendor_extensions/**/*"

@import "utilities/settings";
@import "utilities/fonts";
@import "utilities/mixins";
@import "utilities/helpers";
@import "utilities/animations/**/*";

@import "base/normalize";
@import "base/typography";
@import "base/scaffolding";

@import "layout/**/*";

@import "components/**/*";

@import "pages/**/*";

« Prev Article
Next Article »