Typography System β Accessible Fonts, Sizes, and Spacing
In this tutorial, you will learn about Typography System. We cover key concepts, practical examples, and best practices to help you master this topic.
An accessible typography system provides minimum 16px body text, line height of 1.5 to 2.0, clear heading hierarchy with adequate contrast, readable font choices, and responsive scaling for all screen sizes.
What You'll Learn
You will learn how to build a typography system that prioritizes readability, how to define type scales with Accessibility in mind, and how to ensure your typography tokens produce accessible text.
Why It Matters
Typography is the foundation of content readability. If the typography system produces text that is too small, too dense, or low contrast, every page built with it will be difficult to read for users with visual and cognitive disabilities.
Real-World Use
DodaKit's typography system starts at 16px body text with 1.6 line height. Heading sizes use a 1.25 ratio scale. All sizes use rem units for browser zoom compatibility. A readability mode increases line height to 2.0.
flowchart TD A[Typography System] --> B[Size Scale] A --> C[Line Height] A --> D[Font Family] A --> E[Heading Hierarchy] A --> F[Responsive Scaling] B --> G[16px base, 1.25 ratio] C --> H[1.5 to 2.0 range] D --> I[Sans-serif with fallback] E --> J[h1-h6 with weight] F --> K[rem units, clamp()]
Font Size Scale
Use a modular scale for font sizes. A 1.25 ratio (major third) starting at 16px produces a balanced scale: 16, 20, 25, 31, 39, 49 pixels. This ratio provides clear differentiation between levels.
Line Height
Define line height tokens for different text roles. Body text needs 1.5 to 2.0. Headings need 1.2 to 1.4. The line height should decrease as font size increases.
Font Family
Choose readable, widely available fonts. Sans-serif fonts like Inter, Segoe UI, or system fonts are preferred. Always provide a generic fallback.
// Typography scale generator
function generateAccessibleScale(baseSize, ratio, steps) {
const scale = [];
for (let i = 0; i < steps; i++) {
const size = baseSize * Math.pow(ratio, i);
let lineHeight;
if (size <= 16) lineHeight = 1.8;
else if (size <= 20) lineHeight = 1.6;
else if (size <= 25) lineHeight = 1.4;
else if (size <= 31) lineHeight = 1.3;
else lineHeight = 1.2;
const name = i === 0 ? 'body' :
i === 1 ? 'h4' :
i === 2 ? 'h3' :
i === 3 ? 'h2' :
i === 4 ? 'h1' :
`display-${i - 4}`;
scale.push({
name: name,
sizePx: Math.round(size),
sizeRem: Math.round(size / 16 * 100) / 100 + 'rem',
lineHeight: lineHeight,
recommendedFor: name === 'body' ? 'Body text' : `${name.toUpperCase()} headings`
});
}
return scale;
}
const typographyScale = generateAccessibleScale(16, 1.25, 6);
console.table(typographyScale);
Expected output:
βββββββββββ¬ββββββββββββ¬βββββββββ¬βββββββββ¬ββββββββββββββ¬βββββββββββββββββββ
β (index) β name β sizePx β sizeRemβ lineHeight β recommendedFor β
βββββββββββΌββββββββββββΌβββββββββΌβββββββββΌββββββββββββββΌβββββββββββββββββββ€
β 0 β body β 16 β '1rem' β 1.8 β 'Body text' β
β 1 β h4 β 20 β '1.25r'β 1.6 β 'H4 headings' β
β 2 β h3 β 25 β '1.56r'β 1.4 β 'H3 headings' β
β 3 β h2 β 31 β '1.94r'β 1.3 β 'H2 headings' β
β 4 β h1 β 39 β '2.44r'β 1.2 β 'H1 headings' β
β 5 β display-1 β 49 β '3.06r'β 1.2 β 'Display heading'β
βββββββββββ΄ββββββββββββ΄βββββββββ΄βββββββββ΄ββββββββββββββ΄βββββββββββββββββββ
Heading Hierarchy
Use semantic heading levels h1 through h6. Do not skip levels. Ensure heading sizes are visually distinct. The heading level in HTML must match the visual hierarchy.
Responsive Typography
Use rem units so text scales with browser zoom. Use clamp() for fluid typography that scales between minimum and maximum sizes based on viewport width.
/* Accessible typography system tokens */
:root {
/* Base settings */
--ds-font-body: 'Inter', 'Segoe UI', system-ui, sans-serif;
--ds-font-heading: 'Inter', 'Segoe UI', system-ui, sans-serif;
/* Font sizes β modular scale 1.25 starting at 16px */
--ds-text-xs: 0.75rem; /* 12px β only for labels */
--ds-text-sm: 0.875rem; /* 14px β secondary text */
--ds-text-md: 1rem; /* 16px β body */
--ds-text-lg: 1.25rem; /* 20px β h4 */
--ds-text-xl: 1.563rem; /* 25px β h3 */
--ds-text-2xl: 1.953rem; /* 31px β h2 */
--ds-text-3xl: 2.441rem; /* 39px β h1 */
--ds-text-4xl: 3.052rem; /* 49px β display */
/* Line heights */
--ds-leading-tight: 1.2;
--ds-leading-snug: 1.4;
--ds-leading-normal: 1.6;
--ds-leading-relaxed: 1.8;
--ds-leading-loose: 2.0;
/* Fluid typography example */
--ds-text-fluid-h1: clamp(1.953rem, 1.5rem + 2vw, 3.052rem);
--ds-text-fluid-body: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
}
/* Usage example */
body {
font-family: var(--ds-font-body);
font-size: var(--ds-text-md);
line-height: var(--ds-leading-normal);
}
h1 {
font-family: var(--ds-font-heading);
font-size: var(--ds-text-fluid-h1);
line-height: var(--ds-leading-tight);
font-weight: 700;
}
Common Mistakes
1. Body Text Below 16px
Design systems often set body text at 14px or even 12px. This is too small for readable content.
2. Tight Line Height on Body Text
Line height below 1.5 makes body text dense and difficult to read. Always use at least 1.5 for body.
3. Skipping Heading Levels
Using h1 then h3 without h2 violates semantic hierarchy. Ensure heading levels are sequential.
4. Using px Units
Px units prevent browser zoom from scaling text. Use rem units for all text sizes.
5. Italic or Light Weight Fonts for Body
Light (300) or italic body text is harder to read. Use regular (400) weight for body.
6. No Fallback Font
Custom fonts may not load. Always provide a system font fallback.
7. Heading Sizes Too Similar
Headings that are visually similar do not convey hierarchy. Ensure at least 1.25 ratio between levels.
Practice Questions
1. What is the minimum body text size for an accessible typography system?
16px (1rem). Smaller text is difficult to read for users with visual and cognitive disabilities.
2. What line height range should body text use?
1.5 to 2.0. Below 1.5 is too dense; above 2.0 has too much separation between lines.
3. Why should heading sizes not be skipped?
Skipping heading levels (h1 to h3 without h2) breaks the semantic hierarchy that screen readers rely on.
4. What CSS unit should be used for font sizes and why?
rem units. They respect browser zoom settings and allow users to scale text.
5. Challenge: Create a typography scale with 6 levels. Specify font size (in rem), line height, font weight, and usage for each level.
FAQ
Mini Project
Create a typography system specification with 6 sizes, 5 line height values, and 3 font families. Include responsive tokens using clamp() and rem units. Validate that body text starts at 16px.
What's Next
Learn about Spacing and Layout for accessible design systems. Then explore Component Library a11y patterns.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro