Blog

I Googled “font ramp,” and it opened my eyes to so much more

What I found made me “work smarter, not harder” with little details that make a big difference.
An example of a font ramp: The same words in font sizes that gradually become larger.

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:

  1. --type-scale-base, the base font size of my main body copy.
  2. --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.

null

Same layout, different scale multiplier. Trying out different multipliers helped me see multiple options quickly. With a higher multiplier, big fonts are comparatively bigger; with a lower multiplier, big fonts are still bigger, but less big. Above left: 1.333x, or a “perfect fourth” scale. Above right: 1.2x, or a “minor third” scale. Below: 1.25x, or a “major third” scale. The “major third” scale felt “just right” for desktop form factors.

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.

null

Here’s what the cap height looks like for Poppins. I adjusted the line-height of a heading until its bounding box was as close to lined up with the cap height as possible.

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.

null

Before and after: The page title, where I had been very deliberate in my first pass about sizes and spatial relationships. I intentionally had equal whitespace above and below the page title the first time, but having spatial scale variables helped me try out other precisely calculated proportional relationships quickly.

null

After: Here, the spatial scale is overlaid on top of the layout. You can see the whitespace between the logo and the section title is equal to the cap-height of the section title. The whitespace between the section title and the content is equal to the height of the logo. The logo itself is set to a height from the spatial scale, which means the logo’s height is connected to the base font size.

null

Before and after: CMS content. Before, I had set all margins in em units, which meant whitespace between each block changed with the font size. Spatial scale variables made it painless to set one margin size derived from the base font size. If the font size changes at a later date, the margins automatically change proportionally.

null

Before and after: Portfolio case study heading. Before, I had made guesses about line height for the large text, and whitespace between elements. Using variables derived from the base font size helped me iterate with confidence as I adjusted what size the pieces were and how they fit together.

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.