Skip to main content
BM

Typography

Text in one of the type scale's looks, with the heading level chosen separately.

View source on GitHub

A design system built from tokens up.

Body text sets the reading size. Every size, weight and line height comes from a token.

Last updated October 2026.

TypographyExample.tsx
import { Typography } from "@/components/Typography";

export function TypographyExample() {
  return (
    <>
      <Typography variant="lead">A design system built from tokens up.</Typography>
      <Typography>
        Body text sets the reading size. Every size, weight and line height comes from a token.
      </Typography>
      <Typography variant="small" tone="muted">
        Last updated October 2026.
      </Typography>
    </>
  );
}

Examples

Type scale

Display, 48px

Heading 1, 40px

Heading 2, 32px

Heading 3, 24px

Heading 4, 20px

Heading 5, 16px

Heading 6, 14px

Lead, 20px

Body, 16px

Small, 14px

Label, 12px

Code, inherits size

Level and look are separate

An h4 with the h2 look

An h5 with the label look

Look from the element

An h4, with the h4 look

A code element, with the code lookA small element, with the small look

Lead text with strong text inside, at the lead's size

Tones

Default

Muted

Subtle

Accent

Accent 2

Success: saved

Warning: unsaved changes

Error: the email is missing

Measure

With measure: A comfortable line holds about 45 to 75 characters, so the eye finds the start of the next line without effort. Longer lines tire readers, and shorter ones break the rhythm of reading. The measure caps this paragraph at about 65 characters, whatever its size.

Without measure: A comfortable line holds about 45 to 75 characters, so the eye finds the start of the next line without effort. Longer lines tire readers, and shorter ones break the rhythm of reading. The measure caps this paragraph at about 65 characters, whatever its size.

Inline text

Press Tab to reach main. Web Content Accessibility Guidelines (WCAG) 2.2 was published on . Its reflow criterion asks for content without loss of information or functionality.

Customized with component tokens

Custom label

CSS
.customLabel {
  --component-typography-label-tracking: var(--type-tracking-body);
  --component-typography-label-font-family: var(--type-family-body);
}

Props

Any native prop not listed here goes to the root element unchanged.

Without variant, the look comes from the element: h1–h6 take the variant of the same name; code, kbd and samp take code; small takes small; span, strong, em, mark, s, abbr, cite, q and time take inherit; every other element takes body. An explicit variant wins. The heading level, and so the role, comes only from as. inherit and code set no size, so on h1–h6 the plain heading's size for that level shows through.

Typography props
PropTypeDefaultDescription
as"p" | "span" | "div" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "label" | "legend" | "strong" | "em" | "small" | "mark" | "s" | "code" | "kbd" | "samp" | "abbr" | "cite" | "q" | "time" | "blockquote" | "figcaption" | "caption" | "li" | "dt" | "dd""p"The element, and so the heading level and role.
variant"display" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "lead" | "body" | "small" | "label" | "code" | "inherit"from the elementThe look only: family, size, weight, line height and tracking.
tone"default" | "muted" | "subtle" | "accent" | "accent-2" | "success" | "warning" | "error"inheritedText color, each from its own component token.
measurebooleanfalseCaps the line length at about 65 characters.

Component tokens

Typography component tokens
TokenCopyDescriptionAliasesLightDarkPreview
--component-typography-display-font-familyDisplay text font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-display-font-sizeDisplay text size.type.size.display3remfrom type.font-size.4xl3remfrom type.font-size.4xl
--component-typography-display-font-weightDisplay text weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-display-line-heightDisplay text line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-display-trackingDisplay text letter spacing.type.tracking.display-0.02emfrom type.letter-spacing.neg-2-0.02emfrom type.letter-spacing.neg-2
--component-typography-h1-font-familyHeading 1 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h1-font-sizeHeading 1 look size.type.size.h12.5remfrom type.font-size.3xl2.5remfrom type.font-size.3xl
--component-typography-h1-font-weightHeading 1 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h1-line-heightHeading 1 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h1-trackingHeading 1 look letter spacing.type.tracking.display-0.02emfrom type.letter-spacing.neg-2-0.02emfrom type.letter-spacing.neg-2
--component-typography-h2-font-familyHeading 2 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h2-font-sizeHeading 2 look size.type.size.h22remfrom type.font-size.2xl2remfrom type.font-size.2xl
--component-typography-h2-font-weightHeading 2 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h2-line-heightHeading 2 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h2-trackingHeading 2 look letter spacing.type.tracking.display-0.02emfrom type.letter-spacing.neg-2-0.02emfrom type.letter-spacing.neg-2
--component-typography-h3-font-familyHeading 3 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h3-font-sizeHeading 3 look size.type.size.h31.5remfrom type.font-size.xl1.5remfrom type.font-size.xl
--component-typography-h3-font-weightHeading 3 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h3-line-heightHeading 3 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h3-trackingHeading 3 look letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-h4-font-familyHeading 4 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h4-font-sizeHeading 4 look size.type.size.h41.25remfrom type.font-size.lg1.25remfrom type.font-size.lg
--component-typography-h4-font-weightHeading 4 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h4-line-heightHeading 4 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h4-trackingHeading 4 look letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-h5-font-familyHeading 5 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h5-font-sizeHeading 5 look size.type.size.h51remfrom type.font-size.md1remfrom type.font-size.md
--component-typography-h5-font-weightHeading 5 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h5-line-heightHeading 5 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h5-trackingHeading 5 look letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-h6-font-familyHeading 6 look font.type.family.heading'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display'Space Grotesk Variable', 'Space Grotesk Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.display
--component-typography-h6-font-sizeHeading 6 look size.type.size.h60.875remfrom type.font-size.sm0.875remfrom type.font-size.sm
--component-typography-h6-font-weightHeading 6 look weight.type.weight.heading700from type.font-weight.700700from type.font-weight.700
--component-typography-h6-line-heightHeading 6 look line height.type.leading.heading1.2from type.line-height.tight1.2from type.line-height.tight
--component-typography-h6-trackingHeading 6 look letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-lead-font-familyLead text font.type.family.body'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans
--component-typography-lead-font-sizeLead text size.type.size.lead1.25remfrom type.font-size.lg1.25remfrom type.font-size.lg
--component-typography-lead-font-weightLead text weight.type.weight.body400from type.font-weight.400400from type.font-weight.400
--component-typography-lead-line-heightLead text line height.type.leading.body1.6from type.line-height.normal1.6from type.line-height.normal
--component-typography-lead-trackingLead text letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-body-font-familyBody text font.type.family.body'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans
--component-typography-body-font-sizeBody text size.type.size.body1remfrom type.font-size.md1remfrom type.font-size.md
--component-typography-body-font-weightBody text weight.type.weight.body400from type.font-weight.400400from type.font-weight.400
--component-typography-body-line-heightBody text line height.type.leading.body1.6from type.line-height.normal1.6from type.line-height.normal
--component-typography-body-trackingBody text letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-small-font-familySmall text font.type.family.body'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans'Inter Variable', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, sans-seriffrom type.font-stack.sans
--component-typography-small-font-sizeSmall text size.type.size.small0.875remfrom type.font-size.sm0.875remfrom type.font-size.sm
--component-typography-small-font-weightSmall text weight.type.weight.body400from type.font-weight.400400from type.font-weight.400
--component-typography-small-line-heightSmall text line height.type.leading.body1.6from type.line-height.normal1.6from type.line-height.normal
--component-typography-small-trackingSmall text letter spacing.type.tracking.body0emfrom type.letter-spacing.00emfrom type.letter-spacing.0
--component-typography-label-font-familyLabel text font.type.family.label'Fira Code Variable', 'Fira Code Fallback', ui-monospace, SFMono-Regular, Menlo, Consolas, monospacefrom type.font-stack.mono'Fira Code Variable', 'Fira Code Fallback', ui-monospace, SFMono-Regular, Menlo, Consolas, monospacefrom type.font-stack.mono
--component-typography-label-font-sizeLabel text size.type.size.label0.75remfrom type.font-size.xs0.75remfrom type.font-size.xs
--component-typography-label-font-weightLabel text weight.type.weight.body400from type.font-weight.400400from type.font-weight.400
--component-typography-label-line-heightLabel text line height.type.leading.body1.6from type.line-height.normal1.6from type.line-height.normal
--component-typography-label-trackingLabel text letter spacing.type.tracking.label0.16emfrom type.letter-spacing.160.16emfrom type.letter-spacing.16
--component-typography-code-font-familyCode font. Size, weight and line height come from the surrounding text.type.family.code'Fira Code Variable', 'Fira Code Fallback', ui-monospace, SFMono-Regular, Menlo, Consolas, monospacefrom type.font-stack.mono'Fira Code Variable', 'Fira Code Fallback', ui-monospace, SFMono-Regular, Menlo, Consolas, monospacefrom type.font-stack.mono
--component-typography-tone-default-colorDefault text color.color.text.default#17202bfrom color.gray.900#fffffffrom color.gray.0
--component-typography-tone-muted-colorMuted text color.color.text.muted#455464from color.gray.700#e6ecf3from color.slate.100
--component-typography-tone-subtle-colorSubtle text color. Not checked against glass.color.text.subtle#5d6876from color.gray.600#d3dce6from color.slate.200
--component-typography-tone-accent-colorAccent text color. Not checked against glass.color.accent.text#005f7bfrom color.cyan.700#54d8f4from color.cyan.300
--component-typography-tone-accent-2-colorSecond accent (violet) text color. Not checked against glass.color.accent-2.text#5b3fa6from color.violet.600#c9b8f5from color.violet.300
--component-typography-tone-success-colorSuccess text color. Never the only cue: the wording must state the status (WCAG 1.4.1). Not checked against glass.color.success.text#1e6b45from color.green.700#8fd6a8from color.green.300
--component-typography-tone-warning-colorWarning text color. Never the only cue: the wording must state the status (WCAG 1.4.1). Not checked against glass.color.warning.text#94440afrom color.orange.700#f7ad7cfrom color.orange.300
--component-typography-tone-error-colorError text color. Never the only cue: the wording must state the status (WCAG 1.4.1). Not checked against glass.color.error.text#b3261efrom color.red.700#f4a097from color.red.300
--component-typography-measureMaximum line length with `measure`: about 65 characters in the element's own font.type.measure.text65chfrom type.line-length.6565chfrom type.line-length.65No preview

Accessibility

  • The level comes from as and the look from variant, so keep the page outline logical whatever the size.
  • success, warning and error carry meaning, so the wording must state the status on its own (WCAG 1.4.1); the color is an extra.
  • On glass, use only the default or muted tone: the others aren't contrast-checked there.
  • Don't set tone on text inside a Link, or on mark: those pairings aren't contrast-checked, and a recolored link may lose what sets it apart.
  • The label look's uppercase is CSS only, so write the source text in normal case: some screen readers spell out words typed in capitals.
  • abbr's title isn't reliably announced or shown, so spell the abbreviation out on first use.
  • Sizes are in rem, so text follows the browser's text size and zoom.
  • Long words break instead of overflowing in block layout, so nothing scrolls sideways at 320 CSS px (WCAG 1.4.10). In a flex or grid item, also let it shrink (min-inline-size: 0).