Font Size Guide for Web: Body, Headings and Accessibility
The short answer to web font size: set body text at 16px minimum (most content sites are happiest at 16–18px), build headings up from there with a consistent ratio, and express every size in rem so text respects the reader’s browser settings. That single rule — never lock type to fixed pixels — solves most accessibility failures before they happen. This guide gives you concrete numbers for body, headings, and captions, explains the units, and shows how to keep type readable when users zoom.
This is part of our complete web typography guide; for the spacing that surrounds these sizes, pair it with line height and letter spacing and, for screen-scaling sizes, responsive typography.
The right body font size
Body text is the most-read element on any page, so get it right first. The reliable range:
- 16px (1rem) — the proven minimum for comfortable reading. It’s the browser default for good reason.
- 17–18px — common on editorial and long-form sites where reading comfort is the priority.
- Below 16px — reserve for genuinely secondary text (captions, fine print), never main copy.
Bigger isn’t automatically better — body text above ~20px starts to feel oversized on desktop and forces awkward line breaks. The sweet spot for most sites is 16–18px, tuned so your chosen font’s x-height looks right (a tall-x-height face like Inter reads larger at the same point size than a small-x-height face).
Heading sizes and the type scale
Don’t pick heading sizes by eye one at a time. Choose a base (16px body) and a ratio, then multiply up — this is a type scale, and it’s what makes hierarchy feel deliberate. A 1.25 (major third) ratio on a 16px base produces a clean, content-friendly scale:
| Element | Size (rem) | Approx px |
|---|---|---|
| H1 | 2.44rem | ~39px |
| H2 | 1.95rem | ~31px |
| H3 | 1.56rem | ~25px |
| H4 / lead | 1.25rem | 20px |
| Body | 1rem | 16px |
| Caption / small | 0.875rem | 14px |
Want bigger headline contrast? Step up to a 1.333 (perfect fourth) ratio. Need a denser dashboard UI? Drop to 1.2. Define the steps once as CSS custom properties so a stray inline size can’t sneak in. For headings that resize fluidly across viewports rather than sitting at one fixed size, convert these steps to clamp() as covered in our responsive typography guide.
rem vs px vs em: which unit to use
Units are where accessibility is won or lost.
- rem — relative to the root font size. Use it for nearly all type. When a user raises their default browser font size,
rem-sized text scales with it;pxtext does not. This is the single most important choice in this guide. - px — fixed and absolute. Acceptable for hairline borders or fixed UI chrome, but a poor default for text because it ignores user preferences.
- em — relative to the parent’s font size. Useful for spacing that should track a component’s own size (e.g. padding inside a button), but it compounds when nested, which causes surprises if overused on type.
Practical rule: type sizes in rem, component-internal spacing in em, hairlines in px. Don’t fight users who’ve set a larger font size for a reason — usually their eyesight.
Captions, labels, and fine print
Secondary text can go below your body size, but not by much. 14px (0.875rem) is a sensible floor for captions, form helper text, and labels. Anything smaller starts to fail real-world legibility, especially for older readers and on high-density phone screens. Compensate for small sizes with a touch of positive letter-spacing and slightly more line height — small text needs proportionally more breathing room, a point we expand on in the typography spacing guide.
Mobile vs desktop sizing
A common misconception is that mobile needs smaller text. It usually needs the same body size or larger — phones are held close but have small viewports, and tiny text forces pinch-zooming. Keep body at 16px on mobile (never set it smaller “to fit more in”). What should shrink on small screens are the big headings: an H1 that’s 39px on desktop can feel cramped at the same size on a 360px-wide phone. The clean solution is fluid sizing with clamp() so headings scale down gracefully while body stays put — again, see responsive typography.
Font size and the x-height factor
Point size alone doesn’t determine how big text looks — x-height does much of that work. The x-height is the height of a lowercase letter like “x” relative to the capital height. A face with a tall x-height (such as Inter or Verdana) appears noticeably larger and more legible at a given point size than a face with a small x-height (such as a traditional book serif), because more of the letter sits in the readable zone.
The practical consequence: don’t pick a size in the abstract and apply it to any font. Set your body size, then look at the actual face. A small-x-height serif may need 17–18px to feel as comfortable as a tall-x-height sans at 16px. This is why two sites both “using 16px body text” can read completely differently. Tune the size optically to the font you’ve chosen rather than trusting the number alone, and re-check whenever you swap typefaces.
Setting a base font size in CSS
Establish the base once on the root and let everything inherit and scale from it. Avoid overriding the root with a fixed pixel size that would clobber a user’s browser preference. A clean pattern is to leave the root at the browser default (which respects the user’s setting) and size the body in rem:
html { font-size: 100%; }— keeps the user’s chosen default (usually 16px) intact.body { font-size: 1.125rem; }— sets comfortable 18px body text that still scales with the user’s preference.- Heading and small-text steps then reference
remvalues from your scale.
The anti-pattern to avoid is html { font-size: 62.5%; } (the old “1rem = 10px” trick) combined with pixel-thinking — it works mechanically but encourages reasoning in fixed pixels and can override user defaults. Keep the root at 100% and think in real rem ratios instead.
Accessibility rules for font size
- Size text in relative units (
rem/em) so it honors browser font-size settings and zoom. - Support 200% zoom. WCAG requires content to remain usable when zoomed to 200%; relative units make this automatic.
- Never disable zoom. Don’t ship
user-scalable=noin the viewport meta tag — it locks out users who need to enlarge text. - Maintain contrast at every size. Body text needs 4.5:1 contrast; large text (≥24px, or ≥18.66px bold) needs 3:1.
- Keep a real minimum. 16px body, 14px floor for secondary text.
Quick reference: recommended sizes
- Body: 16–18px (1–1.125rem)
- Lead paragraph: 18–20px (1.125–1.25rem)
- H1: 32–48px, fluid
- H2: 28–36px
- H3: 22–28px
- Captions / small: 14px (0.875rem) floor
- Buttons / labels: 14–16px
Frequently Asked Questions
What is the best font size for web body text?
16px (1rem) is the proven minimum, and 16–18px suits most content sites. Long-form and editorial sites often use 17–18px for comfort. Always set it in rem rather than fixed pixels so the text scales with the reader’s browser settings and zoom.
Should I use px or rem for font size?
Use rem for type. It’s relative to the root font size, so text scales when a user changes their browser default or zooms — a WCAG requirement. Fixed px ignores those preferences and is best reserved for hairline borders or fixed UI elements, not body or heading text.
Is 14px too small for web text?
14px is acceptable for secondary text like captions, labels, and fine print, but too small for main body copy. Keep body text at 16px or larger. If you use 14px, add slight letter-spacing and a bit more line height to preserve legibility, and never go below it for important content.
What font size should headings be?
Build headings from your 16px body using a consistent ratio. A 1.25 scale gives roughly H3 ~25px, H2 ~31px, and H1 ~39px. Use larger ratios (1.333) for more dramatic contrast. On mobile, let big headings shrink with clamp() while body text stays at 16px.
Does mobile need a smaller font size?
No — keep body text at 16px on mobile so users don’t have to pinch-zoom. What should scale down on small screens are large headings, not body copy. Fluid sizing with CSS clamp() handles this automatically, shrinking headlines while leaving body text comfortable.
Try it live: Use our free type scale calculator to generate a modular font-size scale and copy the CSS variables.



