I’ve heard the term, “font ramp,” at the office, and I always assumed the meaning of it was obvious, from looking at it. But it wasn’t mentioned in my design training, so I didn’t actually know what it meant.
In May 2019, I Googled it, did a deep dive on type scales—and felt an irresistible urge to refactor the CSS on my website to use type scales for everything! What could possibly go wrong with a site-wide CSS refactor? 😅
Getting started with a type scale
I started by creating two variables:
- --type-scale-base, the base font size of my main body copy.
- --scale-multiplier, the number I want to use to scale from one font size to the next.
From there, I added the type-scale variables, generated from combinations of the two variables above.
--type-scale-1: var(--type-scale-base) --type-scale-2: calc(var(--type-scale-1) * var(--scale-multiplier)); --type-scale-3: calc(var(--type-scale-2) * var(--scale-multiplier)); --type-scale-0: calc(var(--type-scale-1) / var(--scale-multiplier)); --type-scale-00: calc(var(--type-scale-0) / var(--scale-multiplier));
And so on. My full range of variables goes from --type-scale-00 to --type-scale-8.
Next, I applied the type scale to everything. No exceptions.
It’s natural to worry that applying a predefined type scale to everything can be too rigid, but I found a few helpful tricks for this along the way.
Experiment with changing the multiplier. When the type scale felt like it was too rigid, I think the real problem was that I chose the wrong multiplier.
Use media queries to change CSS variables. For example, if the font scale feels great on a desktop device, but feels like too many things get too big on mobile, you can use a smaller multiplier on smaller devices.
I ended up going with a multiplier of 1.2 (a “minor third” scale) on mobile devices, and a multiplier of 1.25 (a “major third” scale) on desktop screens.
The type scale alone wasn’t enough, so I added a “spatial scale” to the mix.
One of the biggest mistakes I often see UI/UX designers make with typography is to assign a line-height in CSS according to a “best practice” document they read.
Most of what we read lives in the space between the baseline and the cap-height of each font. You know how a line-height of 200% looks like it has one line of whitespace between each line of text for some fonts, but it looks like it has 1-½ lines of whitespace for other fonts? That’s because different fonts have different cap-heights.
This variability is a hard constraint of working with fonts, so to compensate, I created a set of new variables in my CSS, called spatial scale. To find the spatial scale base, I reduced the line-height on a large heading until the element’s borders got as close as possible to lining up with the baseline and cap-height.
Next, I setup variables like these:
--spatial-scale-base: calc(var(--type-scale-base) * .705); --spatial-scale-1: var(--spatial-scale-base); --spatial-scale-2: calc(var(--spatial-scale-1) * var(--scale-multiplier); --spatial-scale-3: calc(var(--spatial-scale-2) * var(--scale-multiplier))
Similar to the type scale variables above, I built a range from from --spatial-scale-00 to --spatial-scale-8.
I used this spatial scale for almost all line-height, margin, padding, and grid-gutter rules.
Before and after impression
To do your own A/B test, open another tab with this earlier build of this site, and rapidly switch tabs.
The visual differences came out a lot smaller than you might think, from looking at how much code was changed.
In some places, I felt like this exercises validated that my original eye for composition had matured more over the years than I had given myself credit for.
In others, this system held me accountable for the places where I ran out of time or energy and started to just put things in place quickly. And better than that: I had a tool for implementing intentionally proportioned design quickly.
Lessons learned from mistakes along the way
Always start with the base content font size. Most of my design time goes to layouts that don’t have content. Because this started out as a passion project, I started out with defining font sizes and scales for the portfolio page. But when I moved deeper into case studies and blog posts, I found my base font sizes didn’t work for plain text content. Oops.
The first refactor is the hardest, but it gets easier. The first refactor took about a week of spare time. Unfortunately, I noticed mistakes at the end, and had to refactor again. The second and third refactors each took about ⅙ as much time. This was partially because the items I needed to change were fresh on my mind but partially because having a predefined system of sizes nearly eliminated analysis paralysis.
What I like about this approach
I feel like this method brings a greater sense of order and visual consistency to the layout, without making the layout feel too rigid. It feels more organic than something that was laid out on graph paper.
In a lot of other baseline grid systems I’ve seen, like a grid where every font size, margin, padding, and grid gutter is set to a multiple of 4px, I think it’s hard to see a sense of order when some spaces are 40px and the next space is 44px. Setting these measurements as exponential values rather than linear incremental measurements removes extraneous options—increasing the sense of visual order, and limiting analysis paralysis.
Challenges to address next
This process also poses some challenges to designers who only use Sketch. My UI code manages font sizes, line heights, and grid gutters down to fractions of pixels. It’s hard work to make Sketch match that level of fidelity. Communicating that level of fidelity from a non-coder to a coder on a case-by-case basis is excruciating.
That said, let’s talk about how design jobs are designed for a moment.
Because I have the ability to both design and build user interfaces and websites, I know it’s very inefficient to expect designers to toil over pixel-perfect mockups, so that engineers can toil over pixel-perfect replicas of the design in code. Although design tools have helped designers move faster by helping them build rules-based systems directly in the design docs, they still have a long way to go to match the power of CSS itself.
This is a great example of the kind of problems design systems help solve. It also shows why a true design system is made up of deliverables from a cross-functional group of contributors. With a less siloed design process, the product team can spend less time on finicky visual design problems, and spend more time on problems that have deeper consequences for the business and its end users.