Tabular Data Type
Monospace as a data contract rather than an aesthetic, with a proportional counter-example directly beside it.
Penelope: Long-running fidelity. Maintained excellence over years.
Exhibit case
Why it matters
Numbers in a proportional font are unreadable as a set. The digit one is narrower than the digit zero in almost every text face, so a column of figures shifts horizontally row by row, and comparing values requires actually reading each one instead of scanning their shapes. In a live interface where numbers update, the column also reflows on every change — a counter ticking from 999 to 1000 nudges everything beside it.
Monospace here is not a style decision borrowed from code editors. It is a contract: fixed advance width means a column is a column, and tabular numerals mean a value can change without moving anything. The proportional example beside the tabular one makes the failure visible in one glance.
Key techniques
font-variant-numeric: tabular-numsapplied through a single[data-meta]attribute selector, so every number in the canon inherits it without a class being remembered.- All numeric metadata routed through one mono family, so figures are recognisable as data before they are read as values.
- Fixed-width formatting in the data itself —
padStart(4, "0")on durations — so the string is as stable as the glyph widths. toFixed(1)on weights, because a column mixing one and two decimal places defeats the point of the alignment it sits in.- Real table semantics:
<caption>,<thead>,scope="col", andscope="row"on the identifying cell. - Hairline row separators instead of full borders or zebra striping — the alignment already does the work of guiding the eye, so the rules can be almost invisible.
What to steal
The transferable part.The attribute hook. One [data-meta] selector setting the mono family and tabular numerals means correctness is the default and there is no class to forget. Add it to your reset and the problem stops recurring.
Padding the string, not just the font. Tabular numerals align glyph widths; they do not align a three-character value against a four-character one. Pad the value.
Fixed decimal places per column. Decide the precision once per column and format to it. Mixed precision in an aligned column looks like a bug, because it usually is one.
Showing the counter-example. Setting the same digits proportionally, right next to the tabular version, is the fastest way to win this argument with anyone who thinks it is a preference.
What not to copy
Context-specific or costly.Do not put prose in mono because it looked good in the data table. Monospace reads measurably slower in long text — the uniform widths that help figures hurt word-shape recognition. Mono is for data, labels, and code.
Do not reach for tabular-nums on marketing figures set at display size. A large hero number set in the display serif should use the serif's own proportional figures; alignment is irrelevant when there is one number, and the tabular forms are usually the less beautiful set.
Inclusion rationale
The lowest complexity entry in the canon and one of the highest ratios of correctness gained to effort spent. It is included because it is a discipline rather than a technique: the rule is trivial, the failure is everywhere, and the counter-example beside it makes the entry self-proving. Penelope for maintained fidelity — this is the kind of decision that keeps paying out silently for years.
Technical register
Performance
One additional font family, one weight, display=swap. font-variant-numeric is a rendering flag with no layout cost and no JavaScript. Values are formatted at render with two string operations per cell — trivial against the cost of rendering the row itself.
Mobile
Mono is wide, and a five-column table at 375px is the case where this discipline collides with reality. The honest answer at small widths is fewer columns, not smaller type: keep the identifying row header and the one or two figures that matter, and move the rest behind a detail view. Shrinking mono below 0.8125rem to fit columns in trades the readability the alignment was bought for.
Accessibility
The table is a real table: <caption> names it, scope="col" associates headers, and scope="row" on the technique cell means a screen reader announces "weighted-press, learning, 5 of 5" rather than reading disembodied numbers. Units are inside the cell text (ms, kB, /5), so a value is never meaningful only by column position. Row separators use the hairline token, which sits above 1.5:1 against the background — visible as structure without competing with the figures.
Study next