The rem vs px Illusion: How Browsers Actually Scale Typography for Accessibility
CSS Edition
June 3, 2026
Go to any frontend engineering forum, search for typography, and you will find yourself staring into a deep, dogmatic rabbit hole. The battle lines were drawn a decade ago: on one side, you have the pixel purists who want exact, predictable control over their designs (font-size: 16px). On the other side, you have the accessibility advocates who insist that hardcoding pixels is an absolute sin, demanding that everything be authored in root em units (font-size: 1rem).
The arguments for rem sound incredibly noble. We are told that if a user goes into their browser settings and changes their default font size from 16px to 24px because of a visual impairment, hardcoded pixels will lock them out. rem units, we are told, act as a magical, fluid conduit that respects the user’s wishes and scales the layout beautifully.
It’s a beautiful mental model. It’s also largely an illusion.
Modern browser rendering engines do not handle typography the way they did in 2012. Let’s look past the surface-level tutorials and look directly at how rendering trees actually calculate text scaling, and why the way you are coding rem units might actually be breaking accessibility anyway.
The Death of the Hardcoded Text Freeze
The historical argument against pixel-based typography stems from an old browser limitation. In early versions of Internet Explorer, if an engineer set a font size to 16px, the browser’s native “Text Size” adjustment tool literally could not scale it. The pixels were treated as absolute physical bounds. Dropping rem or em into your CSS was the only way to allow the text to expand.
But modern browsers don’t just scale text anymore; they scale the entire layout using Page Zoom.
When a user hits Cmd + or Ctrl + in a modern browser, the engine doesn’t go through the DOM tree looking only for relative units to upscale. Instead, the rendering engine modifies the coordinate system of the viewport itself. It alters the pixel ratio. To the engine, a layout authored entirely in 16px scales just as fluidly under Page Zoom as a layout authored in 1rem.
So, if modern page zoom treats pixels and relative units identically, is the rem vs px debate entirely dead? Not quite. The real problem isn’t page zoom—it’s Root Font Configuration.
How the Rendering Tree Calculates the Root
The real divergence happens when a user modifies their baseline browser preferences directly—changing their global default font size from “Medium (16px)” to “Very Large (24px)”.
When the browser engine compiles your styles to generate the render tree, it must compute every relative value down to an absolute, real-world pixel target before it can hand off instructions to the layout and paint hardware. The formula looks like this:
Computed Pixel Size=Element rem Value×Root Font Size
If you use font-size: 1rem, and the user has a default preference of 24px, the text compiles to exactly 24px. If you use font-size: 16px, the user’s global preference is entirely ignored, and the text stays locked at 16px.
So, rem wins, right? Yes—until frontend developers step in and accidentally break the calculation using a very common CSS “hack.”
The 62.5% Anti-Pattern
Because doing base-16 mental math in your head while writing CSS is annoying (nobody wants to calculate what 14px is in rems out to four decimal places), a popular technique emerged across the industry. Developers add this snippet to their global stylesheets:
CSS
html {\n font-size: 62.5%; /* 10px baseline */\n}\n\nbody {\n font-size: 1.6rem; /* Compiles to 16px */\n}
By dropping the root font size to 62.5%, you force 1rem to equal exactly 10px. Now, if you want a heading to be 24px, you just write 2.4rem. It’s clean, easy to read, and keeps your code in relative units.
But think about what this does to the browser engine’s calculation when a visually impaired user alters their baseline settings.
If a user changes their default font size to 24px, they expect your 16px body copy to scale proportionally up to 24px. But because you hardcoded a percentage reduction on the root (62.5%), the engine multiplies the user’s custom 24px preference down to a base of 15px. When your body text requests 1.6rem, it multiplies 1.6 * 15px, resulting in a final painted size of 24px.
You have effectively muted the user’s explicit request. Instead of receiving the significant boost they need to read your content comfortably, your layout applies a dampening filter over their accessibility settings just to save your engineering team from doing basic math.
Writing Typography for the Actual Engine
If you want to build truly accessible web applications that respect how modern rendering trees operate, you have to stop relying on unit dogmatism and focus on predictable scaling:
-
Stop using the 62.5% hack: If you choose to use
remunits, leave the roothtmlfont size completely un-manipulated at100%. Let1remequal whatever the browser runtime says it should equal. If the math gets tedious, offload it to your build tools using PostCSS plugins or CSS variables. -
Design for Fluid Layouts: The real threat to accessibility isn’t the font unit you choose; it’s container clipping. If your text scales up by 200% under user preferences, but your containers have hardcoded heights (
height: 45px), your text will overflow and overlap, making the site completely unreadable. -
Embrace Component Isolation: Use
remfor global typography structure so it scales with user preferences, but consider usingemfor local padding and margins inside components. This ensures that as the text scales up, the breathing room around the text scales up proportionally alongside it.
The browser engine is incredibly resilient, but it relies on us to provide clean, unadulterated baseline intent. Author your layouts so that the browser can do its job, and stop letting clever shortcuts get in the way of a user’s right to read your interface.
Thanks for reading Under The Hood! This post is public so feel free to share it.