Naming Font Sizes in Design Systems

I’ve been wanting to write about how I setup font-sizes in design systems for a while and Dan Mall’s recent article Typography in Design Systems was the kicker I needed. He covers more than just font sizes in his article and overall it’s about a different setup than what I‘m talking about here but I think the issues he describes parallels the difficulties of trying to come up with a good way to implement font sizes into a design system.

One reason font sizes are difficult is you will always (and I mean always!) need to go off script occasionally to maintain the integrity of the design. Take for example a bold font that needs to be 1px larger than the size in the design system because it looks smaller visually than it really is when placed directly above a line or two of text in the normal weight. For this reason the approach to naming and implementing font sizes into a design system should accommodate these variances as part of the system rather than ignore that reality and attempt to force everything into a strict mold.

The backbone of the nomenclature I use is the letter “s” plus a number to notate its place in the scale. (I got this idea from Basscss.)

The system I used in the past would set the main body text font size¹ as the s1 value. Then from that base size, an increase in type scale would be an increase in the suffix number and going down in size would decrease the suffix number with the thought that since the base font size was already on the smaller end you wouldn’t need that many places for decreasing. The whole idea was based on the size of the body text as the pivot point for the entire font-size classification system.

So if s1 = 16, then s2 = 20, s3 = 26 and so forth; and on the other side s0 may equal 14 and then all out of numbers I would use the letter “m” as a modifier for the smallest size, so sm would perhaps equal 12.

Then as variances in sizes were needed — more on this in a minute — I added a -dec1 or -inc1 flag to the main font-size name (e.g. s1-dec1 = 15). I’ve used this in applications and on large websites and found it to be very effective. However, there were a couple problems:

  1. Even though I really liked using s1 as the primary starting point for the type scale and found it very intuitive once you understood it, using s0 as a variable name that isn’t 0 was confusing and not the most scalable naming system.

  2. The -dec1 and -inc1 flags were kind of long and clunky to type, and they tied the increase or decrease to an increment of 1 via the name when that wasn’t always the case.

In summary, it worked fine for me but wasn’t the most scalable solution. The method I use at present is practically the same, just with better naming.

First, instead of -dec1 and -inc1 I use m for minus and p for plus. It’s faster to type and I think somewhat intuitive. And you’re of course not tied to the unit of 1 for your adjustments. For example I have a working project now where the s7 = 68 and s7m = 66.

And second, gone is the confusing “0” suffix. However I have kept the sm unit — I just think it makes a great step down for smaller font sizes — and then start the primary design system scale with s1 and work up from there.

Here’s an example of what this might look like in a design system:

// Font sizes

sm:  13
s1:  16
s2:  18
s3:  21
s4:  26
s5:  36
s6:  42
s7:  48
s8:  68

Then of course you’ll likely have a few additional values in the design that you want to put into the system. Let’s say you also want to be able to access 15px and 17px from time to time, you would add s1m = 15 and s1p = 17. (I’m using unitless values for this example, but obviously you would translate them into the appropriate platform value when the time came e.g. rem(var(--s1))).

I try to group the up or down shifts with contextually what’s most appropriate. s2m = 17 could have also been technically accurate but in my pretend case 17 would be used at times as an alternate to what would have normally been 16 rather than what would have normally been 18. So to keep that front of mind when the values are being referenced I want to tie it to the s1 name.

And then let’s say we also want to be able to use 12 and 14 occasionally and ever so often 24. The final design system type size variables would look like this:

// Font sizes

smm: 12
sm:  13
smp: 14

s1m: 15
s1:  16
s1p: 17

s2:  18
s3:  21

s4m: 24
s4:  26

s5:  36
s6:  42
s7:  48
s8:  68

Now you may say hey that’s kind of weird to just have all the values 12-18 present but when you get into texturing with bolding, uppercase, and more you’ll be surprised at how many font-sizes you’ll need on the smaller end. But it’s important to keep the primary type scale as your backbone and then place your extra adjustments where it makes the most sense.

  1. Most of the time this body text font size was also one of the primary base sizes for the design system type scale.