How I improved my workflow with SMACSS & Sass
Update: 27-02-2017 I wrote an extensive new article about Structuring Front-end Components.
A couple of months ago I passed by Jonathan Snook's SMACSS website while browsing the web. After reading the SMACSS core articles I felt a bit awkward about how I organised and crafted my CSS. My CSS was quite unorganised and the only pattern used was the waterfall pattern; Work your way from the header all the way to the footer. The CSS also contained fixed withs, overuse of ID selectors & many specificity workarounds. It was not organised, not modular & most of all: Not reusable.
Meet SMACSS permalink
SMACSS stands for Scalable and Modular Architecture for CSS, and is more a style guide than a CSS framework. On a high level SMACSS aims at changing the way we are turning designs into code. Instead of working in a page mentality where you try to turn a single page design into code, SMACSS aims to identify repeating visual patterns. Those patterns are then supposed to be coded into flexible/re-usable modules, wich should be independent as possible from the individual page context. This is not a revolutionary point-of-view for a programmer, but in the web design world this is indeed a newer way of thinking.
The basic concept of SMACSS is to devide styles into 5 categories: base, layout, modules, states and theme*. Each category comes with a set of usage rules and naming conventions. The main reason of this categorization is that rulesets should only ever inherit and add to previous ones, never undo.
Any declarations like these
...are typically bad news. If you have to remove borders, you probably applied them to early.
This is where all the base styles live; resets, element defaults, default font sizes, etc. This category is mainly dominated by element selectors. You should always ask yourself if a ruleset must live in base in order to not lose flexibility down the road.
In this section you specify all types of layout containers, such as header, footer, content, sidebar, etc. The layout elements haven't got any styles applied to them, they only divide the website into sections. This is the layer where grid systems etc, would be living.
The bulk of your css is made up of independent modules and submodules. Every module should be completely independent of its context and should work within any layout container or other module.
If a specific context requires changes to a module you rather create a submodule that describes the context instead changing styles based on the parent.
Modules can be in different types of states: class-based-states(.is-active), pseudo-classes(:hover, :focus), attribute states(data-state="rotating"), or @mediaquery states. These states belong directly to the modules but have a different categorybecause the have their own naming convention and usage rules.
SMACSS points to an optional fifth category, theme, but this is only applicable to pages that require theming. Theme styles override or extend the modules, and only apply colors and backgrounds.
Syntactically Awesome StyleSheets(Sass) permalink
SMACSS works especially well with Sass, and I'll try to explain why and how I implemented Sass into my workflow:
File structure permalink
In Sass you can easily chop your stylesheet into partials by using the @import rule. This allows us to easily organize and maintain our files similar like this:
Partial setup permalink
Every partial stands for a standalone module wich has its own sectioning:
- module, the base module rulesets
- state, the different states the module can be in
- theme, optional but recommended to separate style from structure
Since the module has its own module, state, theme sections it can be easily copied to another project while the characteristics stay the same.
I'm using a namespacing that is based off the BEM front-end naming methodology wich stands for: Block, Element, Modifier. The naming convention follows the following pattern:
.blockrepresents the high level element of the module
.block__elementrepresents a descendent of .block
.block--modifierrepresents a different version of .block
The point of BEM is to tell other developers more about what a piece of markup is doing from its name alone.
Within the SMACSS guidelines we prefix the classes with a section based prefix. A module should always be prefixed with .m-: e.g. .m-search, .m-contentbox. Elements that live inside a module have classnames like this: .m-search__heading. A brief example of a module:
border: 1px solid #ccc;
A submodule is specified like this:
border-bottom: 1px solid #f00;
A module that lives in the layout section gets the prefix of: .l-.
When you are using BEM, though, it is important to remember that you don’t need to use it for everything. Take for example:
This CSS would never fall into any BEM category, it’s merely a standalone rule.
Using Sass @extend permalink
Sass @extend is a very powerful tool to DRY out you stylesheets, but must not be overused. Since we want modules to be portable you must only extend within a modules scope, a module must not be tied to other modules to work.
SMACSS is a very user-friendly approach to modular CSS. It asks for nothing less than a complete shift from a "page mentality" towards web design, to a search and codification of visual patterns. For that it offers a sensible categorization and naming scheme. It goes along very well with SASS, especially using the @extend feature and when it comes to themeing. It's kind of an open question how SASS's nesting capabilities fit with SMACSS, but in general I think it can bring lots of very valuable and badly needed modularity and conventions to the web design community.