This article is part of a series on design systems inspired by our library of web components. The library relies on a solid system of CSS globals. So this is us sharing the things we’ve learned setting the global style of our library! ✌

Article Series:

- Part 1: Typography

- Part 2: Grid & Layout

- Part 3: Colors

- Part 4: Spacing

- Part 5: Icons

- Part 6: Buttons

🔥 📢 We’ve launched the Typography Editor! A visual tool to set the typography of your web project based on the CodyHouse Framework. You can use it for font pairing, to generate the type scale and set responsive rules.

For those of you who prefer to skip the article entirely and take a look at the final CSS file, you can check it out here.

Setting the Typography system using CSS Variables

Designing a typography system means making decisions about:

The typeface (font-family) you want to use. Type (modular) scale. Responsiveness of the text (size unit and breakpoints). Spacing and vertical rhythm. Colors (theming).

Let’s start with point one and two. Picking the right typeface is probably one of the first steps when you create a design system. Let’s assume you’ve browsed hundreds of font families and found the one you love (for now!); in your global/_typography.scss file, you can set your font-families as variables.

The primary font, in this case, is the “most used” font; or the body font. The secondary font can be applied, for example, to a heading element. This approach is arbitrary, of course.

Along with the typeface, we’ve defined two variables: the — text-base-size and the — text-scale-ratio. The value of the text base size is 1em, while the — text-scale-ratio is used to generate the type scale.

When applied to the <body> (we’re assuming no font-size is applied to the <html> element), 1em equals to 16px in most modern browsers. Since our framework is mobile-first, we’re saying: on small devices, I want the body text size to be ~16px (the font-size of the body is equal to the — text-base-size).

And yes, after a long debate, we’ve opted for the em unit. The reasons behind this choice are explained later, in the Spacing section of the article.

The modular scale is a set of values obtained from a base value (in our case, 1em) and a ratio, or multiplier ( — text-scale-ratio). You can apply the scale to any measurable element (margin, paddings, etc.). Here’s how you create a type scale taking advantage of the CSS calc() function*:

*We could have simplified the code by replacing the parts where we repeat — text-scale-ratio with variables (e.g., — text-lg: calc(1em * var( — text-md));), but we had issues with how the postcss-css-variables gulp plugin compiles nested calc() function and CSS Variables.

The reason why a modular scale is useful when applied to anything in a design system is that it generates a harmonious set of values, as opposed to setting each value independently (maybe obtaining them from a .sketch file).

Note that in defining each text size variable we multiply 1em by the — text-scale-ratio. That 1em is not the —text-base-size value. You could set a — text-base-size different from 1em (while you shouldn’t change the 1m in the calc() function).

Since the em unit is a relative unit equal to the current font size, if we update the — text-base-size variable at a specific media query, we update the font-size of the body, and, as a result, all the text size variables. The whole typography is affected.

The paragraph element inherits the base font size, while we set a specific font size for each heading element. Besides, we create some utility classes in case, for example, we want to apply the — text-xxl font size to an element that is not an <h1>.

Why including the type scale in your CSS? In one word: control.

Say we want to increase the body font size at a specific media query; for example, we increase the — text-base-size to 1.25em past 1024px. The heading elements are all affected by the change (the 1em in the calc() function is no longer ~16px, but ~20px), therefore they all become bigger. Let’s suppose we feel like increasing the size of the <h1> element even more. How do we do that?

One option would be increasing the — text-base-size value, but it’s not ideal. The body text is big enough, I just want to target the <h1>. Here’s the advantage of storing the — text-scale-ratio in a variable. We can edit it and affect everything but the body text:

With this technique, you can manage the size of all your text elements by editing only two variables. Not just that, you can take advantage of the em unit and modify all margins, paddings, and spacing in general by editing the — text-base-size at a root level.

This method is not just a time-saver IMO, it’s a powerful approach to making text responsive. Both designers and developers can benefit from it. All we need is setting a demo-typography.html file with some text elements plus some components. The designer can jump in and tweak the typography directly in coding.