What Is a Modular Scale?
A modular scale starts with a base size (usually 16px / 1rem for body text) and multiplies by a fixed ratio to generate larger sizes, or divides to generate smaller ones. Every size in the scale is mathematically related to every other size.
With a ratio of 1.25 and base 16px:
Step Calculation Size Rem
-2 16 / 1.25 / 1.25 10.24px 0.64rem (small caption)
-1 16 / 1.25 12.8px 0.8rem (small)
0 16 (base) 16px 1rem (body)
1 16 × 1.25 20px 1.25rem (large body / h5)
2 16 × 1.25 × 1.25 25px 1.563rem (h4)
3 ... × 1.25 31.25px 1.953rem (h3)
4 ... × 1.25 39.06px 2.441rem (h2)
5 ... × 1.25 48.83px 3.052rem (h1)
6 ... × 1.25 61.04px 3.815rem (hero)
Common Ratios
| Name | Ratio | Character |
|---|---|---|
| Minor Second | 1.067 | Very subtle, tight |
| Major Second | 1.125 | Subtle, gentle hierarchy |
| Minor Third | 1.2 | Balanced, common default |
| Major Third | 1.25 | Clear hierarchy, modern web |
| Perfect Fourth | 1.333 | Confident, editorial |
| Augmented Fourth | 1.414 | Dramatic, bold |
| Perfect Fifth | 1.5 | Strong hierarchy, display-friendly |
| Golden Ratio | 1.618 | Classical elegance |
| Double Octave | 2.0 | Extreme contrast, landing pages |
Choosing the Right Ratio
Dense, long-form content (docs, blog): use a small ratio like 1.125 or 1.2. Subtle hierarchy reduces visual noise in text-heavy pages.
General product UI: 1.25 (major third) is the modern web default — enough contrast for clear hierarchy without feeling dramatic.
Marketing pages, landing pages: 1.333 to 1.5. You want dramatic hero headings that contrast sharply with body text.
Editorial / magazine layouts: 1.414 or golden ratio (1.618). Classical, confident, gives display typography real presence.
Implementing a Scale with CSS Variables
:root {
/* Major Third scale, base 16px */
--text-xs: 0.64rem; /* 10.24px */
--text-sm: 0.8rem; /* 12.8px */
--text-base: 1rem; /* 16px */
--text-lg: 1.25rem; /* 20px */
--text-xl: 1.563rem; /* 25px */
--text-2xl: 1.953rem; /* 31.25px */
--text-3xl: 2.441rem; /* 39.06px */
--text-4xl: 3.052rem; /* 48.83px */
--text-5xl: 3.815rem; /* 61.04px */
}
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }
h5 { font-size: var(--text-lg); }
body { font-size: var(--text-base); }
small { font-size: var(--text-sm); }
Responsive Scales with clamp()
Static scales are too big on mobile — a 48px hero that's beautiful on desktop dominates a 375px-wide phone. Use clamp(min, preferred, max) to scale smoothly:
:root {
/* Fluid scale — smaller on mobile, larger on desktop */
--text-base: clamp(1rem, 0.95rem + 0.2vw, 1.125rem);
--text-lg: clamp(1.125rem, 1rem + 0.5vw, 1.25rem);
--text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.563rem);
--text-2xl: clamp(1.5rem, 1.2rem + 1vw, 1.953rem);
--text-3xl: clamp(1.875rem, 1.4rem + 1.5vw, 2.441rem);
--text-4xl: clamp(2.25rem, 1.6rem + 2.5vw, 3.052rem);
--text-5xl: clamp(2.75rem, 2rem + 3.5vw, 3.815rem);
}
The middle value combines a rem base with a vw (viewport-width) scalar, letting the type grow linearly with the screen size between the minimum and maximum bounds.
Mixing Two Ratios (Advanced)
A single ratio can feel monotonous at extreme sizes. A more sophisticated approach uses different ratios for body-range and display-range sizes:
/* Body range uses Minor Third (1.2) for subtle steps */
/* Display range uses Perfect Fourth (1.333) for dramatic headings */
:root {
--text-xs: 0.694rem; /* 16 / 1.2 / 1.2 */
--text-sm: 0.833rem; /* 16 / 1.2 */
--text-base: 1rem; /* 16 */
--text-lg: 1.2rem; /* 16 × 1.2 */
--text-xl: 1.44rem; /* 16 × 1.2² */
--text-2xl: 1.919rem; /* 1.44 × 1.333 */
--text-3xl: 2.559rem; /* × 1.333 */
--text-4xl: 3.411rem; /* × 1.333 */
--text-5xl: 4.549rem; /* × 1.333 */
}
Related Properties in the Scale
A true design system applies the same ratio to more than just font size — spacing, border-radius, and line-heights should feel cohesive:
:root {
/* Spacing scale, same 1.25 ratio */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.625rem; /* 10px */
--space-4: 0.8rem; /* 12.8px */
--space-5: 1rem; /* 16px */
--space-6: 1.25rem; /* 20px */
--space-7: 1.563rem; /* 25px */
--space-8: 1.953rem; /* 31.25px */
/* Line-heights decrease as font size grows */
--leading-tight: 1.1; /* headlines */
--leading-normal: 1.5; /* body */
--leading-loose: 1.75; /* long-form reading */
}
Frequently Asked Questions
- Why are "musical" ratios good for typography?
- Humans perceive proportional relationships as harmonious whether they're frequency ratios (music), spatial ratios (design), or time intervals (rhythm). The same reason a chord sounds right makes a type scale look right — mathematically clean proportions reduce visual noise.
- Should I use exact calculated values or round them?
- Use calculated values via CSS variables or a
calc()expression. Rounding introduces inconsistency. If you want clean numbers for a specific size, adjust your base size or ratio until they come out cleaner. - Do I need every step of the scale?
- No. Most projects use 6-8 sizes total. Define the whole scale in your CSS variables for consistency, but only apply the handful you actually need. Having the scale available prevents random one-off sizes from creeping in later.
- How do I match the scale to a specific brand?
- Start with the brand's existing display font. Set that at your largest size. Work backwards to find a ratio that produces body text at 16px-18px. This anchors both ends of the scale to real design constraints.
- Can I use a type scale with Tailwind CSS?
- Yes — override Tailwind's default type scale in
tailwind.config.jsby settingtheme.fontSizewith your calculated values. This makes utilities liketext-xluse your brand's scale instead of Tailwind's defaults.