Scaleability — like the Romans knew how

Building Scaleable CSS

Peter Mouland
5 min readJul 7, 2017

--

I have been working to help create styles that are to be used across multiple projects and teams; a Style-guide that should live long and be easy to maintain. This project is built up of a number of separate components, some CSS only.

When thinking about building components, even the CSS ones, I often think back to a great article by Nicolás Bevacqua about how to write Front-End Modules. This approach from the start has meant I have less coding now, which leads to less maintenance in the future. This approach is both flexible and brilliant 🤓

Starting a style-guide brought up the classic CSS debates within the team. This is where the point of this article comes in:

  • Setting a goal
  • BEM vs SMACSS. The winner is sub-classes.
  • is extends really bad?
  • Whats wrong with Mixins?

Too much already? Read the tl;dr at the end of the article

Setting A Goal

Creating CSS that tries to solve every possible outcome in advance will created bloated styles. Refactoring CSS once it is live can be difficult. The easiest code to look after is the code you haven’t written. With this in mind, we set out to:

  • Keep it simple — So it easy to maintain
  • Keep it flexible — Help solve future requirements
  • Keep it small — Performance matters.

Sub-classes

While the BEM vs SMACCS debate can be engaging, both methods solve real problems, so lets move past this distraction onto something important. Sub-classing.

Say you have a <button>, which has 5 colours (primary, secondary, disabled, warning and error). Without sub-classing, 5 class names would be created; with sub-classing there will be 6. Although more classes are created with sub-classes, they are more modular which is perfect for making CSS flexible.

/* Without sub-classes */
my-button-primary { ... }
my-button-secondary { ... }
my-button-disabled { ... }
my-button-warning { ... }
my-button-error { ... }

/* With sub-classes.
* Double or single dash. the choice is yours!
*/
my-button { ... }
my-button--primary { ... }
my-button--secondary { ... }
my-button--disabled { ... }
my-button--warning { ... }
my-button--error { ... }

Theming with sub-classes

Creating ‘experimental’ or ‘promotional’ pages often happens, which mean small button but important tweaks to the styles. Without sub-classes, the 2 codebases would be bound tightly together.

/* Modification when not using sub-classes */
.my-theme {
.my-button-primary,
.my-button-secondary,
.my-button-disabled,
.my-button-warning,
.my-button-error {
/* example change to apply to all buttons */
padding: 10px;
}
}

With sub-classes, only one override is required.

/* Modification when using sub-classes */
.my-theme .my-button {
/* example change to apply to all buttons */
padding: 10px;
}

To Extend or not to Extend

I have read around the subject on a few occasions and for me, when talking about reusable CSS, it always comes down to a couple points.

  • Extends creates more CSS than reusing a class name.
  • Extending can cause unknown side-effects

Creating CSS that will be distributed among many applications means that the CSS needs to be as small and unobtrusive as possible. #perfmatters. The size of the selector string extends creates can be mind-boggling.

CSS is not thought of as public and private which means the programmer wont always know the knock-on effects if they decide to make changes to a class which is ‘extended’.

For small projects, that don’t change often, and have CSS-authors that understand the dangers (or how other could accidentally mis-use them) then ‘extends’ may work.

However, we are talking about building a toolkit; something to be used by multiple teams which must require no cognitive effort to maintain. Because of this, we must leave mixins out of it.

What’s Wrong With Mixins

I am a fan of clever code. I love taking a look at CodePen.io and seeing what awesome tricks people have come up with. But, CSS can be time consuming to test. If you are creating a mixin which loops round an array of variables to create a number of class names, then you are probably creating more CSS than may be necessary.

Looping though variables to create 5 tooltip classes can generate the following:

.my-tooltip--primary { background:$primary; color:$white; }
.my-tooltip--secondary { background:$secondary; color:$white; }
.my-tooltip--inactive { background:$inactive; color:$white; }
.my-tooltip--warning { background:$warning; color:$black; }
.my-tooltip--error { background:$error; color:$black;}

What happens if those colours are needed for a second component, or a third? Creating a new mixin for each component isn’t going to keep our code simple. Tying in array variables into multiple components wont help us maintain and update colours in the future. Being able to find every use of the $primary colour is actually very reassuring. This falls down if you also have to remember “oh yeah, the $colours array”. Keeping my life simple now, also means the code is easier to maintain in the future.

If we were to use utils classes, we could still use the $colours array, but they can live with the `_colour.scss` file so the link is clear.

.state--bg-primary { background:$blue; color:$white; }
.state--bg-secondary { background:$red; color:$white; }
.state--bg-inactive { background:$green; color:$white; }
.state--bg-warning { background:$yellow; color:$black; }
.state--bg-error { background:$apricot; color:$black;}

These state classes can now be used for many components. Not only that, they can be used in other apps for components which are not covered by the style-guide. flexible!

flexible!

TL;DR

CSS has always been able to combine class names. It is a major strength that we sometimes forget. Utilising this to your advantage will mean much simpler and smaller CSS.

Create classes that have a small purpose and re-use. There is nothing wrong with the following HTML. Your CSS will be forever young and beautiful because of it!

<div class="my-module state--bg-primary clearfix">

How to achieve our goal:

  • Keep it simple — keep cognitive effort low and don’t promote potentially dangerous methods; i.e. Dont use extends
  • Keep it flexible — Use sub-classes
  • Keep it small — Don’t mixins that could generate wasted CSS

--

--