A How-to Guide to Font Selection
Motivation. There are two practical considerations to move beyond the default fonts. First, defaults are designed to be universally applicable, which inevitably makes them suboptimal for specific situations. Different types of texts—such as research papers, technical manuals, personal blogs, or software user interfaces—require different fonts to establish the right tone and clearly convey meaning without distracting their readers. Second, from a practical standpoint, most fonts are created to support only a limited subset of characters and styles. In practice, we have to deal with coverage issues and need to pair fonts to handle a wide range of characters, especially in non-English texts.
In this note, I will first clarify some terminology and introduce the general principles for choosing fonts. Then, I provide guides on the following topics: previewing fonts, querying fonts, and inspecting fonts. Finally, I include a list of my favorite fonts and a brief overview of text rendering in the appendices.
Terminology
Terms used in typography, web development, and other fields may vary a lot. To avoid possible confusions, a brief list is provided below for reference. More terms and explanations can be found in the Glossary provided by Google Fonts, The Vocabulary of Type in Tracy (2003), and Appendix C: Glossary of Terms in Bringhurst (2002).
- Glyph.
A glyph is a specific, visual representation of a character. Glyphs are the visual forms; characters are the abstract text elements.
In traditional typography, a glyph is literally a physical piece of metal or wood. In early digital typography, a glyph is a bitmap image—a pattern of tiny pixels that, when viewed together, resembles the shape of a character. In modern digital typography, a glyph is a vector outline—a flexible, resolution-independent vector graphic used to render a character visually.
A single character may have multiple glyphs (see alternates), and a glyph may represent multiple characters (see ligatures).
- Font.
A font is a set of glyphs.
In traditional typography, a font is a physical plate with all its glyphs. In modern digital typography, a font is the digital palette itself or the digital information encoding it (a font file). Currently, most fonts are available in TrueType (.ttf, .ttc), OpenType (.otf, .otc), or Web Open Font Format (.woff, .woff2).
- Font family
A font family is a collection of fonts that share the same design.
Each font in a family often has a specific size and weight. For example, the font
DejaVu Sans-12:bold
has a size of 12 points and a weight of bold. The font family, in this case, is DejaVu Sans.In addition, a superfamily is a group of related font families. For example, the superfamily DejaVu contains font families DejaVu Serif, DejaVu Sans, and DejaVu Sans Mono.
How-to: Choose Fonts
The general principle for choosing fonts is to ensure that they effectively convey the intended meaning of the text. To achieve this, one need to check:
- The selected fonts are appropriate for the project. To avoid issues, choose fonts that were designed for the intended use.
- The selected fonts offer enough style variants to reflect text structures. For example, make sure there are suitable styles for emphasis, headlines, verbatim texts, and code sections.
- The selected fonts provide adequate script coverage (e.g., Greek and CJK).
- (Optional) The selected fonts support advanced typographic features. Look for features such as ligatures, alternative stylistic sets, and proper handling of punctuation for CJK characters.
For detailed considerations, please refer to Choosing type.
How-to: Preview Fonts
If a font family is accessible on the machine, then a convenient way to preview it is through the web browser. For example, the following HTML template previews the regular, italic, bold, and the small caps variant in Lora family.
<div class="font-section" style="font-family: lora;"> <p style="font-size: xx-large; font-variant: small-caps">Lora:</p> <p> <b>Theorem (Arzelà–Ascoli).</b> Consider a set of real-valued continuous functions defined on a compact metric space. If this set is <i>equicontinuous</i> and <i>pointwise bounded</i>, then it is relatively compact in the topology induced by the <i>uniform</i> norm. </p> </div>

For preview results of additional fonts, see also Appendix: A List of
My Preferred Fonts. To list fonts available to the operating system,
see also Appendix: Query Fonts via Fontconfig. Given a font file in
.ttf or .otf format, one can use otfinfo
or this online tool to view
various metadata of the font; see also Appendix: Inspect OpenType Font
Files.
How-to: Query Fonts
Fontconfig is a free and open-source software library designed to
provide font discovery, configuration, and substitution functionality
on Linux. It comes with a set of command-line utilities fc-*
. Some of
their usages are demonstrated below.
fc-list. List and filter fonts Fontconfig knows about.
fc-list :family=lora:style=italic file
/home/dou/.local/share/fonts/opentype/Lora/Lora-Italic.otf: /home/dou/.local/share/fonts/opentype/Lora/Lora-SemiBoldItalic.otf: /home/dou/.local/share/fonts/opentype/Lora/Lora-MediumItalic.otf:
fc-match. Find the font that matches a given pattern.
fc-match "lora-8:slant=italic:weight=medium" file
:file=/home/dou/.local/share/fonts/opentype/Lora/Lora-MediumItalic.otf
fc-pattern. Parse and show pattern according to Fontconfig's syntax.
fc-pattern "lora-8:slant=italic:weight=medium"
Pattern has 4 elts (size 16) family: "lora"(s) slant: 100(i)(s) weight: 100(f)(s) size: 8(f)(s)
See more explanations in fontconfig user documentation.
How-to: Inspect Fonts
OpenType (.otf) is an extension of TrueType (.ttf), and both are
widely supported font formats on modern systems. Besides the glyph
table, an OpenType font file also encodes various metadata and other
font information to provide advanced typographic capabilities; see
also OpenType Layout Overview. The online tool Font Drop can be used
to inspect these data. Below, I demonstrate the usage of otfinfo
.
The command-line utility otfinfo
can report scripts and language
systems supported in the font.
otfinfo -s sarasa-term-sc-nerd-regular.ttf
... hani CJK Ideographic hani.JAN CJK Ideographic/Japanese hani.KOR CJK Ideographic/Korean hani.ZHH CJK Ideographic/Chinese, Hong Kong SAR hani.ZHS CJK Ideographic/Chinese Simplified hani.ZHT CJK Ideographic/Chinese Traditional ... latn Latin latn.JAN Latin/Japanese latn.KOR Latin/Korean latn.ZHH Latin/Chinese, Hong Kong SAR latn.ZHS Latin/Chinese Simplified latn.ZHT Latin/Chinese Traditional
This shows that it supports two script systems: Latin and CJK. For CJK scripts, it supports five language systems: Simplified Chinese, Traditional Chinese, Chinese HK, Japanese, and Korean.
Supported OpenType features can also be printed via otfinfo
.
otfinfo -f Lora-Regular.otf
aalt Access All Alternates calt Contextual Alternates case Case-Sensitive Forms ccmp Glyph Composition/Decomposition frac Fractions kern Kerning liga Standard Ligatures mark Mark Positioning mkmk Mark to Mark Positioning ordn Ordinals pnum Proportional Figures sups Superscript tnum Tabular Figures
For font collections (.ttc or .otc), one can inspect encoded tables or extract individual fonts via Fonttools.
from fontTools.ttLib import TTCollection from pathlib import Path filepath = Path(...) ttc = TTCollection(filepath) # list opentype features for i, font in enumerate(ttc.fonts): print(f"Font index {i}:") if "GSUB" in font: gsub = font["GSUB"] featureList = gsub.table.FeatureList if featureList: featureSet = set() for record in featureList.FeatureRecord: featureSet.add(record.FeatureTag) print(sorted(list(featureSet))) # unpack the font collection for i, font in enumerate(ttc.fonts): output_path = f"{filepath.stem}_{i}.ttf" try: font.save(str(output_path)) # font.save() expects a string path print(f"Extracted: {output_path}") except Exception as e: print(f"Error saving font {i}: {e}")
References
Books:
Online resources:
- Fontconfig user documentation. https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user.html.
- Fonttools. https://github.com/fonttools/fonttools
- Google fonts knowledge. https://fonts.google.com/knowledge.
- MDN web docs. Font. https://developer.mozilla.org/en-US/docs/Web/CSS/font.
- OpenType® specification version 1.9.1. https://learn.microsoft.com/en-us/typography/opentype/spec/
Appendix: Text Rendering
According to Microsoft's OpenType Specifications, a string of characters codes are rendered by following a standard process summarized below.
- Convert a string of characters into a sequence of character codes.
- Convert the character codes into a sequence of glyph indices.
- Modify, substitute, and position the glyphs.
- Rasterizes the line of glyphs and renders the glyphs in device coordinates that correspond to the resolution of the output device.
Here, a character code (or code point) is simply an integer, which uniquely identifies a specific character within the Unicode standard. These integers are often experssed in hexadecimal (base-16) format, using the prefix "U+". For example, the letter "A" is assigned the integer 65, which is represented as "U+0041".
Appendix: A List of My Favorite Fonts
Below is a collection of my favorite fonts and their attributes; see previews here. The column Supported Scripts considers only: Latin, Greek, Math, and CJK. The column OpenType Features considers only: ligatures, fractions, small capitals, superscripts, and subscripts.
Font Family | Properties and Tags | Supported Scripts | Style Variants | OpenType Features | Recommended Usage | Additional Info |
---|---|---|---|---|---|---|
DejaVu Serif | Serif | Latin, Greek | Regular, Italic, Bold, Bold Italic | Ligatures | Print, documents, body text | Good Unicode coverage, Free & Open Source |
DejaVu Sans | Sans-serif | Latin, Greek | Regular, Oblique, Bold, Bold Oblique | Ligatures | UI, web design, documentation | Readable at small sizes, Free & Open Source |
DejaVu Sans Mono | Monospace | Latin, Greek | Regular, Oblique, Bold, Bold Oblique | N/A | Coding, terminals | Popular with programmers, Free & Open Source |
Fira Sans | Sans-serif | Latin, Greek | Regular, Italic, Bold, Bold Italic | Fractions, Ligatures, Small Capitals, Subscripts, Superscripts | UI, body text, print | Modern, legible design, Free & Open Source |
Fira Code | Monospace | Latin, Greek | Regular, Bold | Fractions, Subscripts, Superscripts | Code editors, programming | Specialized for programming, includes ligatures for code |
Lora | Serif | Latin | Regular, Italic, Bold, Bold Italic | Fractions, Ligatures, Superscripts | Editorial, web, blogs, print | Contemporary with roots in calligraphy, Google Fonts |
Noto Serif CJK SC | Serif | Latin, Greek, CJK | Regular, Bold | Ligatures | Multilingual documents, CJK support | Excellent for combining CJK & Latin, Google Fonts |
Noto Sans CJK SC | Sans-serif | Latin, Greek, CJK | Regular, Bold | Ligatures | UI, documents, multilingual text | Excellent for CJK and Latin, Google Fonts |
Noto Sans Mono CJK SC | Monospace | Latin, Greek, CJK | Regular, Bold | Ligatures | Programming, multilingual coding | Covers East Asian monospace needs, Google Fonts |