So you want to create a design system, pt. 3: Typography
So you want to create a design system, pt. 3: Typography

Long gone are the days when apps could only use a single system font, bold and italic at most, and that was it. Typography is now a significant part of product identity, but how do you apply it systematically?

As with colors, the most important thing is to avoid hardcoding type-specific values in the design tool and in the code. This means that you need to define a set of text styles and use them consistently wherever text appears in your UI.

Both major mobile platforms provide default text styles for different situations such as headings, subheadings, paragraphs, captions, or labels. However, these styles don't match across platforms, and it's also likely that your product needs won't fit neatly into these preset categories. In that case, rather than combining built-in and custom styles, it's easier to define your own styles for everything and ignore the built-in ones.

Elements of style

So what does the text style contain? To be on the safe side and avoid surprises caused by built-in components and their default values, you should always define at least the following properties:

  • Typeface: The font family you want to use. If appropriate on the platform, it is a good idea to specify a generic (or fall-back) font family too, such as serif, sans-serif, monospace, etc.
  • Weight: Modern font families have a much wider range of weights than just regular and bold, not to mention variable fonts. The weight is usually expressed as a number or a name. Here is a table of the most common values: Table of font weights
  • Style: Normal or italics, that's more or less it.
  • Width: The width of each letter. Font families with variable widths are not quite common. Examples include: Table of font widths
  • Case: Uppercase, lowercase, or small caps.
  • Text decoration: Overline, underline, or strikethrough text.
  • Size: The height of the characters. This is where it starts to get tricky, see implementation details in the next section.
  • Letter spacing (tracking): The space between the characters. Zero is the default value specified in the font family, but it is often advisable to use a slightly higher positive value to improve readability (especially for paragraph styles with smaller text size), or a slightly negative value to better visually balance large headings.
  • Line height: Vertical space between text lines, measured from baseline to baseline. Baseline is the invisible line on which each character sits, not including downstrokes (like in lowercase letters p or g).
    As with letter spacing, each font family has a default value that may be adjusted for readability.
  • Paragraph spacing: Vertical space between paragraphs.
  • Paragraph alignment: Left, right, center, or block. Be careful with block alignment, as the legibility and visual quality of the resulting typesetting depends a lot on the quality of the algorithm used (which usually cannot be changed), including hyphenation algorithms for different languages.
  • Text direction: If your application supports languages that are written from right to left, you often need to adjust layouts as well, and consistently use layout terms that are independent of text direction, such as start and end instead of left and right.
  • Color: Should color be directly part of the text style specification? A slightly tricky question, both options have their pros and cons. However, specifying a default color probably won't do any harm, so I’d generally recommend including color in text style specification.

Practical type system

So what text styles does a typical application need?

First of all, it is a good idea to distinguish between text styles for a text that stands on its own, as “top-level” content (headings, paragraphs, labels, captions, notes, etc.), and text styles for components that happen to contain text (buttons, menus, toolbars, input fields, tabs, etc.).

Some very well-known design systems don't distinguish between those usages (or, on the contrary, mix those together), but this is unfortunate—it often happens that in such systems a change of paragraph style unintentionally results in a change of the text style in some component like button or input field, which is something you usually don't want.

Content text styles

As with colors, it's a good idea to hide content text styles behind semantic names. The choice is completely yours, but usually, you will need at least several levels of headings and subheadings, one or two styles for regular text in paragraphs, accompanying styles such as captions or notes, and maybe even some styles for things like list items, etc.

If your app's domain is so specific that it's worth creating styles for concrete elements (e.g. cart items in an e-shop app, or waypoints in a navigation app), then definitely do so, even if those styles are visually very similar or even the same as the general-purpose styles. It's important to be able to change text styles that have common semantics (which means they change together, for the same reason), not just a coincidentally common look.

Content text styles example

Component text styles

What about component text styles? Most importantly, they should be considered private implementation details of the components, meaning they mustn’t be used in other components or stand-alone text.

They can only be reused between a group of tightly knit components, e.g., it’s fine to have a common text style for primary, secondary, outlined, or text buttons, but it’s a bad idea to share this style with unrelated components like tabs or chips—chances are, some of these components will change independently (at a different time, or for a different reason, or both), causing problems in unrelated places.

Beware—many platforms support some kind of inheritance for text styles, meaning you can derive a new style from an existing one by adding or overriding properties. Although this feature looks appealing because it can save implementation effort, when used incorrectly it leads to unwanted coupling, similar to the reuse of styles in unrelated components.

Never misuse inheritance as a tool to share implementation. Inheritance only works when it creates an “is-a” relationship—e.g., a secondary button certainly is a kind of button, but a tab is probably not a kind of button, and thus its text style should be kept separate.

Component text styles example

Technical difficulties

You may often encounter some complications during text style specification and implementation:

  • Size units are a minefield. There are a large number of units and each platform uses its own specific ones. Sometimes the platform may even use different units for different things, which can be further complicated when the platform must support displays with different physical resolutions.
    The system design specification needs to state the values using the units appropriate for each platform, or at least provide a conversion formula.
  • Be careful, not all fonts provide all the weights or styles. Some platforms then try to interpolate the weight when asked for a value that the font does not contain, and the result is usually obviously fake, and visually pretty bad; the same can happen with italics. Real and fake italics and bold
  • Since the text in the application can come from a variety of sources, and some have built-in formatting (e.g. when displaying HTML, Markdown, etc. with bold and italics applied), the formatting may interfere with the specified weight or text style. In this case, you need to either remove the formatting first, or specify what bold and italics actually mean for each text style.
  • You need to be absolutely sure that the font family you choose contains all the characters from all the languages your application supports. It's not just a problem of seeing embarrassing "tofu" blocks in place of missing glyphs, but also of rendering diacritics correctly. Missing and invalid glyphs
  • Especially if your application uses multiple font families, each with multiple weights and styles, pay attention to size of the font files you are packaging with the application. Higher download sizes increase customer churn.

Other problems you may encounter include:

  • Languages vary greatly in word length. You have to take this into account especially when designing layouts, because what fits on one line in one language may need two or more lines in another. You have to define what should happen in that case, e.g., words are replaced, ellipsized, hyphenated, text size is reduced…
  • Especially if you are designing mobile apps, you necessarily need to see all the text on an actual phone screen. Checking on a computer or laptop display is not enough, because it may give you a distorted impression of the size and, above all, the readability of the text.
    Also remember that many people still use mobile devices with lower physical resolution, which has a big impact on readability, especially the text is small. It may often be appropriate to use other font families that render better on such devices. Displays with different resolutions


Typography plays a crucial aesthetic and practical role in a design system. At the same time, it is important to create a robust yet flexible set of text styles to support different functions of text in digital products.

Next time we'll look at one more important part of design systems—the grid.


#design-system; #ui; #ux; #development; #android; #iOS


Jiří Hutárek