Skip to content

Proportion system

Typography

Nine type steps, each a half golden ratio above the last, with leading and tracking derived from the same ratio.

Typefaces

Satoshi sets headings and the wordmark. Inter sets everything else. There are no other typefaces. Satoshi ships in two weights, 500 and 700, and Inter is used at 400 and 600.

Formula

A full golden step per level is too large for an interface: from a 16 px body it jumps to 26 px and then 42 px. Half a step keeps the ratio and gives usable sizes. With the body as step 0:

size(n)=round⁡ ⁣(16 φ n/2) px\text{size}(n) = \operatorname{round}\!\left(16\,\varphi^{\,n/2}\right)\text{ px}

Two steps up is one golden ratio, so every second step has the same relation as neighbouring Fibonacci numbers. Space between lines gets looser as type gets smaller and tightens towards solid as type grows. The leading is a multiple of the size:

leading(n)=1+φ−(1+n/2)\text{leading}(n) = 1 + \varphi^{-(1+n/2)}

At the body size this is exactly phi, 1.618. As n grows it falls towards 1. Large type is also tracked in slightly, and small type out:

tracking(n)=− φ n/2−189 em\text{tracking}(n) = -\,\frac{\varphi^{\,n/2}-1}{89}\ \text{em}

89 is a Fibonacci number, and it keeps the largest display size at about minus 0.036 em.

The scale

Each row is set in its real size, leading and tracking.

text-s668px · 1.146 · -0.0364emDisplay · Satoshi

Stars at 21 lux

text-s553px · 1.186 · -0.0262emHeading 1 · Satoshi

Stars at 21 lux

text-s442px · 1.236 · -0.0182emHeading 2 · Satoshi

Stars at 21 lux

text-s333px · 1.3 · -0.0119emHeading 3 · Satoshi

Stars at 21 lux

text-s226px · 1.382 · -0.0069emHeading 4 · Satoshi

Stars at 21 lux

text-s120px · 1.486 · -0.0031emLead, subtitle · Inter

Stars at 21 lux

text-s016px · 1.618 · 0.0000emBody · Inter

Stars at 21 lux

text-s-113px · 1.786 · 0.0024emCaption, helper text · Inter

Stars at 21 lux

text-s-210px · 2 · 0.0043emOverline, legal · Inter

Stars at 21 lux

Computed values

Raw is 16 x phi^(n/2). Size is the nearest whole pixel and is what scale.css holds; the build compares the two.
nRawSizeLeadingLine boxTracking
-29.88910220.00.0043em
-112.578131.78623.20.0024em
016.000161.61825.90.0000em
120.352201.48629.7-0.0031em
225.889261.38235.9-0.0069em
332.931331.342.9-0.0119em
441.889421.23651.9-0.0182em
553.283531.18662.9-0.0262em
667.777681.14677.9-0.0364em

Rules

  1. Use only these steps. Body copy is step 0. Do not pick an in-between size.
  2. Body is Inter, headings are Satoshi. Steps 2 and up are headings and use Satoshi 700. Steps below 2 are Inter.
  3. Leading and tracking come with the step. Never set them independently; use the pair in the token.
  4. A heading is at least two steps above the text it introduces. That keeps the golden relation between heading and body.
  5. Measure is 76 characters. That is the upper end of comfortable reading. Cap prose with the measure token, in characters, never in pixels.
  6. Respect platform text scaling. Sizes are multiples of the 16 px unit and follow the user's setting, in rem on the web and sp in Flutter. Layouts must survive 200 percent.

Usage

html
<!-- Tailwind: size, leading and tracking come together --><h2 class="font-heading text-s4">Tonight’s sky</h2><p class="text-s0">Cloud cover is 12 percent after midnight.</p>
css
/* the equivalent plain CSS */h2 {  font-size: var(--text-s4);  line-height: var(--text-s4--line-height);  letter-spacing: var(--text-s4--letter-spacing);}
scale.css
@theme static {  --text-s-2: calc(var(--u) * 0.625);  --text-s-2--line-height: 2;  --text-s-2--letter-spacing: 0.0043em;  --text-s-1: calc(var(--u) * 0.8125);  --text-s-1--line-height: 1.786;  --text-s-1--letter-spacing: 0.0024em;  --text-s0: calc(var(--u) * 1);  --text-s0--line-height: 1.618;  --text-s0--letter-spacing: 0em;  --text-s1: calc(var(--u) * 1.25);  --text-s1--line-height: 1.486;  --text-s1--letter-spacing: -0.0031em;  --text-s2: calc(var(--u) * 1.625);  --text-s2--line-height: 1.382;  --text-s2--letter-spacing: -0.0069em;  --text-s3: calc(var(--u) * 2.0625);  --text-s3--line-height: 1.3;  --text-s3--letter-spacing: -0.0119em;  --text-s4: calc(var(--u) * 2.625);  --text-s4--line-height: 1.236;  --text-s4--letter-spacing: -0.0182em;  --text-s5: calc(var(--u) * 3.3125);  --text-s5--line-height: 1.186;  --text-s5--letter-spacing: -0.0262em;  --text-s6: calc(var(--u) * 4.25);  --text-s6--line-height: 1.146;  --text-s6--letter-spacing: -0.0364em;}