Foundations

Typography

Apple's typographic system — from Display to Caption. Every size, weight, and spacing decision that gives interfaces their voice.

Type Scale

Twelve carefully calibrated levels — each optimized for its context. Sizes map directly to Apple's SF Pro optical sizing ranges.

The quick brown fox
Display
56px / 700 / −0.03em
Hero titles, landing pages
The quick brown fox jumps
Large Title
40px / 700 / −0.02em
Page titles, modal headers
The quick brown fox jumps over
Title 1
32px / 700 / −0.02em
Section headings
The quick brown fox jumps over the lazy dog
Title 2
26px / 700 / −0.01em
Card titles, subsections
The quick brown fox jumps over the lazy dog
Title 3
22px / 600 / 0em
Grouped list headers
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs.
Headline
17px / 600 / 0em
Emphasized body text, labels
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs. How vexingly quick daft zebras jump.
Body
17px / 400 / 0em
Primary reading text
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs. How vexingly quick daft zebras jump.
Callout
16px / 400 / 0em
Callout text, descriptions
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs. How vexingly quick daft zebras jump. The five boxing wizards jump quickly.
Subhead
15px / 400 / 0em
Secondary labels, subheadings
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs. How vexingly quick daft zebras jump. The five boxing wizards jump quickly. Sphinx of black quartz, judge my vow.
Footnote
13px / 400 / 0em
Notes, supplemental info
The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs. How vexingly quick daft zebras jump. The five boxing wizards jump quickly. Sphinx of black quartz, judge my vow. Bright vixens jump; dozy fowl quack.
Caption 1
12px / 400 / +0.01em
Image captions, timestamps
THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. PACK MY BOX WITH FIVE DOZEN LIQUOR JUGS. HOW VEXINGLY QUICK DAFT ZEBRAS JUMP. THE FIVE BOXING WIZARDS JUMP QUICKLY. SPHINX OF BLACK QUARTZ, JUDGE MY VOW.
Caption 2
11px / 400 / +0.01em
Labels, tags, badges

Font Weights

SF Pro exposes four distinct weights used across the system. Each carries semantic meaning — weight communicates emphasis before content is read.

Ag
Regular
400
Body, callout, captions
Ag
Medium
500
Active nav items, UI labels
Ag
Semibold
600
Headline, Title 3, buttons
Ag
Bold
700
Display, titles, impact
Weight ramp at 17px
400 The quick brown fox jumps over the lazy dog
500 The quick brown fox jumps over the lazy dog
600 The quick brown fox jumps over the lazy dog
700 The quick brown fox jumps over the lazy dog

Hierarchy in Practice

A real-world card demonstrating all four levels of the type hierarchy working in concert — from eyebrow label to metadata.

Design System

Building with Purpose

Typography creates hierarchy before a single word is read. Size, weight, and spacing work together to guide the eye through content in a natural, effortless flow.

Updated April 2025 · 5 min read
1
Eyebrow Label — Caption 2
12px, uppercase, +0.06em tracking, accent color. Establishes context before the title.
2
Title — Title 2
26px, 700, −0.01em. The dominant visual anchor — creates immediate recognition.
3
Body — Body
17px, 400, secondary color. The reading layer — comfortable at 1.6 line height.
4
Metadata — Footnote
13px, tertiary color. De-emphasized supplemental information — present but subordinate.

Line Length & Legibility

Optimal reading measure sits between 60–80 characters per line. Too narrow creates choppy rhythm; too wide loses the reader's place on return.

❌ Too Narrow (<40 chars)
Typography creates hierarchy before a single word is read. Each line break disrupts your flow unnecessarily.
✓ Optimal (60–80 chars)
Typography creates hierarchy before a single word is read. Size, weight, and spacing work together to guide the eye through content in a natural, effortless way that supports comprehension.
⚠ Too Wide (>90 chars)
Typography creates hierarchy before a single word is read. Size, weight, and spacing work together to guide the eye through content in a natural, effortless flow that feels comfortable and supports comprehension at long reading sessions.
Tip: Set max-width: 65ch or 672px on body text containers to enforce optimal measure.

Optical Sizing

SF Pro automatically adjusts letterform details based on point size. Display variants have finer strokes and tighter proportions; Text variants are optimized for readability at small sizes.

Display Context — Large Sizes (≥20px)
Clarity
At large sizes, SF Pro Display reduces inter-letter spacing aggressively (−0.03em) and uses finer stroke contrast. Characters have more optical nuance visible at scale.
Text Context — Small Sizes (≤20px)
Clarity, deference, and depth are the three primary principles of Apple's design language. These qualities inform every decision.
At text sizes, stroke contrast is reduced for even color on screen. Neutral tracking keeps characters from crowding at small sizes.
Letter-spacing guide
56–40px −0.03em to −0.02em
32–22px −0.02em to 0em
17–13px 0em
12–11px +0.01em

Code: Implementing the Scale

Production-ready CSS custom properties and a reusable React component for consuming the type system.

CSS
/* Typography Scale CSS Variables */
:root {
  /* Typeface */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display",
    "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SF Mono", "Fira Code", monospace;

  /* Type Scale */
  --text-display:     56px;   /* Hero, landing pages */
  --text-large-title: 40px;   /* Page titles */
  --text-title1:      32px;   /* Section headings */
  --text-title2:      26px;   /* Card titles */
  --text-title3:      22px;   /* Grouped list headers */
  --text-headline:    17px;   /* Bold emphasis (600) */
  --text-body:        17px;   /* Primary reading (400) */
  --text-callout:     16px;   /* Callout descriptions */
  --text-subhead:     15px;   /* Secondary labels */
  --text-footnote:    13px;   /* Supplemental notes */
  --text-caption:     12px;   /* Captions, timestamps */

  /* Font Weights */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* Line Heights */
  --leading-tight:   1.1;
  --leading-snug:    1.25;
  --leading-normal:  1.5;
  --leading-relaxed: 1.6;
}
TSX
import React from 'react';

type Variant =
  | 'display' | 'large-title' | 'title1' | 'title2'
  | 'title3'  | 'headline'    | 'body'   | 'callout'
  | 'subhead' | 'footnote'    | 'caption';

const variantStyles: Record<Variant, React.CSSProperties> = {
  'display':    { fontSize: '56px', fontWeight: 700, letterSpacing: '-0.03em', lineHeight: 1.05 },
  'large-title':{ fontSize: '40px', fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1.1  },
  'title1':     { fontSize: '32px', fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1.15 },
  'title2':     { fontSize: '26px', fontWeight: 700, letterSpacing: '-0.01em', lineHeight: 1.2  },
  'title3':     { fontSize: '22px', fontWeight: 600, letterSpacing: '0',       lineHeight: 1.25 },
  'headline':   { fontSize: '17px', fontWeight: 600, letterSpacing: '0',       lineHeight: 1.35 },
  'body':       { fontSize: '17px', fontWeight: 400, letterSpacing: '0',       lineHeight: 1.55 },
  'callout':    { fontSize: '16px', fontWeight: 400, letterSpacing: '0',       lineHeight: 1.55 },
  'subhead':    { fontSize: '15px', fontWeight: 400, letterSpacing: '0',       lineHeight: 1.55 },
  'footnote':   { fontSize: '13px', fontWeight: 400, letterSpacing: '0',       lineHeight: 1.55 },
  'caption':    { fontSize: '12px', fontWeight: 400, letterSpacing: '0.01em', lineHeight: 1.5  },
};

interface TypeTextProps {
  as?: keyof JSX.IntrinsicElements;
  variant?: Variant;
  color?: 'primary' | 'secondary' | 'tertiary' | 'accent';
  children: React.ReactNode;
  style?: React.CSSProperties;
  className?: string;
}

const TypeText = ({
  as: Tag = 'p',
  variant = 'body',
  color = 'primary',
  children,
  style,
  className,
}: TypeTextProps) => {
  const colorVar = {
    primary:   'var(--color-text-primary)',
    secondary: 'var(--color-text-secondary)',
    tertiary:  'var(--color-text-tertiary)',
    accent:    'var(--color-accent)',
  }[color];

  return (
    <Tag
      className={className}
      style={{
        fontFamily: 'var(--font-sans)',
        color: colorVar,
        margin: 0,
        ...variantStyles[variant],
        ...style,
      }}
    >
      {children}
    </Tag>
  );
};

export default TypeText;

Rules & Best Practices

Eight practical guidelines derived from Apple HIG. Each pair contrasts correct and incorrect application.

✓ Do
Use negative tracking on large sizes
Apply −0.02em to −0.03em letter-spacing on headlines above 32px. Large letterforms need tighter spacing to feel cohesive.
✕ Don't
Use more than 3 weight levels per view
Using Regular, Semibold, and Bold on one screen is enough contrast. Adding Medium and other weights creates visual noise without hierarchy benefit.
✓ Do
Limit body copy to 65ch width
Set max-width on reading containers to 65ch or 672px. This keeps lines in the optimal 60–80 character range for comfortable reading.
✕ Don't
Track uppercase text above 0.12em
Over-tracked uppercase labels lose legibility. Cap tracking at 0.08–0.10em for labels, and use it only on sizes 13px and below.
✓ Do
Use 1.5–1.65 line height for body
Body text at 17px reads best at 1.55–1.65 line height. Tight leading causes lines to crowd; loose leading disconnects paragraphs.
✕ Don't
Use font-size below 11px
Sub-11px text is inaccessible to most users. Apple's minimum is 11px (Caption 2). Anything smaller should be replaced with icons or visual cues.
✓ Do
Pair color and weight for emphasis
Use both a color shift (secondary → primary) and a weight increase (400 → 600) when emphasizing text. Either alone is often insufficient.
✕ Don't
Rely on italics for hierarchy
SF Pro italics are rarely used in Apple interfaces. Use weight and color instead. Reserve italics for truly editorial contexts like pull quotes.

Numbers & Data

Use tabular figures for data that must align vertically. SF Pro supports tabular-nums via font-feature-settings, ensuring digits share identical advance widths.

✕ Proportional Numbers
Item Value Change
Revenue$1,204,719+11.1%
Sessions8,871,001−4.7%
Conversion3.14%+0.3%
Avg Order$177.11+0.1%
✓ Tabular Numbers
Item Value Change
Revenue$1,204,719+11.1%
Sessions8,871,001−4.7%
Conversion3.14%+0.3%
Avg Order$177.11+0.1%
font-variant-numeric: tabular-nums; font-feature-settings: "tnum";

Practical Web Scale

Ready-to-use pixel and rem values for web implementations. All values align to the 8pt grid and SF Pro's optical sizing boundaries.

Role HIG Style Size Rem Weight Tracking Line-height Use Case
Hero Display 56px 3.5rem 700 −0.03em 1.05 Marketing hero
Page Title Large Title 40px 2.5rem 700 −0.02em 1.1 Page H1
Section Title 1 32px 2rem 700 −0.02em 1.15 Major H2
Card Title Title 2 26px 1.625rem 700 −0.01em 1.2 Card H3
Subsection Title 3 22px 1.375rem 600 0 1.25 Group header
Label Headline 17px 1.0625rem 600 0 1.35 Bold label
Body Body 17px 1.0625rem 400 0 1.55 Reading text
Description Callout 16px 1rem 400 0 1.55 UI descriptions
Secondary Subhead 15px 0.9375rem 400 0 1.55 Secondary text
Footnote Footnote 13px 0.8125rem 400 0 1.5 Notes, meta
Caption Caption 1 12px 0.75rem 400 +0.01em 1.5 Image captions
Micro Caption 2 11px 0.6875rem 400 +0.01em 1.45 Badges, tags