BJRN Logo

Tabular Numbers: the tiny typography switch that makes dashboards feel “engineered”

|4 min read

If you’ve ever built a live-updating UI—price tickers, timers, analytics dashboards, order books—you’ve probably seen it: numbers update, and the layout wriggles. Nothing is “broken”, yet the interface suddenly feels cheap.

Live Precision Test

Proportional Default
Rev Q1111,100
Rev Q2888,800
Rev Q3123,456
Notice the jittering layout as numbers rapidly change width.
Tabular Nums Optimized
Rev Q1111,100
Rev Q2888,800
Rev Q3123,456
Beautifully stable. Perfect vertical alignment maintained.
ImplementationCSS
.tabular-nums {
font-variant-numeric: tabular-nums;
}

The reason is simple: most fonts render digits proportionally by default. In proportional figures, 1 is usually narrower than 0 or 8. So when 199 becomes 200, the text width changes, and your rows/columns nudge left and right.

And once you notice it, you can’t unsee it.

This is not only a “visual annoyance”. It reduces scanability in dense tables and increases perceived instability in UIs that are supposed to communicate precision (finance, monitoring, metrics, ops, etc.).


The real problem: proportional digits + frequent updates = jitter

Typography defaults are optimized for reading paragraphs, not for machines spitting out constantly changing digits.

Proportional figures are great in running text because they look natural. But in a UI where numbers are:

  • aligned in columns (tables, leaderboards)
  • compared at a glance (diffs, KPIs, deltas)
  • updated frequently (streaming data, timers)

…proportional width becomes a layout liability.

Even if the overall container width is fixed, the internal alignment still shifts, which is exactly what your eye tracks while scanning.


The fix: tabular-nums (monospace behavior, but only for digits)

OpenType fonts often include a “tabular figures” feature: every digit takes the same horizontal space.

In CSS, you enable it with:

.metric,
.price,
.timer {
  font-variant-numeric: tabular-nums;
}

That’s it. No special font, no JS measurement hacks, no manual padding.

If you want a very “UI-ish” look, you can also force lining numbers:

.metric {
  font-variant-numeric: tabular-nums lining-nums;
}

tabular-nums is the important part for alignment. lining-nums is a stylistic preference (more uniform for interfaces than oldstyle figures in many fonts).


Tailwind version (same idea, less typing)

Tailwind exposes it directly:

<span class="tabular-nums">12.345</span>

If you also want lining numbers and your Tailwind setup supports it:

<span class="tabular-nums lining-nums">12.345</span>

Where it matters most (frontend “hot spots”)

I personally reach for tabular-nums in a few predictable places:

  • Tables: totals, percentages, money, counts
  • Timers: 09:5910:00 (this one looks especially “jumpy” without it)
  • Trading / finance UI: price, change, spread
  • Monitoring dashboards: CPU %, requests/sec, error rate
  • Any “dense list of numbers” where your user is scanning patterns, not reading prose

A good mental model: if the user is comparing numbers, tabular figures help; if they’re reading a sentence, proportional figures may look nicer.


When not to use it

tabular-nums is a tool, not a default for everything.

Avoid applying it globally on body if your site has lots of editorial text. In paragraphs, tabular figures can feel slightly rigid and “spread out”, depending on the font.

A nicer approach is scoping:

/* editorial pages: keep default */
article {
}
 
/* data surfaces: make numbers behave */
.dashboard,
.table,
.kpi {
  font-variant-numeric: tabular-nums;
}

Font support notes (the practical part)

A few quick realities from the trenches:

  • Not every font supports every numeric feature. If the font doesn’t have tabular figures, the property won’t magically invent them.
  • Most modern UI fonts do support it, especially system UI stacks and many popular web fonts.
  • If you’re using a variable font or a custom brand font, it’s worth verifying the feature exists.

If you want the “explicit” OpenType switch, you can also do:

.metric {
  font-feature-settings: "tnum" 1;
}

But prefer font-variant-numeric when possible—it’s more readable and maps to the same underlying OpenType features.


TL;DR

  • proportional digits: better for prose, worse for live-updating numeric UI
  • tabular digits: better for alignment, stability, and “engineered” feel
  • use: font-variant-numeric: tabular-nums; (or Tailwind tabular-nums)