---
title: "How to align numbers in a table"
description: "Right-aligned is not aligned. Tabular figures, case-shifted parentheses, decimal alignment, a reserved sign column and rules that carry the arithmetic."
canonical: "https://lopifi.com/docs/guides/align-numbers-in-a-table"
---

# How to align numbers in a table

> Right-aligned is not aligned. Tabular figures, case-shifted parentheses, decimal alignment, a reserved sign column and rules that carry the arithmetic.

Source: https://lopifi.com/docs/guides/align-numbers-in-a-table
Part of: Lopifi — Planned: US GAAP books on autopilot, checked by a CPA (https://lopifi.com)

---

# How to align numbers in a table

<!-- description: Right-aligned is not aligned. Tabular figures, case-shifted parentheses, decimal alignment, a reserved sign column and rules that carry the arithmetic. -->

Right-aligned isn't aligned. Making a column of money read as a column takes four settings and one rule line. That's the difference between a finance product and an admin template with a dollar sign.

---

## 1. Turn on tabular figures

Most typefaces set numerals proportionally by default, so a `1` is narrower than a `0`. That's right for prose and wrong for a column, where the digits in row four stop sitting above the digits in row five.

```css
.numeric {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
```

Inter has `tnum`, as does almost every UI typeface worth using. Turn it on for any numeral a reader might compare with another. In a finance interface that's all of them, including dates, reference numbers and quantities.

## 2. Turn on case-shifted parentheses

`case` (`cv##` in some fonts) shifts brackets, dashes and other punctuation up so they sit optically centered on lining figures instead of lowercase text. Without it, the parentheses in `(1,234.00)` hang slightly low.

```css
font-feature-settings: "tnum" 1, "case" 1;
```

Use both features on anything numeric. It's the cheapest credibility gain in a financial interface.

## 3. Align on the decimal point, not the right edge

Right alignment only works because fixed decimal places make it equivalent to decimal alignment. So the real rule is:

> Fixed decimals throughout. `$1,200.00`, never `$1,200`.

`Intl` does this by default. The bug comes from someone trimming trailing zeros to "clean up" the column. Once one value has two decimals and another has none, right alignment stops aligning anything.

When a column really does mix scales, like a rate at three decimals beside an amount at two, align on the decimal separator with a grid instead of hoping padding holds.

## 4. Reserve the sign column

A column mixing `1,234.00` and `(1,234.00)` loses its alignment to the closing paren. Reserve the slot on both sides. The three ways to do it are ranked in [negative numbers in a financial table](https://lopifi.com/md/docs/guides/negative-numbers-in-financial-tables#the-alignment-problem).

## 5. Rule lines carry the arithmetic

A single rule above a subtotal, a double rule under a total. Four centuries of convention, two CSS declarations:

```tsx
<Rule variant="subtotal" />   // border-top: 1px solid
<Rule variant="total" />      // border-bottom: 3px double
```

The rule **spans the numeric column only**, not the label column. That's what makes it read as accounting instead of a divider. In a multi-period statement it spans each period column separately and leaves the gutters unruled. Never put a rule and a background fill on the same row. Pick one, and pick the rule.

## 6. Do not stripe the rows

Zebra striping is what you reach for when the numbers aren't aligned. Fix the alignment and the stripes become noise. Tabular figures do the work, and a hairline row separator handles the rest at any density.

## 7. Never animate a value the reader might trust

A number counting up from zero is unreadable while it animates, and a reader who glances mid-tween walks away with a figure that was never true. Crossfade a changed value if you need to signal the change. Never interpolate it.

---

## Where this is implemented

- [`Rule`](/components/rule): ten lines of code, the highest credibility-per-byte component here
- [`StatementTable`](/components/statement-table): hierarchy, period columns and rules together
- [`LedgerTable`](/components/ledger-table): debit and credit as two aligned columns
- [`TransactionTable`](/components/transaction-table): virtualized, and still aligned at 240 rows
- [Tables, running](/showcase/tables): with a density toggle, the real test of an alignment claim
- [Typography](https://lopifi.com/md/docs/foundations/typography): the type system these features live in
- [Numerics](https://lopifi.com/md/docs/foundations/numerics#rule-lines): rule lines, in full
