Type something to search...
How to Support Browser Zoom and User Font Preferences?

How to Support Browser Zoom and User Font Preferences?

A user zooms your marketing site to 200% to read the pricing details. The sticky header, which was a tidy 80px bar, now takes up a third of the screen. The hero heading overflows its container because it was sized in vw and refused to grow. The cookie banner covers what's left. The user can technically still scroll, but reading the page has become a fight. None of this shows up when you test at 100% on a large monitor, which is why zoom bugs are so common.

This article explains the different ways people enlarge text, what WCAG requires for each, the CSS patterns that keep layouts readable at 200% and 400%, how to handle iOS Dynamic Type and Android font scaling, and a quick test routine you can run on any page.

The Different Ways Users Enlarge Text

"Zoom" covers several separate mechanisms, and each one affects your CSS differently:

MethodWhere it livesWhat it scalesEffect on layout
Page zoomCtrl/Cmd + plus, browser zoom menuEverything (CSS pixel size changes)Viewport width shrinks, breakpoints fire
Text-only zoomFirefox "Zoom text only", Safari optionText onlyLayout stays, text grows inside it
Default font sizeBrowser settings (Chrome, Firefox, Safari)rem and em valuespx text ignores it
Minimum font sizeBrowser settingsAny text below the minimumCan break tightly sized components
Pinch zoomTouch devices, trackpadsVisual viewport onlyLayout doesn't change; user pans around
OS text sizeiOS Dynamic Type, Android font scaleDepends on browser and your CSSVaries by platform
Screen magnifiersZoomText, macOS Zoom, Windows MagnifierThe whole screen imageYour layout is unaffected, user sees a portion

A robust site works with all of these. The good news is that the same handful of CSS habits covers almost every case.

What WCAG Requires

Three WCAG 2.2 Level AA criteria apply directly:

  • 1.4.4 Resize Text. Text can be resized to 200% without assistive technology and without loss of content or functionality.
  • 1.4.10 Reflow. Content can be presented at a width of 320 CSS pixels (equivalent to 1280px at 400% zoom) without scrolling in two dimensions. Data tables, maps, and similar content that require two-dimensional layout are exempt.
  • 1.4.12 Text Spacing. No loss of content when users increase line height to 1.5, paragraph spacing to 2×, letter spacing to 0.12em, and word spacing to 0.16em.

Together they mean your text must grow, your layout must reflow instead of forcing horizontal scrolling, and your containers must make room for larger, looser text.

Rule 1: Never Disable Pinch Zoom

This viewport tag is still common, and it's an accessibility failure:

<!-- Don't do this -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />

Use the plain version:

<meta name="viewport" content="width=device-width, initial-scale=1" />

iOS Safari has ignored user-scalable=no since iOS 10, but Android browsers and in-app web views may still honor it. If you were disabling zoom to stop iOS from zooming into form fields, set input font sizes to 16px or larger instead. In the Next.js App Router, export a viewport object from your root layout and leave out maximumScale and userScalable:

// app/layout.tsx
import type { Viewport } from "next";

export const viewport: Viewport = {
  width: "device-width",
  initialScale: 1,
};

Rule 2: Use Relative Units for Text

Text sized in px grows with page zoom but ignores the browser's default font size setting. Text in rem respects both. Leave the root font size at the browser default:

html {
  font-size: 100%;
}

body {
  font-size: 1.125rem;
  line-height: 1.6;
}

The full reasoning, plus a migration plan for older code, is in why you should use rem instead of px for font sizes.

Rule 3: Never Size Text with Viewport Units Alone

Viewport units are the most common cause of text that won't zoom. When a user zooms the page, the viewport width measured in CSS pixels shrinks by the same factor, so 5vw produces the same physical size, or even a smaller one, after zooming.

/* Fails 1.4.4: does not grow with zoom */
h1 {
  font-size: 5vw;
}

/* Works: the rem component scales with zoom and user settings */
h1 {
  font-size: clamp(2rem, 1.25rem + 3vw, 3.5rem);
}

Check your clamp() values carefully. If the vw part dominates and the maximum is low, zooming to 200% may not increase the text size by much. A safe rule is that the maximum value should be no more than about 2.5 times the minimum. That way, zooming always gets the user at least 200% of the minimum size. The post on fluid typography with CSS clamp() works through the math.

Rule 4: Let Containers Grow with Their Text

When text grows, everything holding it must grow too. The usual offenders:

  • Fixed heights on cards, buttons, headers, and hero sections.
  • overflow: hidden that clips text that no longer fits.
  • Absolute positioning that stacks elements on top of each other once text wraps.
  • Fixed widths in pixels on sidebars, form fields, and modals.

Replace them with intrinsic sizing:

/* Before */
.card {
  height: 320px;
  overflow: hidden;
}

/* After */
.card {
  min-height: 20rem;
}

.button {
  min-block-size: 2.75rem;
  padding: 0.625em 1.25em; /* grows with the button's text */
}

.sidebar {
  inline-size: min(100%, 20rem);
}

If you need to truncate text, make sure the full content is reachable another way, such as a link to the full article. Clamped lines that hide content with no recovery fail 1.4.4 when the content grows.

Rule 5: Design Layouts That Reflow at 320px

Reflow means that at 400% zoom on a 1280px-wide window, which gives a 320 CSS pixel viewport, the page becomes a single column with vertical scrolling only. If your site already works well on a 320px phone, you're most of the way there. Patterns that help:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: 1.5rem;
}

pre,
table {
  max-inline-size: 100%;
  overflow-x: auto; /* allowed for content that needs 2D layout */
}

img,
video {
  max-inline-size: 100%;
  block-size: auto;
}

.long-words {
  overflow-wrap: anywhere;
}

Use breakpoints in rem or em rather than px. With text-based breakpoints, a user with a larger default font size gets the narrower layout earlier, which keeps line lengths and columns readable.

@media (min-width: 60rem) {
  .layout {
    grid-template-columns: 1fr 18rem;
  }
}

Rule 6: Tame Sticky and Fixed Elements

At high zoom, the visible viewport becomes very short. A sticky header, a fixed bottom bar, and a chat widget can together cover most of the screen. WCAG 1.4.10 notes that content shouldn't be obscured, and the newer 2.4.11 Focus Not Obscured (Minimum) criterion in WCAG 2.2 requires that focused elements are not entirely hidden by author-created content.

Use a height-based media query to drop stickiness when the viewport is short:

.site-header {
  position: sticky;
  top: 0;
}

@media (max-height: 30rem) {
  .site-header {
    position: static;
  }
}

/* Keep focused elements clear of a sticky header */
html {
  scroll-padding-block-start: 5rem;
}

Because the media query is in rem, it also kicks in when the user's default font size is large.

Rule 7: Respect OS-Level Text Size

Phones have their own text size settings, and browsers handle them differently.

iOS Dynamic Type

Safari on iOS doesn't apply the system text size to web content automatically. You can opt in by using Apple's system font keyword on the root element, which sets the root font size from the user's Dynamic Type setting:

@supports (font: -apple-system-body) {
  html {
    font: -apple-system-body;
  }
}

body {
  font-family: "Inter", system-ui, sans-serif; /* restore your font family */
  font-size: 1rem;
}

The font shorthand also sets the family, so you need to restore your own font-family afterward. Everything sized in rem then follows the user's iOS text size. Test this carefully: at the largest accessibility sizes, root text can exceed 50px, so your layout has to be genuinely fluid.

Android Font Scale

Chrome on Android applies the system font scale to web content, either through its text scaling or by adjusting page zoom, depending on the version and settings. In both cases, rem-based typography and fluid layouts handle it gracefully.

Text Size Adjust

Mobile browsers may inflate text in landscape orientation. If you set text-size-adjust, use 100% rather than none, because none can interfere with users' ability to zoom in some browsers:

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

Rule 8: Respect Other User Preferences

Text size is one preference among several. Modern CSS lets you honor others that affect reading:

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .animated-heading {
    animation: none;
  }
}

@media (prefers-contrast: more) {
  :root {
    --text-muted: var(--text);
    --border: CanvasText;
  }
}

@media (forced-colors: active) {
  .tag {
    border: 1px solid CanvasText;
  }
}

Also avoid !important on typography properties where possible. Users who apply custom stylesheets or extensions to increase spacing or change fonts need their rules to win.

How to Test Zoom and Font Preferences

Run this routine on your key templates: home page, article, product or pricing page, and forms.

  1. Page zoom to 200% (Ctrl or Cmd plus, five or six times). All text should be larger, nothing should be cut off, and no content should overlap.
  2. Page zoom to 400% on a 1280px-wide window. The layout should be a single column without horizontal scrolling, except for tables, code blocks, and maps.
  3. Change the default font size to Very Large (24px) in Chrome settings, then reload. All text should grow.
  4. Firefox text-only zoom. In Firefox, enable View, Zoom, Zoom Text Only, and zoom to 200%. This is the harshest test of fixed-height containers.
  5. Apply WCAG text spacing with a bookmarklet or a user style.
  6. On iOS, set Settings, Accessibility, Display & Text Size, Larger Text to a large size and reload.
  7. Tab through the page at 200% zoom and confirm the focused element is never hidden behind sticky content.

For a fuller testing process aimed at real readers with low vision, see how to test typography for low-vision users.

Browser Zoom and Font Preferences FAQ

Page zoom enlarges everything on the page, including images and layout, and it changes the viewport width so responsive breakpoints fire. Text-only zoom and the browser default font size enlarge only text, leaving images and spacing as they are, which is a much harder test for fixed-size containers.

WCAG 1.4.10 Reflow requires content to work at a width of 320 CSS pixels without horizontal scrolling, which is equivalent to 400 percent zoom on a 1280 pixel wide window. Criterion 1.4.4 separately requires that text can be resized to 200 percent.

It is probably sized with viewport units alone, such as 5vw. Zooming shrinks the viewport width in CSS pixels, so the computed size stays the same. Combine a rem value with the vw value inside clamp so part of the size always scales.

No. Disabling zoom with user-scalable=no or maximum-scale=1 blocks users who need to enlarge content and fails WCAG 1.4.4. iOS Safari ignores those values anyway. Prevent unwanted zoom on form fields by setting their font size to at least 16px.

Set the root element's font to the -apple-system-body keyword inside a supports query, restore your own font family, and size everything else in rem. Safari will then base the root font size on the user's Dynamic Type setting. Test at the largest sizes, because text can become very large.

Yes, for content that genuinely needs two-dimensional layout, such as data tables, maps, diagrams, and code blocks. Wrap those in a container that scrolls horizontally on its own, while the rest of the page reflows into a single column.

Conclusion

Supporting zoom and user font preferences isn't one feature. It's a set of habits: never disable pinch zoom, size text in rem, never use viewport units alone for font sizes, let containers grow with their text, design layouts that reflow to 320px, and keep sticky elements from swallowing short viewports. Each habit is small, and together they make your site work for people who enlarge text in very different ways.

The final step is testing in the ways your users actually zoom: 200% and 400% page zoom, a large default font size, Firefox text-only zoom, and large text on a phone. Ten minutes per template is usually enough to catch the fixed heights and overflowing headings that would otherwise lock people out of your content.

Here are some useful references for going deeper on zoom and font preferences:

  1. W3C WAI: Understanding Success Criterion 1.4.10: Reflow — the 320 CSS pixel requirement and its exceptions.
  2. W3C WAI: Understanding Success Criterion 1.4.4: Resize Text — what "resize to 200%" means in practice.
  3. MDN Web Docs: text-size-adjust — how mobile text inflation works and why to avoid the none value.
  4. WebKit Blog: Using the System Font in Web Content — Apple's explanation of system font keywords, including the Dynamic Type styles.
  5. Next.js Docs: generateViewport — how to configure the viewport in the App Router.
Share :

Related Posts

Ascenders, Descenders, and Baselines: The Anatomy of a Letterform

Ascenders, Descenders, and Baselines: The Anatomy of a Letterform

You align an icon next to a button label and it looks a pixel or two too high, no matter how you adjust vertical-align. You set overflow: hidden

Continue Reading
Are Google Fonts GDPR-Compliant?

Are Google Fonts GDPR-Compliant?

In late 2022, thousands of small business owners in Germany and Austria opened letters demanding a few hundred euros in "damages" because their websi

Continue Reading
How to Audit Web Font Performance with Lighthouse?

How to Audit Web Font Performance with Lighthouse?

A client sends you a screenshot of their PageSpeed Insights report: performance score 61, LCP 3.9 seconds, and a vague list of warnings. They want to

Continue Reading