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...

Isaac Pinnock   ·   29 May 2015

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...

Alex Barlow   ·   12 May 2015

Design

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...

Veronika Janeckova   ·   11 May 2015