Journal··8 min read

Lining, Oldstyle, and Tabular Figures: The Numbers Most Designers Forget to Set

Four figure styles, two axes, and one CSS property that fixes the jittering numbers in your dashboard.

OpenTypeFundamentals

Type discussions default to letters. Numerals get chosen by accident — whatever the font happens to ship as default — and then cause problems nobody traces back to a typographic decision. Prices that shift position as they update, a table of figures that will not align, a date inside a paragraph that reads as a row of tiny billboards. All four of those are figure style problems, and all four are one CSS declaration away from being fixed.

Two Independent Choices

Figure styles vary along two axes that can be combined freely. The first is height: lining figures are all the same height as the capitals, while oldstyle figures — also called text figures — have varying heights with ascenders and descenders, so a 3 drops below the baseline and an 8 rises above the x-height. The second is width: tabular figures all occupy an identical advance width, while proportional figures are spaced individually so a 1 takes less room than a 0.

Two axes give four combinations, and each has a job. Lining tabular for data. Lining proportional for headlines and interface labels. Oldstyle proportional for running prose. Oldstyle tabular is rare but appears in book indexes and footnote columns. A well-equipped text family ships all four; a display face may ship only one.

Tabular Figures Solve the Jitter

If you have ever watched a live-updating counter, a stopwatch, or a price wobble horizontally as the digits change, you have watched proportional figures at work. Because each digit has its own width, replacing a 1 with an 8 changes the string's total width and shifts everything after it. Tabular figures give every digit the same advance, so the string width depends only on the number of characters. The counter stops dancing.

The same property makes columns of numbers align without any additional effort. In a table of prices or measurements, tabular figures put the hundreds column above the hundreds column automatically. Right-aligning proportional figures gets you partway there but leaves the interior digits ragged, which is exactly the misalignment that makes financial tables hard to scan.

If a number can change while the user is looking at it, or sits above another number, it wants tabular figures.

Oldstyle Figures Belong in Sentences

Lining figures are cap height, which means a year written inside a paragraph creates four letter-height spikes in a line of lowercase text. The eye reads them as an interruption. Oldstyle figures were designed to solve this: their varying heights give them the same visual texture as lowercase, so a date or a quantity sits inside the sentence instead of jumping out of it.

The trade-off is scanability. Because oldstyle figures blend in, they are harder to find when a reader is hunting for a number rather than reading. Use them in running prose, book-style body copy, and editorial layouts. Avoid them in dashboards, pricing tables, form fields, and anywhere the number is the thing being looked up.

The CSS You Need

The font-variant-numeric property controls all of this, and it is well supported across current browsers. The values you will actually use are tabular-nums, proportional-nums, oldstyle-nums, and lining-nums, and they can be combined in a single declaration such as font-variant-numeric: oldstyle-nums proportional-nums. There is also the lower-level font-feature-settings approach using tags like tnum and onum, but the high-level property is more readable and should be preferred.

Two adjacent features are worth knowing. The value diagonal-fractions turns 1/2 into a properly drawn fraction with a diagonal bar, replacing the awkward slash-and-two-digits fallback. And slashed-zero, exposed as the zero feature, distinguishes 0 from O — worth enabling for order numbers, licence keys, and any string a user has to read aloud or retype.

It Only Works If the Font Has Them

Every one of these declarations is a request, not a guarantee. If the font file contains no oldstyle set, font-variant-numeric: oldstyle-nums does nothing at all and you get the default figures with no warning, no console message, and no visual clue beyond the effect being absent. This is the most common reason a developer concludes the property is broken.

There is a second trap specific to web fonts. Aggressive subsetting to reduce file size frequently strips alternate glyph sets, so a font that supports tabular figures in its desktop form may lose them in the woff2 you are serving. If figure features matter to your interface, verify them in the built file rather than in the foundry's specimen, and check the subsetting configuration before assuming the font is at fault.

A Short Audit

  • Data tables, financial figures, and any column of numbers: lining tabular.
  • Live counters, timers, and countdowns: tabular, always.
  • Dates and quantities inside running prose: oldstyle proportional, if the family supports it.
  • Headlines and large display numbers: lining proportional, then check the spacing by eye.
  • Order numbers and codes users must transcribe: enable the slashed zero.

Numerals are the part of a typeface most likely to be inherited rather than chosen. Spending ten minutes on them usually removes a visual bug that a team has been quietly tolerating for months. The Font Weight Preview Tool and the Font Pairing Recommendation Tool on this site help you audition a family's letters; when you are evaluating a face for an interface with real data in it, paste a column of numbers into the preview as well and watch what the digits do.