When you're displaying currency or numeric data, tabular numbers help digits line up cleanly. But they often mess up punctuation – commas and full stops get spaced out too, and it can look weird!
This might not be a problem for you. Some fonts, like Inter, handle tabular numbers better than others – their punctuation doesn’t throw off the visual spacing as much as they use less wide characters for punctuation. If that’s the case, you’re probably fine without this.
For the font nerds: In many fonts, tabular digits are typically set to 600 units wide (assuming a 1000 units-per-em grid). But in some typefaces, punctuation like commas and full stops also get padded to that width in the tnum
set. That’s where things start to look off. Fonts like Inter take a smarter approach – digits stay aligned, but punctuation stays tight (around 200–300 units), which feels more natural.
DM Sans (left) vs Inter (right) - both set to tabular-nums
The problem
Say you've got a list of prices or currency values. You want the digits to align neatly in a column. The CSS property font-variant-numeric: tabular-nums
is perfect for this – it makes each digit take up the same width, so your numbers line up perfectly.
But there's a catch: many fonts will treat punctuation marks (like commas and decimal points) as tabular too. This means they get the same rigid spacing as the digits, which can make the whole thing look overly spaced or clunky.
Here's what that looks like in practice:
Default (No special formatting)
£1,212.12
£9,090.90
£12,345.67
Tabular Numbers (All characters)
£1,212.12
£9,090.90
£12,345.67
Font used: DM Sans
Notice how the commas and decimal points in the tabular version are spaced out too? That's what we want to fix.
The solution
What we really want is:
- Digits using tabular spacing (so they line up)
- Punctuation using normal spacing (so it looks natural)
You could split the string manually and wrap digits in a span, but that's messy and doesn't scale. Instead, we can use a small utility class and a bit of JavaScript to handle this automatically.
Here's how it works:
- First, we create our CSS utility classes:
.tabular-nums {
font-variant-numeric: tabular-nums;
}
.normal-nums {
font-variant-numeric: normal;
}
.tabular-nums-only {
font-variant-numeric: tabular-nums;
}
char.normal-nums {
display: inline;
}
- Then, we wrap our numbers in the
.tabular-nums-only
class:
<p class="tabular-nums-only">£1,212.12</p>
- Finally, we use a small JavaScript snippet to wrap just the punctuation in a tag that overrides the spacing:
document.querySelectorAll(".tabular-nums-only").forEach((el) => {
el.innerHTML = el.innerHTML.replace(/([.,])/g, '<char clas="normal-nums">$1</char>');
});
This works nicely with most fonts that support font-variant-numeric: tabular-nums
. Here's how it looks:
Tabular Numbers (Digits only)
£1,212.12
£9,090.90
£12,345.67
Font used: DM Sans
A note on the markup
I used a <char>
tag here. It's not a real HTML element, but that's fine – unknown tags are treated as inline by default, so they behave nicely in the browser.
It also keeps the markup readable. You could use <span>
, but if your digits are already inside a span, things can get confusing quickly.
You can swap it for something like <digit>
or <number>
if you prefer, but there's a small risk browsers might start supporting those tags differently in the future.
Things to watch out for
- This only works if your font supports tabular numbers.
- Mixing numbers with and without decimal points might still throw off your alignment slightly.
Why bother?
You might not need this fix – plenty of fonts handle tabular numbers cleanly in CSS.
But if you're using font-variant-numeric: tabular-nums
and seeing odd spacing around punctuation, this gives you a bit more control. It's just one class and a small script – easy to add, easy to remove later if browser or CSS support changes.
Here's a comparison of all three approaches side by side:
Default (No special formatting)
£1,212.12
£9,090.90
£12,345.67
Tabular Numbers (All characters)
£1,212.12
£9,090.90
£12,345.67
Tabular Numbers (Digits only)
£1,212.12
£9,090.90
£12,345.67
Font used: DM Sans