Notes on the typography of this site

Every decision here is reversible, which is why each one is written down.

Updated:3 min read#typography#craft#meta

This piece is also the template’s kitchen sink: it exercises every prose component the theme ships, so if something is broken it is broken here first.

The body is a serif, and that is the whole design

A serif body face is unusual on the web and almost unheard of in a portfolio template. It is the single decision everything else follows from.

A sans-serif says interface. A serif says document. This is a document.

the argument, compressed

The practical consequence is that the sans has to be demoted somewhere, and the place it goes is the chrome — navigation, dates, tags, buttons. That split is strict:

The measure is 42rem and it is not negotiable

At the 18px prose size that lands around 74 characters per line, inside the 60–80 band that legibility research and four centuries of typesetting practice both arrive at.

The tokens live in one place, and the shell width is derived from them rather than chosen:

export const layout = {
  sidebar: '19rem',
  reading: '42rem',
  contentPad: '3rem',
  // 19 + 42 + 3 + 3 — recompute this if you change any of the three above.
  shellMax: '67rem',
};

Numerals do two different jobs

Old-style figures in prose, lining figures in the chrome. This is set once on body and overridden on the meta line:

body {
  font-variant-numeric: oldstyle-nums;
}

.meta-line,
.archive-date {
  font-variant-numeric: lining-nums tabular-nums;
}

Old-style numerals have ascenders and descenders and sit in a line of lowercase without interrupting it — which is what you want when a year appears mid-sentence, like 1971. Lining numerals are uniform cap height, which is what you want in a column where the dates have to align.

The tabular-nums half is doing real structural work in the archive: fixed-width digits are the only reason every row’s title column starts at the same horizontal position.

Inline things

Inline code like --layout-reading is set in the mono face at 0.9em — a relative size, so it tracks whatever it is sitting in rather than fixing itself to the prose size and looking wrong inside a callout.

A link inside prose is the one place the accent appears as text you are meant to click, which is why prose links are green and every other link on the site is not. A page where the date, the tag and the title were all accented would be a page of green.

A blockquote is distinct from a pull-quote, and this template treats them as different objects. This one stays inside the measure and takes a left rule; a pull-quote breaks out of the column and is set in italic display size.

Lists get a faint marker so the numbers do not compete with the text:

  1. Old-style numerals in prose.
  2. Lining, tabular numerals in the chrome.
  3. Never both in one column.

That is everything. If you are reading this in a fork and something above renders wrong, the component is in src/components/prose/ and the styling is in the @layer components block of global.css.