Typography basics and best practices for software developers

Typography is about shaping and laying out the texts on your website to create a pleasant user experience. Web design is 95% typography. And it's essential for website developers to know the basics and some common practices.

There's a lot more jargon and subjectivity in typography than in other areas. This article is intended as a concise and practical guide for software developers on choosing/using custom fonts and laying out the texts nicely and comfortably. It covers the basics to get you most of the way there.


Let's start with some basic terms and the common categories of fonts.

1. Typeface vs. Font

"Typeface" and "Font" mean different things,

  • typeface is the design (e.g. shape) of a collection of letters, numbers and symbols (also called glyphs), whereas
  • font is a specific size, weight, or style (e.g. regular, bold, italic) of a typeface.

Most of the time people use them interchangeably. But hey, we're trying to look professional here ;-).

2. Common Font Categories

Typefaces come in all different shapes, and there is no single classification system. Below are a few of the most commonly seen categories.

2.1 Serif

A “serif” is a small stroke attached to the ends of letters, giving them a traditional feel. The "serif" category includes a few sub-categories such as Old Style, Classical, Neo-Classical, Transitional, Clarendon, etc. These typefaces are mostly used in books and newspapers.

Below is what the "Caslon" font (in the Old Style subcategory) looks like. Notice the small feet present at the tops and bottoms of each letter.


You can see the top 10 most popular serif fonts here.

2.2 Sans Serif

"Sans" comes from the French "without" and as the name states - sans-serif typefaces don’t have these extra strokes, giving them a smooth, modern feel. It includes humanist, geometric and grotesk etc. as sub-categories.

Below is the font called "Futura" in the Sans Serif category. Again, notice the clean and straight lines, compared to the serif fonts.


You can see the top 10 most popular sans serif fonts here.

2.3 Monospace

Monospaced typefaces are non-proportional - every glyph takes up the exact same space. It's possible to arrange them into visual structures. And your code editor probably uses a monospace font.

Below is the "Courier" font which is a monospace font.


You can see the top 10 most popular monospace fonts here.

3. "Web safe" Fonts vs Custom Fonts

A font is "web safe" if most computers have it installed already, and these computers don't have to download it separately when visiting your site. Examples include Arial, Times New Roman, Courier, Georgia, Verdana and more.

A website can declare a custom font as a resource, just like CSS, images or JavaScripts. And the visiting browser will download the font and apply it to the texts on the website.

Using fonts

You can apply a font by using the "font-family" attribute with the following syntax in CSS.

body {
  font-family: 'custom-font', fallback1, fallback2;

Where is the custom-font coming from? Well, it could be from either your OS if you have it installed (e.g. Segoe UI on Windows, or Roboto on Android), or a third party such as Google Fonts, Adobe Fonts etc. In the later case, you most likely need to tell the browser to download it by including the <link> tag in the head of your page, like below.

    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" />

Flash of Unstyled Text

In the case that a custom font used by a website is not available on the visiting computer, it needs to be transferred across the wire. This takes time! The browser will use a fallback font in the font stack until the custom font is loaded. This can cause the flash of unstyled text (FOUT).

As an example, suppose you had the font stack below,

body {
  font-family: Merriweather, Georgia;

and the font "Merriweather" needs to be downloaded by the browser, you could have the texts to flash like below after the page is loaded.

Flash of Unstyled Text

Some common approaches to mitigate FOUT include,

  • using a third party (e.g. Google Fonts, Adobe Fonts etc.) to optimise the font files and deliver them via a CDN,
  • transforming your font files using tools like Transfonter,
  • picking a fallback font that's similar to the custom font you want to use with tools like Font style matcher.

Native font stack

A “native font stack” allows for optimum text rendering on every device and OS with zero latency. For example, Bootstrap 4 uses the following native font stack by default,

  // Safari for OS X and iOS (San Francisco)
  // Chrome < 56 for OS X (San Francisco)
  // Windows
  "Segoe UI",
  // Android
  // Basic web fallback
  "Helvetica Neue", Arial, sans-serif,
  // Emoji fonts
  "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;

And you can find more system font stacks here.

Best Practices

I've listed some of the practices that I follow in choosing font size, heading size, line height, letter spacing and how many characters should be included in one line.

1. Font sizing

Sizing in CSS can be specified in either absolute units (think px) or relative units (e.g. em). The size of an element specified in absolute units doesn't change, while the size of an element specified in relative units depends on the size of other elements on the page.

As an example, most desktop browsers usually sets the texts inside the body tag to 16px by default. You can use 2em on an element if you want it to be twice as big as the body text.

2. Heading sizing

The size of headings are usually expressed in relative units. And it's common to define 6 levels of headings.

Bootstrap 4 defines the size of headings as below,

Headings in Bootstrap 4

Another popular approach is to define a modular scale to define the heading sizes. Basically, it means specifying a root number and a ratio, and ratios are multiplied by the base to produce a scale of numbers that is proportionally related. For example, the following scale uses base 1em and the ratio 1.5. You can use this tool to create your custom scale.

Modular Scale

3. Line height

Line height can be specified in CSS using the line-height property like below,

p {
  line-height: 1.5; # Note - better to not use any unit here.

When you don't put a unit, it's relative to the computed size of the text. For example, if the text is 12px (or 0.75em in a browser with default font size of 16px) in size, the line height will be 18px.

4. Letter spacing

This is used a lot less compared to line-height or font-size. In general, we only need to specify custom spacing for texts that are either too big or too small. And you can do it in CSS using the letter-spacing property. Similar to font-size, it's best to be specified in relative units such as em.

p {
  letter-spacing: 1em;

5. Length of line

The general consensus is that lines should contain 60 to 70 characters for best reading experience, especially for text heavy pages.

And you can specify the line length in CSS using the following property,

p {
  width: 50ch;

The unit ch represents the width, or more precisely the advance measure, of the glyph "0". And 50ch generally results in line width to be 60 to 70 characters in length. A lot of text heavy sites, such as Medium.com, or even the Google search result page, put a similar limit on the number of characters in a line.


  1. nuxt/content
  2. Typography for Developers
  3. Web Design is 95% Typography
  4. Using UI System Fonts In Web Design: A Quick Practical Guide
  5. CSS px is an Angular Measurement
  6. Modular Scale
  7. Safe web fonts