QUOIN FORME № 1.1 — LOCKED UP PITCH 8px MIT · NO DEPENDENCIES · 26 kB measuring…

Specimen — a page like any other. A fluid type scale, a spacing scale in round numbers, leading set as a ratio. Nothing on it is a mistake.

The letters were never centred

Every font reserves a band of empty space above its capitals and another below its baseline for descenders, and those two bands are almost never the same size.

The browser measures the font's box, subtracts it from the line height, and splits what is left equally. So it centres the box perfectly. The letters inside that box were never centred.

Print solved this with the baseline grid: one invisible ruler down the page, and every line of text in every column seated on it. It has existed since metal type and it is a checkbox in InDesign.

There is no number you can write down once.

IT PUTS A WEB PAGE
ON A BASELINE GRID

A quoin is the wedge a printer hammers into the chase to lock the type so nothing shifts on the press. Same job.

Print has had this since metal type. The web has never had it at all.

Every measurement on this sheet is taken in your browser, on the fonts your browser resolved.

I

THE DEFECT

fig. 1 — the line box, dimensioned

Hxp

box top · half-leading cap height BASELINE — where it must land

|← ascent 0.727emdescent 0.273em →|

The browser centres the box. Nothing centres the letters. The two bands are never equal, so the baseline lands where the typeface's asymmetry puts it.

The web has never had one, because line-height centres text in its box rather than seating it on a line, so the baseline lands wherever a particular typeface's asymmetry puts it. There is no number you can write down once.

RHYTHM

Every vertical distance a whole number of grid rows. CSS gives you this exactly.

PHASE

The first baseline inside each box landing on one. CSS gives you nothing.

So: CSS for the rhythm, this for the phase.

II

THE SURVEY

212 measured · 152 scored · 1280×900 · half-pixel tolerance
CATEGORY SITES 8PX GRID RHYTHM DRIFTS
Institutions932.0%2.2%22
Type foundries1531.9%3.7%21
Academic630.9%12.6%34.5
Design systems2730.8%29.5%21
Documentation3929.3%20.9%22
Studios1125.7%8.1%28
Editorial2025.0%18.8%46
Products2525.0%25.4%43
III

MOVE THE GRID TO THE DESIGN

npx quoin fit --design design.json · three families · 76ms

Everything above is remedial. It measures a page that is off the grid and pushes each block into place, and what you get back is a list of pixel corrections that describe one arrangement of line breaks. There is a better answer, and it does not ask you to change a single size.

Trim the boxes. Under text-box-trim: trim-both with text-box-edge: cap alphabetic, a block starts at its cap height and ends at its baseline, so the distance from one baseline to the next across a block boundary is

(lines − 1) × leading + space + cap

lines is the only term that changes with the viewport, and it is multiplied by a leading that is already a whole number of rows. So modulo the pitch what is left is space + cap, and every term in that belongs to one block by itself. Nothing relates one size to another. The sizes are free.

So a design keeps every size it asked for. The leading is snapped to the nearest whole number of rows, which is the one thing that moves and is the same thing InDesign moves when you tick the box. The space before each block is then solved to close that block's own cap height.

The grid is not asking you to accept type that looks different. It is asking how many sizes you actually needed.

IV

WHERE A CORRECTION HOLDS

seated at 1280 · carried to 375

100%when only the line breaks moved

0%when a media query changed a container's padding by thirteen pixels

Corrections survive reflow and do not survive a layout change, and every real site has one. Snapping every leading to whole rows means an extra line adds a whole number of rows and nothing shifts.

AND IT CHECKS THE STYLESHEET IT GIVES YOU

Pointed at five design system homepages, four reproduced the seating from the exported CSS alone. Material Design 3 went from 123 of 123 with the script to 18 of 123 with the stylesheet: nine line-height declarations lost the cascade to Angular's four-component scoped selectors.

So the export applies itself, measures every declaration, and adds !important to exactly the ones that lost.

WHY AN EXTENSION, NOT A PASTE-YOUR-URL BOX

A page's Content-Security-Policy governs script tags injected from outside, and a hosted service has no other way in. The two most famous URLs anyone would paste are the two it could not measure.

ROUTE IN STRIPE GITHUB KLIM LINEAR
A <script> tag, which a hosted service must usenonoyesyes
chrome.scripting, which the extension usesyesyesyesyes
V

FOUND BY BUILDING IT

all three reproducible · raw output committed

Cap height travels now

Both readings are called cap height and only one of them is portable

Canvas reports the drawn glyph: Chromium and WebKit hinted onto the pixel grid, Firefox as a scaled outline. CSS text-box-edge: cap reports the font's own sCapHeight.

font table
130 / 130
canvas
90 / 130

A generic keyword is not a font

fontBoundingBox agrees exactly, and the exceptions are not exceptions

Across three engines it agreed to the pixel for every font loaded from the same bytes. It disagreed on monospace and system-ui, which are the two rows where the engines resolved different typefaces.

same font
0.04px
monospace
27.16px
system-ui
14.14px

Found in the discard pile

WebKit does not apply automatic optical sizing

Two fonts kept failing a validity check, and they were the only two in the corpus with an opsz axis. Set font-optical-sizing: none and all three agree to 0.03px.

Inter, Chromium & Firefox
460.88
Inter, WebKit
483.59
VI

SIX WAYS IN

no dependencies · Playwright only where a browser is driven

Fit a design

npx quoin fit --design design.json

Keeps every size, snaps the leading, solves the spacing. Name each family's font file and it never opens a browser: three families in 76ms, which is what makes it usable in a build.

Fit a site you already have

npx quoin fit \
  --from https://example.com

Reads the design off the rendered page, groups every block by what it actually resolved to, and fits that. Most people have a site rather than a design file.

Measure and correct

npx quoin check \
  https://example.com
npx quoin seat \
  https://example.com \
  -o baseline.css

For a page that cannot be rebuilt. --min 90 exits non-zero, and the GitHub Action gates on a committed baseline.

On the page in front of you

quoin.check()
quoin.seat()
quoin.css()

Paste the bundle into any console, or install the extension and press a button. Both reach pages a hosted service cannot.

In your build

npm install quoin

fitScale, inferDesign, verifyGrid, verifyRhythm, seatPage. ESM, CJS and types, no dependencies.

For an agent

cat design.json | npx quoin fit --design - --json

Takes the shape you already have, whether that is a Figma export or a flat token file. Every error names the entry it is about, because an agent cannot ask a follow-up question.