Files
agents/plugins/ui-design/skills/visual-design-foundations/references/typography-systems.md
Seth Hobson 1e54d186fe feat(ui-design): add comprehensive UI/UX design plugin v1.0.0
New plugin covering mobile (iOS, Android, React Native) and web
applications with modern design patterns, accessibility, and design systems.

Components:
- 9 skills: design-system-patterns, accessibility-compliance, responsive-design,
  mobile-ios-design, mobile-android-design, react-native-design,
  web-component-design, interaction-design, visual-design-foundations
- 4 commands: design-review, create-component, accessibility-audit, design-system-setup
- 3 agents: ui-designer, accessibility-expert, design-system-architect

Marketplace updated:
- Version bumped to 1.3.4
- 102 agents (+3), 116 skills (+9)
2026-01-19 16:22:13 -05:00

8.7 KiB

Typography Systems Reference

Type Scale Construction

Modular Scale

A modular scale creates harmonious relationships between font sizes using a mathematical ratio.

// Common ratios
const RATIOS = {
  minorSecond: 1.067,    // 16:15
  majorSecond: 1.125,    // 9:8
  minorThird: 1.2,       // 6:5
  majorThird: 1.25,      // 5:4
  perfectFourth: 1.333,  // 4:3
  augmentedFourth: 1.414, // √2
  perfectFifth: 1.5,     // 3:2
  goldenRatio: 1.618,    // φ
};

function generateScale(baseSize: number, ratio: number, steps: number): number[] {
  const scale: number[] = [];
  for (let i = -2; i <= steps; i++) {
    scale.push(Math.round(baseSize * Math.pow(ratio, i) * 100) / 100);
  }
  return scale;
}

// Generate a scale with 16px base and perfect fourth ratio
const typeScale = generateScale(16, RATIOS.perfectFourth, 6);
// Result: [9, 12, 16, 21.33, 28.43, 37.9, 50.52, 67.34, 89.76]

CSS Custom Properties

:root {
  /* Base scale using perfect fourth (1.333) */
  --font-size-2xs: 0.563rem;  /* ~9px */
  --font-size-xs: 0.75rem;    /* 12px */
  --font-size-sm: 0.875rem;   /* 14px */
  --font-size-base: 1rem;     /* 16px */
  --font-size-md: 1.125rem;   /* 18px */
  --font-size-lg: 1.333rem;   /* ~21px */
  --font-size-xl: 1.5rem;     /* 24px */
  --font-size-2xl: 1.777rem;  /* ~28px */
  --font-size-3xl: 2.369rem;  /* ~38px */
  --font-size-4xl: 3.157rem;  /* ~50px */
  --font-size-5xl: 4.209rem;  /* ~67px */

  /* Font weights */
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  /* Line heights */
  --line-height-tight: 1.1;
  --line-height-snug: 1.25;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.625;
  --line-height-loose: 2;

  /* Letter spacing */
  --letter-spacing-tighter: -0.05em;
  --letter-spacing-tight: -0.025em;
  --letter-spacing-normal: 0;
  --letter-spacing-wide: 0.025em;
  --letter-spacing-wider: 0.05em;
  --letter-spacing-widest: 0.1em;
}

Font Loading Strategies

FOUT Prevention

/* Use font-display to control loading behavior */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap; /* Show fallback immediately, swap when loaded */
}

/* Optional: size-adjust for better fallback matching */
@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial');
  size-adjust: 107%; /* Adjust to match Inter metrics */
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}

body {
  font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;
}

Preloading Critical Fonts

<head>
  <!-- Preload critical fonts -->
  <link
    rel="preload"
    href="/fonts/Inter-Variable.woff2"
    as="font"
    type="font/woff2"
    crossorigin
  />
</head>

Variable Fonts

/* Variable font with weight and width axes */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 75% 125%;
}

/* Use font-variation-settings for fine control */
.custom-weight {
  font-variation-settings: 'wght' 450, 'wdth' 95;
}

/* Or use standard properties */
.semi-expanded {
  font-weight: 550;
  font-stretch: 110%;
}

Responsive Typography

Fluid Type Scale

/* Using clamp() for responsive sizing */
h1 {
  /* min: 32px, preferred: 5vw + 16px, max: 64px */
  font-size: clamp(2rem, 5vw + 1rem, 4rem);
  line-height: 1.1;
}

h2 {
  font-size: clamp(1.5rem, 3vw + 0.5rem, 2.5rem);
  line-height: 1.2;
}

p {
  font-size: clamp(1rem, 1vw + 0.75rem, 1.25rem);
  line-height: 1.6;
}

/* Fluid line height */
.fluid-text {
  --min-line-height: 1.3;
  --max-line-height: 1.6;
  --min-vw: 320;
  --max-vw: 1200;

  line-height: calc(
    var(--min-line-height) +
    (var(--max-line-height) - var(--min-line-height)) *
    ((100vw - var(--min-vw) * 1px) / (var(--max-vw) - var(--min-vw)))
  );
}

Viewport-Based Scaling

// Tailwind config for responsive type
module.exports = {
  theme: {
    fontSize: {
      xs: ['0.75rem', { lineHeight: '1rem' }],
      sm: ['0.875rem', { lineHeight: '1.25rem' }],
      base: ['1rem', { lineHeight: '1.5rem' }],
      lg: ['1.125rem', { lineHeight: '1.75rem' }],
      xl: ['1.25rem', { lineHeight: '1.75rem' }],
      '2xl': ['1.5rem', { lineHeight: '2rem' }],
      '3xl': ['1.875rem', { lineHeight: '2.25rem' }],
      '4xl': ['2.25rem', { lineHeight: '2.5rem' }],
      '5xl': ['3rem', { lineHeight: '1' }],
    },
  },
};

// Component with responsive classes
function Heading({ children }) {
  return (
    <h1 className="text-3xl md:text-4xl lg:text-5xl font-bold leading-tight">
      {children}
    </h1>
  );
}

Readability Guidelines

Optimal Line Length

/* Optimal reading width: 45-75 characters */
.prose {
  max-width: 65ch; /* ~65 characters */
}

/* Narrower for callouts */
.callout {
  max-width: 50ch;
}

/* Wider for code blocks */
pre {
  max-width: 80ch;
}

Vertical Rhythm

/* Establish baseline grid */
:root {
  --baseline: 1.5rem; /* 24px at 16px base */
}

/* All margins should be multiples of baseline */
h1 {
  font-size: 2.5rem;
  line-height: calc(var(--baseline) * 2);
  margin-top: calc(var(--baseline) * 2);
  margin-bottom: var(--baseline);
}

h2 {
  font-size: 2rem;
  line-height: calc(var(--baseline) * 1.5);
  margin-top: calc(var(--baseline) * 1.5);
  margin-bottom: calc(var(--baseline) * 0.5);
}

p {
  font-size: 1rem;
  line-height: var(--baseline);
  margin-bottom: var(--baseline);
}

Text Wrapping

/* Prevent orphans and widows */
p {
  text-wrap: pretty; /* Experimental: improves line breaks */
  widows: 3;
  orphans: 3;
}

/* Balance headings */
h1, h2, h3 {
  text-wrap: balance;
}

/* Prevent breaking in specific elements */
.no-wrap {
  white-space: nowrap;
}

/* Hyphenation for justified text */
.justified {
  text-align: justify;
  hyphens: auto;
  -webkit-hyphens: auto;
}

Font Pairing Guidelines

Contrast Pairings

/* Serif heading + Sans body */
:root {
  --font-heading: 'Playfair Display', Georgia, serif;
  --font-body: 'Source Sans Pro', -apple-system, sans-serif;
}

/* Geometric heading + Humanist body */
:root {
  --font-heading: 'Space Grotesk', sans-serif;
  --font-body: 'IBM Plex Sans', sans-serif;
}

/* Modern sans heading + Classic serif body */
:root {
  --font-heading: 'Inter', system-ui, sans-serif;
  --font-body: 'Georgia', Times, serif;
}

Superfamily Approach

/* Single variable font family for all uses */
:root {
  --font-family: 'Inter', system-ui, sans-serif;
}

h1 {
  font-family: var(--font-family);
  font-weight: 800;
  letter-spacing: -0.02em;
}

p {
  font-family: var(--font-family);
  font-weight: 400;
  letter-spacing: 0;
}

.caption {
  font-family: var(--font-family);
  font-weight: 500;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

Semantic Typography Classes

/* Text styles by purpose, not appearance */
.text-display {
  font-size: var(--font-size-5xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-tight);
}

.text-headline {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
}

.text-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
}

.text-body {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-normal);
}

.text-body-sm {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-normal);
}

.text-caption {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-normal);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
}

.text-overline {
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-normal);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-widest);
}

OpenType Features

/* Enable advanced typography features */
.fancy-text {
  /* Small caps */
  font-variant-caps: small-caps;

  /* Ligatures */
  font-variant-ligatures: common-ligatures;

  /* Numeric features */
  font-variant-numeric: tabular-nums lining-nums;

  /* Fractions */
  font-feature-settings: 'frac' 1;
}

/* Tabular numbers for aligned columns */
.data-table td {
  font-variant-numeric: tabular-nums;
}

/* Old-style figures for body text */
.prose {
  font-variant-numeric: oldstyle-nums;
}

/* Discretionary ligatures for headings */
.fancy-heading {
  font-variant-ligatures: discretionary-ligatures;
}