OpenType features
The features hiding inside your font files
Most fonts ship with dozens of features you're not using. Ligatures, tabular figures, small caps. The difference between a font _being available_ and a font _looking right_.
## The body-text essentials
Enable these four for running text:
```css
body {
font-kerning: normal;
font-variant-ligatures: common-ligatures contextual;
/* or, explicit */
font-feature-settings: "kern", "liga", "clig", "calt";
}
```
- **`kern`**: adjusts space between letter pairs (`AV`, `To`, `Wa`).
- **`liga`**: standard ligatures (`fi`, `fl`, `ff`, `ffi`, `ffl`).
- **`clig`**: contextual ligatures.
- **`calt`**: contextual alternates.
Most browsers enable these by default. Explicit declarations guard against inconsistencies. Prefer `font-variant-*` over `font-feature-settings` since changing one feature in `font-feature-settings` resets the others.
## Ligatures in detail
OpenType groups ligatures into four categories:
- **Standard (`liga`)**: everyday set (`fi`, `fl`). Always on for body.
- **Contextual (`clig`)**: substitutions based on surrounding context. On for body.
- **Discretionary (`dlig`)**: decorative pairs (`st`, `ct`, `Th`). Off for body, on for headlines.
- **Historical (`hlig`)**: long-_s_ ligatures and archaic forms. Off unless the design calls for it.
```css
body {
font-feature-settings: "liga", "clig", "calt";
}
h1 {
font-feature-settings: "liga", "dlig", "clig", "calt";
}
```
## Code block typography
Ligatures harm code. They collapse `fi` into one glyph and transform `!=` into a combined symbol:
```css
code,
pre {
font-variant-ligatures: none;
font-feature-settings:
"liga" 0,
"clig" 0,
"calt" 0;
}
```
Choose a monospace face with distinct `0`/`O`, `l`/`1`/`I` glyphs: JetBrains Mono, Fira Code (ligatures off), Cascadia Code, Berkeley Mono. Set code `line-height` at 1.5–1.7.
## Small caps
True small caps are _drawn_ at the optical size of lowercase, not shrunk. A real small-cap `H` has the stroke weight of a lowercase `h`. Pseudo small caps (scaled-down uppercase) are too thin.
```css
.abbr {
font-variant-caps: all-small-caps;
letter-spacing: 0.05em;
}
```
Use for abbreviations (NATO, HTML, BBC), short labels, and editorial credits. Verify the font ships `smcp` first. Many free fonts omit it.
## Tabular vs. proportional figures
**Tabular figures** give every digit the same width:
```css
.data-table td {
font-variant-numeric: tabular-nums;
text-align: right;
}
```
Use tabular figures for tables, prices, dashboards, and animated counters. **Proportional figures** (variable widths) for body text.
## Oldstyle vs. lining figures
**Oldstyle figures** have ascenders and descenders, like lowercase letters. **Lining figures** sit on the baseline at cap height.
```css
body {
font-variant-numeric: oldstyle-nums; /* prose */
}
.btn,
h1,
table {
font-variant-numeric: lining-nums; /* UI / headings / data */
}
```
If `font-variant-numeric: oldstyle-nums` produces no visible change, the font doesn't support it.
## Other features worth knowing
- **`dlig`**: discretionary ligatures. Display only.
- **`swsh`**: swashes. Ornate alternates, display only.
- **`salt` / `ss01`–`ss20`**: stylistic alternates and sets. Alternate letter shapes the designer offers.
- **`c2sc`**: uppercase to small caps. Pair with `smcp` to convert all caps.
- **`onum` / `lnum`**: oldstyle and lining figures.
- **`tnum` / `pnum`**: tabular and proportional figures.