If you’re like a lot of developers out there, you start your projects off with the best of intentions. No developer ever says, “I am going to make this project a fucking mess, a cluster-fuck of spaghetti code that even I’ll struggle to read in 2 weeks, let alone any other developer”
We’re living in the golden-age of front-end development. We have tools, we have awesome methodologies like BEM and CSS pre-processors like Sass. And for all that automation without a proper structure, our CSS always ends up being unorganised and messy.
I’ve done seen a lot of roaches and bitches, but the dog keep going the distance
Use The Structure, Luke
There are a lot of different ideas out there for structuring your Sass. Each has its own advantage and disadvantage, one thing is for certain though: folders are awesome and you should use them.
It can be hard breaking out of that old-css mindset when using Sass. You often see developers throwing a whole bunch of their Sass files into the one folder, maybe one sub-folder if you’re lucky.
My Structure
This is the money shot. This is the structure that I use on all projects I touch and it works well. It’s modular so it prevents conflicts, it means many developers can work on different aspects and not cause conflicts when committing your files (conflicts are annoying).
Stylesheets/ homepage.scss # Imports the _homepage.scss file from pages/ (if you want separate stylesheets for different pages) style.scss # The primary global stylesheet you include everywhere on your site -- base/ _functions.scss # Custom user mixins/functions _variables.scss # Variable values _base.scss # This includes the files above in one handy file, also could include Compass or Bourbon here. All standalone files should import this base file for access to variables/functions, etc. -- components/ _buttons.scss # Button styles _classes.scss # Generic CSS classes _forms.scss # Form styles _grids.scss # Grid system _responsive.scss # Our media queries file _tables.scss # Table styles _typography.scss # Type styles _components.scss # This file includes all of the components via imports (except the _responsive file, this is included separately) -- pages/ _global.scss # Global page styles _homepage.scss # Homepage styles _contact.scss # Contact page styles -- vendor/ _bootstrap.scss _jquery.ui.scss _vendor.scss # This includes all previous vendor files, so we don't have to include one by one
Take me to your style.scss
Inside of your main stylesheet which we called style.scss, it will look something like below. The goal with the main style.scss stylesheet is that it will become a global styles file of sorts. You include this and it gets loaded on each page.
// Import Compass
@import "compass";
// Base styles
@import "base/base";
// Import our components file minus the responsive include
@import "components/components";
// Vendor styles
@import "vendor/vendor";
// If you were to include page styling for all pages include it here in the middle
// Keep in mind this is a global file and to prevent bloat, you should break CSS
// files where possible into separate includes to prevent pages loading unneeded CSS
// Include our media queries file at the bottom
@import "components/responsive";
Huh?
What the above does is it generates a definitive global stylesheet called style.scss — it gets included on every page and features base styles. For specific pages like the homepage, we incur an additional request (if browser cache isn’t primed) but only include CSS on pages that need it.
I have a separate stylesheet for each page if there are going to be lots of changes and additions only relative to that page. If not, then you put your global page styles into the _global.scss file in the pages folder. Simple.
For each additional separate page stylesheet we need to make sure we include the base/_base.scss by adding: @import “base/base”; to the top of the file. This gives us all variables, functions and other nice Sassy stuff we might want to use.
Sass Pitfalls
Nesting
All CSS pre-processors allow their users to fall into this trap: nesting hell. This is where you nest styles inside one another, while it might look neat and manageable on your side, the generated CSS looks like this:
.selector > .someotherselector table > tr > td
Doesn’t that make you want to gouge your eyes out? As a general rule of thumb, limit any nesting to 3 levels. Try using BEM for your CSS to prevent nesting altogether.
Duplicating Compass or Bourbon Functionality
Heck, even I’ve done this before (too many times to count). Be mindful of whether or not that mixin you are writing already exists if you’re using Compass or Bourbon (chances are it does). You’d be surprised what they cover (all CSS3 properties/prefixes, colour manipulation and more).
Inline Media Queries
A cool feature in Sass is being able to nest media queries inside of a selector which will output a media query with the style change for the specified breakpoint.
In this post, arguments for inline media queries are pretty convincing. It’s not so much a pitfall, but rather something you need to be aware of. Inline media queries will mean duplicates (unless you use a Grunt or Gulp task to combine them).
That is pretty much it. The approach has flaws like being too modular and forgetting to include a file or getting caught in dependency hell where one file relies upon another file being include first before it will work properly, but managing things properly from the start avoids this.