DEV Community

Cover image for Typography basics and best practices for software developers
Zean Qin
Zean Qin

Posted on • Updated on • Originally published at

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;
Enter fullscreen mode Exit fullscreen mode

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="" rel="stylesheet" />
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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.

You should avoid using absolute units like px, and instead use relative units like em as much as possible.

The purpose of the px unit should be to serve as the foundation of a type system based on relative units. In other words, it’s an absolute value that a relative unit can point to in order to define its own size relative to that value.

Fun fact, the px unit doesn't actually have anything to do with screen pixels - it's just a poorly chosen name. It's actually an non-linear angular measurement. And this is why you can actually specify pixels in decimals such as 12.4px.

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.

When setting the size of some texts, try to think in relative units - "I want element A to be twice as big as element B". Instead of thinking "I want element A to be 20px".

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,

Bootstrap Headings

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.
Enter fullscreen mode Exit fullscreen mode

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.

The browser sets the line height to 1.2 by default, but it's usually too tight. And a line height of 1.5 makes the viewing experience a lot better. See image below, the line height on the left is 1.2 while the line height on the right is 1.5.

Alt Text

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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, or even the Google search result page, put a similar limit on the number of characters in a line.

That's all. Let me know in the comments section if you have any feedbacks!

Top comments (6)

dar5hak profile image
Darshak Parikh

This post was a reminder to me that you should read things even if you think you know a lot about the topic. I did know most of this stuff, but the useful ch unit was new to me.

zeanqin profile image
Zean Qin

Hahaha, same here! I only came across it a couple of days ago. Then I thought I better write it down so I can burn it into my head and actually use it.

leob profile image

Totally new to me, ch, never heard of it ...

So, 'ch' is something like the "amount" of text, horizontally, for a line or paragraph. If you use many W's or M's then way fewer characters will fit in 50ch than when you use i's or j's ... which makes the "amount of text to process" in a line 'constant' for the user (for lack of a better description).

At least for variable width fonts (for fixed width fonts an i and a W have the same width).

Thread Thread
zeanqin profile image
Zean Qin • Edited

At least for variable width fonts (for fixed width fonts an i and a W have the same width).

Oh, this is a very good point. I didn't think of this - so using ch with monospaced typefaces would result in (probably) same amount of characters on every (full) line.

scroung720 profile image

Same here. I had no idea about ch unit

zeanqin profile image
Zean Qin

One other thing that surprised me was that it's widely supported by all browsers - even IE 9!

IE 9 support