# Numbers, features and faces

> Line numbers up with tabular figures, reach the extras inside a font file, and choose a typeface that doesn't read as the default.

Module: Typography · Level: intermediate · 7 min · https://school.agents.org.in/design/typography/numbers-and-faces

Watch the right-hand column of this price table for a few seconds. Then flip the switch.

*[Interactive demo: Proportional digits jiggle as they tick. Tabular digits hold still.]*

Most fonts draw a "1" narrower than an "8", which looks lovely in a sentence and terrible in a column. Every update shifts the number sideways and nothing lines up.

## Tabular figures for anything that changes

Tabular figures (Digits that all take the same width, so numbers line up in columns and a ticking counter doesn't wiggle. Turned on with font-variant-numeric: tabular-nums) give every digit the same width. Columns align, and a ticking timer only moves the digits that actually changed.

```css
.price, .timer, td.number { font-variant-numeric: tabular-nums; }
```

Use them on timers, prices, counters, scores, table columns of figures, anything live. Leave running prose on the default figures, which read more naturally in a sentence. Numbers people compare also right-align, so the decimal points stack.

## What's hidden in a font file

A good font carries far more than one set of letters. These extras are called OpenType features (Optional extras hidden inside a font file: tabular digits, a slashed zero, real fractions, small caps, alternate letters. CSS switches them on), and CSS switches them on. Try a few on Inter, the face this demo uses:

*[Interactive demo: A slashed zero for codes, real fractions, and a weight axis that takes any number.]*

The useful ones:

- **`slashed-zero`** wherever 0 and O can be confused: order codes, serial numbers, coupons.
- **`diagonal-fractions`** for ½-style fractions in recipes and specs.
- **Real small caps (Capital letters drawn at about lowercase height, designed to match the weight of the text. Shrinking normal capitals instead makes them look thin)** with `font-variant-caps: small-caps`, never shrunken capitals, which come out too thin.
- **Real superscripts** (m², CO₂) with `font-variant-position: super | sub`, instead of the default `<sup>`, which is too big and pushes lines apart.
- **Stylistic sets** (`ss01` to `ss20`) are numbered slots whose meaning differs in every font. Read the font's specimen, then comment what the slot does: `font-feature-settings: "ss02" 1; /* single-storey a */`.

> **Features fail silently.** If the font doesn't contain the feature, nothing happens and nothing warns you. Check that the glyphs exist, and prefer the named CSS property over raw four-letter codes, because properties fall back sensibly.

## Variable fonts and their axes

A variable font (One font file that holds a whole range of a style, usually weight, so any value like font-weight: 473 is real instead of only 400 and 700) is one file holding a whole range of a style. Weight is the common one, which is why the slider above accepts 430 or 610, not just 400 and 700. Each range is an **axis**:

| Axis | Varies | Set it with |
|---|---|---|
| `wght` | weight | `font-weight` |
| `wdth` | width | `font-stretch` |
| `opsz` | optical size (Versions of a typeface tuned for a size: sturdier and looser for small text, finer and tighter for big headlines. Some fonts adjust it automatically) | `font-optical-sizing: auto` |
| `slnt` / `ital` | slant, italic | `font-style` |

A font exposes only the axes it was built with. One or two weights usually ship lighter as separate static files; many weights or an optical-size axis favour the variable file. Measure rather than assume.

Some families ship separate cuts for size, like Text and Display versions of one design: sturdier and looser for paragraphs, finer and tighter for headlines. Pick the cut for the size you set.

## Choosing a face that isn't the default

Now the human part. Flip between these three versions of the same hero.

*[Interactive demo: The default, a pair across categories, and one family doing everything.]*

Inter and SF Pro are excellent, neutral and on nearly every generated page. That ubiquity is the problem: on a landing page, the stock face at stock weights signals "default" before anyone reads a word.

The skill's advice:

- **On marketing pages, pick something with character.** Foundries worth knowing include Pangram Pangram, Displaay, Grilli Type and Vercel's Geist. Pair across categories when you use two (a serif display over a sans text face), never two lookalikes.
- **Inside the product, Inter or SF Pro are fine.** They were built for screens and stay legible at 12px. But then you have used your one default: don't also ship the default colors and the default icons.
- **The single-weight rule.** For a first version, use **one weight** of one face for everything and get hierarchy from size and space. It's cheaper, faster and usually cleaner. Add weights when a real need shows up.

**Test the face at every size you actually use.** Geometric faces that look great at 16px can turn to mush at 11px, which is when Inter's boring legibility wins. *(A typeface is a tell only on surfaces where people judge the brand. In a dense settings screen, legibility is the brand.)*

**Numbers and fonts (paste into your agent):**

```text
Typography details pass:
- font-variant-numeric: tabular-nums on every price, timer, counter and number column; right-align compared figures.
- Use named CSS properties for font features (font-variant-numeric, font-variant-caps, font-variant-position, font-weight); font-feature-settings only for stylistic sets, with a comment saying what the slot does in this font.
- slashed-zero on order codes and serials.
- Marketing pages: propose two typefaces that aren't Inter/SF Pro, paired across categories, and start with a single weight. Keep Inter for dense product UI.
```

**Check yourself:** A dashboard counter updates every second and the number shivers sideways. What's the one-line fix?

- [ ] letter-spacing: -0.01em
- [x] font-variant-numeric: tabular-nums
- [ ] font-weight: 600
- [ ] text-align: center

*Why:* Tabular figures give every digit the same width, so only the digits that change move and nothing shifts.

## In the skill

- https://school.agents.org.in/skill/typography/opentype-features-and-axes.md
- https://school.agents.org.in/skill/typography/typography-humanity.md
