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.
Basics
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.
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" />
</head>
</html>
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.
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,
$font-family-sans-serif:
// Safari for OS X and iOS (San Francisco)
-apple-system,
// Chrome < 56 for OS X (San Francisco)
BlinkMacSystemFont,
// Windows
"Segoe UI",
// Android
"Roboto",
// 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.
You should avoid using absolute units like
px
, and instead use relative units likeem
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 as12.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,
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.
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
.
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.
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.
That's all. Let me know in the comments section if you have any feedbacks!
Top comments (6)
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.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.
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).
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.Same here. I had no idea about ch unit
One other thing that surprised me was that it's widely supported by all browsers - even IE 9!