How we do CSS at Made by Many
This write-up aims to summarise our thinking about how to write CSS. It’s grown out of lots of conversations around best practices seen elsewhere, and ultimately what seems right for the kinds of work we do most.
It’s stemmed from my attempt to update a two-year-old guide of ours titled ‘CSS at MxM’. It’s frankly surprising how much things have moved on since that was written. Here’s where we are now.
I should preface that the techniques outlined here are heavily underpinned by our use of Sass. Though that’s not to say they don’t apply for writing standard CSS too.
Structure
We’ve come up with a twist on SMACSS that provides an excellent foundation for modular, reusable CSS. This consists of the three key parts: Base, Patterns and Modules.
To start, here’s how our code is laid out:
Base
All of our defaults, variables, helpers and typography.
Defaults
Resets, global styling, anything like that.
Helpers
Define Sass functions and smaller, more dynamic mixins here.
Typography
Where @font-face declarations live.
Variables
Generally speaking all of our variables are kept in one place. Namespacing helps to describe the purpose of a variable.
Or even maps:
Patterns
Patterns are styles shared across any number of modules. Patterns are always declared as mixins in Sass.
This makes consistency really easy, and provides a great way to modify styles on a module-by-module basis.
A pattern is only a pattern when it’s used multiple times, otherwise it’s a module.
Modules
These form the main part of our CSS. Modules describe specific components; they’re not reused or repurposed because that’s what patterns are for. This helps enormously in keeping track of legacy and makes semantic naming much easier.
In practice
We use BEM for writing our CSS. It really works when things start small and grow over time and is the best way to combat lack of scope in CSS.
We’ve always struggled with the difference between modifiers and state. In the end it comes down to semantics. The rule we go by is that if it’s toggled (i.e. by JavaScript), then it’s state. This then prevents selectors leaking into JavaScript.
Nested elements
It seems natural to name your elements based on their hierarchy in the markup, but we’ve found that makes naming more complicated than it has to be.
We generally avoid deeply nested elements and tend to split complex modules into smaller namespaced ones.
In an ideal world modules are well defined and specific enough not to require namespacing.
For more on BEM see:
Top-level modifiers
We have a convention around how top-level modifiers are applied to elements of a module.
This way all styling concerning a particular element is kept in one place.
JavaScript hooks
Any element referenced in JavaScript should be prefixed with js- so that JavaScript remains decoupled from CSS.
Tools
We’re mostly working with Rails and sometimes Node at the moment. These are some of the tools we’ve been using.
CSS Patterns
CSS patterns is our attempt to abstract common patterns throughout our projects. This includes some of the best bits from HTML5 Boilerplate.
Each pattern is consistent with our definition of patterns above. You can find the documentation at http://madebymany.github.io/css-patterns
Autoprefixer
For a long time we had been using Bourbon to handle vendor prefixes, but recently switched to using Autoprefixer because of its transparency.
Autoprefixer is just one of many brilliant PostCSS plugins.
In closing
Establishing these kinds of guiding principles has helped enormously in terms of maintainability. As roles chop and change, we’ve all found it much easier to get onboard with unfamiliar projects and keep things consistent going forward.
We’ve successfully scaled this approach for big sites like ITV.com and Composed.com, both of which worked out excellently. We’re always looking to improve and optimise, so any feedback is greatly appreciated.
In summary of everything covered here, here is a small reference project to test stuff out:
http://github.com/madebymany/css-guide-example
Some further reading
Continue reading
David Cameron is committing crimes against typography
Number 10 is now on Slideshare. That’s right, the slide hosting service loved by professionals and thought leaders around the world has been joined by the...
Replacing Rails: Part 3 - Go and deploy!
One of the sweeter things in go is most definitely deployment! Gone are the annoyances of setting up a server with the right version of Ruby (probably hav...
The 20 things you should know when designing for classrooms
Download the accompanying report at the end of this post to discover more about co-designing education services with teachers.Collaboratively designing wi...