We’ve gone over how we tackle colors and typography in our design systems at The Scenery, so now we turn our attention to the system that goes largely unnoticed (because it’s not really there): spacing.
Before we begin, it’s best to define what a spacing system should do. At its most basic level, a spacing system should define the distance between elements and components. And it should always be a full system itself—trying to couple spacing to type or nesting it inside components is a recipe for disaster and developer overwrites.
As far as goals go, your spacing system should be…
- Easily defined and applied to designs
- Understood by designers and developers alike
- Able to change without breaking
To define a spacing system that achieves these, we started with a core question, “What should spacing really be based on?”
All Your Base Are Belong to Us
There are a myriad of ways to define your spacing system’s core units of measurement, but which one is really the best? To find out, let’s explore some of the popular options we’ve used in the past (in order of when we thought they were the bees-knees).
Old faithful. Base-10 is prevalent for two main reasons. One, it is the number of fingers and toes most people have. Two, it is easy to use. Aside from that there’s little reason to use base-10 spacing other than our sense of nostalgia (and the fact that in Sketch the default big-nudge is 10px).
Verdict: Arbitrary at best, but math is easy!
Now we’re talking. Ems make great spacers because they’re an abstraction based on the font size. They’re also terrible because they’re an abstraction based on the font size. Designers and developers both love ems because of their ease of use and flexibility, but they fail in one core area: they’re variable.
In one of our biggest systems to date, we started our spacing system with the caveat that space could be defined absolutely with pixels or with ems, based on context.
Here’s what happened: designers couldn’t understand how the ems were used, do the math in their heads to translate ems to px, and then use those values consistently in their design flats. It was a nightmare, so we pulled the em-based spacers and moved to absolute ones that could be symbolized in Sketch, shared, and implemented without fail.
What we learned is that a variable spacing system is nice in theory but an absolute pain when applied at scale across a large team (and product).
Verdict: Great idea, but the designers will stage a coup.
Tired of base-10? Try 8! It’s like 10, but more divisible. Base-8 is actually far more useful than base-10 as far as systems go. It provides great options for scaling up that are largely divisible by 2, 3, and 4, and matches up with base font-sizes. It’s also a highly used scale when it comes to core UI elements like iconography.
If you’re going to choose a simple mathematical value-based spacer system, this is the best one so far. It’s quickly becoming industry standard, thanks primarily to its use in Material Design. But something about it still seemed really arbitrary to us, so we kept thinking.
Verdict: Better than anything else so far.
Just Not Our Type
Not ones to settle —we have authority issues as a whole —we decided to take a step back and think about what concept should define the space around our system’s components. Then we realized we could base it on the stuff that makes up 98% of our system: our system’s type.
ex-unit is a hardly-used CSS unit tied to the very thing we want spacing to relate to: typography. And not just type, the x-height of type, which varies wildly from typeface to typeface, even when the base font size remains the same. Using this unit, we are able to spec spacing components that relate directly to the fonts in our UI, creating a harmonious design that uses classical design theory —not an arbitrary number.
Even more beneficial is the fact that the unit is wildly flexible. Now, when you go to change your system’s core body copy from Brandon to Avenir you won’t have to rework your whole spacing system because everything feels gigantic. The unit is built to mitigate the pain of change across your system, and that is something we can get behind for any part of our system.
Verdict: related to our core type while being super flexible to work with. Winner.
Now that we’ve found a base that achieves our goals, we need to tackle the next aspect of spacing: the sizes themselves.
Generating Spacing Sizes
Spacing sizes are just like any other design system component —too many variations and they will be used inconsistently, too few and your system will become fragile, breaking under the stress of scale. The goal for us in defining spacing sizes is to define them in a way that strikes a balance between those two extremes.
To do this we created a philosophy: each spacer size should be meaningfully different than the ones bracketing it.
What is a meaningful space? This probably sounds like an ontological question. We might as well be asking what the meaning of life is, as well as our various spacer sizes. But surprisingly, we found our solution to defining what a meaningful difference really is in a place we have consistently derided as both pretentious and self-gratifying. We use a Fibonacci sequence.
Everyone has seen Dribbble posts where a designer has magnificently aligned their vector shapes to the golden rule in the name of classical design-theory and virtue. This is not that.
The Fibonacci sequence does one thing very well: it differentiates steps so they are at least as far away as the step preceding them. In short, it enforces meaningful change between steps. If you were going to use this sequence for anything that aligns to its core principle, applying it to spacing would be it.
When we take our ex units and apply a Fibonacci sequence we get something beautiful in its simplicity, but powerful in its relation to the rest of our design system.
This system is fantastic for the same three reasons we stated at the beginning:
- It is easily defined, and applied to designs (thanks, Fibonacci and Sketch symbols)
- It can be understood by designers and developers alike (thanks, absolute sizes)
- It can change without breaking (thanks, ex unit)
Naming Your Sizes
Since the exact pixel value of the spacer can change, we use abstractions for our spacing names. These could either be a numeric scale (sp-1, sp-2, sp-3, etc) or t-shirt sizes (xs, s, m, l, xl, etc). This allows our spacing system to flex on specific sizing of each step, while maintaining the integrity of the codebase.
We opt for the t-shirt sizes in our systems. They help relate the general size of the space while still giving developers and designers a clear delineated path through the sizes of the system. And since the sequence isn’t open to half-measures we don’t have to worry about someone trying to insert the dreaded “smedium” size into the system at some point.
With this core process powering your system spacing, you’ll be set up for the future with a core that changes gracefully, relates perfectly to your designs, and isn’t just based on your own two hands.