REM-Based Typography — Scalable Font Sizes with rem Units
Using rem for font sizes creates accessible, scalable typography. Text inherits from the user's browser setting instead of a fixed pixel size. Here's how to set up rem-based...
Using rem for font sizes lets users control text size through browser settings. When a user sets their browser to 20px base font, everything sized in rem scales up proportionally — px values stay fixed.
Use the PX to REM Converter to convert pixel values to rem.
Why rem for typography
/* Fixed pixels — ignores user font settings: */
.text { font-size: 16px; } /* Never changes */
/* rem — respects user preferences: */
.text { font-size: 1rem; } /* Scales with browser setting */
A user who sets their browser to 20px base (common for low-vision users) sees:
16px→ remains 16px (too small for them)1rem→ becomes 20px (respects their preference)
This is the core accessibility argument for rem typography.
Setting up the root font size
/* Common approach: 62.5% base makes 1rem = 10px at default: */
html {
font-size: 62.5%; /* 16px × 0.625 = 10px */
}
/* Now rem values are easy to calculate: */
h1 { font-size: 3.2rem; } /* 32px */
h2 { font-size: 2.4rem; } /* 24px */
body { font-size: 1.6rem; } /* 16px */
small { font-size: 1.2rem; } /* 12px */
Caution: The 62.5% trick overrides user font-size settings because it’s percentage-based from the user’s set size. If the user sets 20px, the base becomes 12.5px, not 10px — still proportional.
/* Alternative: keep default root font size, use natural rem values */
html {
/* No font-size override — use browser default (16px) */
}
h1 { font-size: 2rem; } /* 32px */
h2 { font-size: 1.5rem; } /* 24px */
p { font-size: 1rem; } /* 16px */
small { font-size: 0.875rem; } /* 14px */
This is the cleanest approach — no percentage tricks needed.
Type scale system
A modular type scale creates visual harmony by using consistent ratios between sizes:
:root {
/* Base: 1rem = 16px (browser default) */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 3.75rem; /* 60px */
}
/* This is Tailwind's type scale */
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }
p { font-size: var(--text-base); }
small { font-size: var(--text-sm); }
Fluid typography with clamp()
clamp() creates font sizes that scale smoothly between minimum and maximum:
h1 {
font-size: clamp(1.75rem, 4vw, 3rem);
/* Minimum: 1.75rem (28px)
Preferred: 4% of viewport width
Maximum: 3rem (48px) */
}
body {
font-size: clamp(1rem, 1.2vw + 0.5rem, 1.25rem);
}
This scales from the minimum on small screens to the maximum on large screens without media queries.
Complete fluid type scale
:root {
--text-sm: clamp(0.8rem, 0.17vw + 0.76rem, 0.89rem);
--text-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
--text-lg: clamp(1.25rem, 0.61vw + 1.1rem, 1.58rem);
--text-xl: clamp(1.56rem, 1vw + 1.31rem, 2.11rem);
--text-2xl: clamp(1.95rem, 1.56vw + 1.56rem, 2.81rem);
--text-3xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);
}
Generated using Utopia’s type scale calculator.
Responsive typography with media queries
The simpler approach when fluid isn’t needed:
/* Mobile first: */
:root {
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--heading-1: 1.75rem;
--heading-2: 1.5rem;
}
/* Tablet: */
@media (min-width: 768px) {
:root {
--heading-1: 2.25rem;
--heading-2: 1.875rem;
}
}
/* Desktop: */
@media (min-width: 1200px) {
:root {
--heading-1: 3rem;
--heading-2: 2.25rem;
}
}
h1 { font-size: var(--heading-1); }
h2 { font-size: var(--heading-2); }
Line height with unitless values
/* AVOID: px or rem line-height (doesn't scale with font size): */
p { line-height: 24px; }
p { line-height: 1.5rem; }
/* PREFER: unitless (scales with font-size automatically): */
p { line-height: 1.6; } /* 1.6 × font-size */
h1 { line-height: 1.1; } /* Tighter for headings */
.small-text { line-height: 1.4; }
Related tools
- PX to REM Converter — convert pixel values to rem
- rem, px, em Explained — CSS unit comparison
- Fluid Typography CSS — clamp() typography
Related posts
- Fluid Typography with CSS clamp() — Scale Fonts Without Media Queries — CSS clamp() creates fluid typography that scales smoothly between minimum and ma…
- CSS Units Guide — px, em, rem, vw, vh, and When to Use Each — CSS has absolute units (px), relative to font-size (em, rem), viewport units (vw…
- CSS Design Tokens — Define Spacing, Colors, and Typography with Custom Properties — CSS design tokens store reusable values as custom properties (CSS variables). Le…
- Font Size Accessibility — Minimum Sizes, User Zoom, and WCAG Requirements — WCAG 2.1 doesn't mandate a specific minimum font size, but best practice is 16px…
- REM, PX, EM Units Explained — CSS Length Units Comparison — CSS has absolute units (px) and relative units (rem, em, %). Here's how rem, px,…
Related tool
Convert px to rem, em, and percent — and vice versa. Configurable root font size. Bulk conversion mode for entire stylesheets.
Written by Mian Ali Khalid. Part of the Frontend & Design pillar.