Foundations

Typography

39 typography tokens. The base theme sets text in the system UI font, so a new project starts with nothing to download; a brand swaps the family and keeps the scale. The fluid sizes below change with your window.

Type scale

  1. Display--font-size-displayclamp(2rem, 0.75rem + 5vw, 5rem) / 1.125

    Tokens first, then components

  2. H1 fluid--font-size-h1-fluidclamp(1.75rem, 0.75rem + 4vw, 4rem) / 1.125

    Getting started

  3. H2 fluid--font-size-h2-fluidclamp(1.625rem, 1rem + 2.5vw, 3rem) / 1.25

    Component library

  4. H3 fluid--font-size-h3-fluidclamp(1.5rem, 1rem + 2vw, 2.5rem) / 1.25

    Foundations

  5. H4--font-size-h424px / 32px

    Install the package

  6. H5--font-size-h520px / 24px

    Props

  7. Body--font-size-body18px / 28px

    Body text is sized for reading, so long passages stay comfortable without zooming in.

  8. Control--font-size-control16px / 24px

    Save changes

  9. Small--font-size-small14px / 20px

    Supporting text and table cells

  10. Label--font-size-small14px / 16px

    Email address

  11. Caption--font-size-caption12px / 16px

    Updated 30 September 2026

Tokens

Families

The base theme uses the system UI font for text, so nothing is downloaded, and JetBrains Mono for code.

TokenValue
--font-family-base-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
--font-family-heading-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
--font-family-mono'JetBrains Mono', monospace

Sizes

Display and H1 to H3 have fluid versions that scale with the viewport. Everything from H4 down is fixed.

TokenValue
--font-size-body18px
--font-size-control16px
--font-size-small14px
--font-size-caption12px
--font-size-h164px
--font-size-displayclamp(2rem, 0.75rem + 5vw, 5rem)
--font-size-h1-fluidclamp(1.75rem, 0.75rem + 4vw, 4rem)
--font-size-h248px
--font-size-h2-fluidclamp(1.625rem, 1rem + 2.5vw, 3rem)
--font-size-h332px
--font-size-h3-fluidclamp(1.5rem, 1rem + 2vw, 2.5rem)
--font-size-h424px
--font-size-h520px

Weights

Weights by role. Title is the bold one, for small titles in card and dialog headers (decisions/0010 in the library).

TokenValue
--font-weight-body400
--font-weight-heading600
--font-weight-label500
--font-weight-display600
--font-weight-title700
--font-weight-control500

Line heights

Fixed line heights sit on a 4px grid. Display and heading use a ratio, so they follow the fluid sizes.

TokenValue
--line-height-display1.125
--line-height-body28px
--line-height-control24px
--line-height-small20px
--line-height-caption16px
--line-height-h180px
--line-height-h260px
--line-height-h340px
--line-height-h432px
--line-height-h524px
--line-height-heading1.25
--line-height-label16px

Letter spacing

Tighter for headings, slightly open for labels, wide for uppercase.

TokenValue
--letter-spacing-heading-0.02em
--letter-spacing-subheading-0.01em
--letter-spacing-body0
--letter-spacing-label0.01em
--letter-spacing-wide0.08em

Usage

tsx
import { Heading } from '@amezquita/design-system/components/primitives/Heading'

// Visual size and document level are separate:
// a page title that looks like H2 but is the page's <h1>.
<Heading level={2} as="h1">Account settings</Heading>

/* In CSS, take size, weight and line-height as a set. */
.caption {
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-label);
  line-height: var(--line-height-caption);
}

Do and don’t

Do

  • Use Heading for headings, and set as when the outline level and the visual size differ.
  • Take size, weight and line height from the same step.
  • Keep running text at body size and within --size-container-text.

Don’t

  • Hardcode a line height. The linter rejects it in component CSS.
  • Skip heading levels to get a smaller look. Change level, keep the outline.
  • Set a font family in a component. A brand sets it once, in its tokens.