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.
"Typeface" and "Font" mean different things,
Most of the time people use them interchangeably. But hey, we're trying to look professional here ;-).
Typefaces come in all different shapes, and there is no single classification system. Below are a few of the most commonly seen categories.
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.
"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.
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.
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.
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>
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,
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.
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.
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.
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.
20px
".
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.
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
.
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;
}
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.