Pixels vs. Ems: Users DO Change Font Size

Web developers love a good holy war, whether it’s over our favorite JavaScript frameworks or principles like separation of concerns. One that’s always been of interest to me is the battle over CSS units, namely between pixels and relative units like rems and ems.

For years, most web designers and developers have been measuring things in pixels. They’re pretty easy to understand — one pixel in code maps to one pixel on screen, or at least it used to. But pixels are an absolute size, meaning they don’t change change in response to user preferences (other than browser zoom, which can override everything). That isn’t great for accessibility. Enter ems and rems, two font size-relative units that provide the accessibility benefits missing in pixels, but arguably lack their intuitive semantics. Naturally, over the years there have been dozens of blog posts debating one approach or the other (Ben Frain’s “Just Use Pixels” and Nicolas Hoizey’s “People don’t change the default 16px font size in their browser,” just to name a few).

Here at the Internet Archive, we have some folks on both sides of the issue, and when the question of moving from pixels to rems and ems came up we didn’t have much solid evidence for one or the other. Many of the old arguments rely on untested assumptions; the pro-pixel crowd assumes that almost no one changes their browser or OS font size, while rem/em supporters assume that lots of people do. It seemed that if we were going to make a decision that could affect the user experience for our users, we should have some data to back it up.

The question was “How many users browse the main Internet Archive site with a default font size other than the common value of 16 pixels?” By knowing this, we would determine how many users would be affected by sizing with relative units like rems/ems.

Using the methodology I describe below, we found that the answer is 3.08% of our users. That’s a pretty big number, higher than most counts of the market share of browsers like Internet Explorer, Edge, or Opera Mini.

The Data

We use Google Analytics (albeit heavily anonymized to protect our users’ privacy), so we opted to send the font size via a Custom Dimension, which allows for some nice audience segmenting.

| Size    | Percent of Users |
| ------- | ---------------- |
| 16px | 96.92% |
| 20px | 0.50% |
| 19.2px | 0.42% |
| 25.6px | 0.23% |
| 17px | 0.18% |
| 24px | 0.15% |
| 20.8px | 0.15% |
| 14.4px | 0.10% |
| 18px | 0.10% |
| 18.4px | 0.08% |
| 18.56px | 0.07% |
| 14px | 0.07% |

As you can see, there’s a pretty wide spread of sizes, including a couple that are smaller than 16 pixels. That was surprising, since we assumed the only real use case was visually impaired users who need larger font sizes for readability. It’s possible there are users setting smaller sizes in order to fit more content on-screen, maybe because they’re using a small monitor, or it could be due to browsers setting non-16px defaults.

| Browser                     | Percent of Users |
| --------------------------- | ---------------- |
| Chrome (desktop) | 37.81% |
| Android Webview | 12.89% |
| Opera Mini | 10.88% |
| Firefox (desktop) | 9.17% |
| Samsung Internet | 5.56% |
| Internet Explorer (desktop) | 5.26% |
| Chrome (mobile) | 5.16% |
| Android Browser | 4.35% |
| Safari (desktop) | 3.26% |
| UC Browser | 2.35% |
| Opera (desktop) | 1.07% |
| Internet Explorer (mobile) | 0.32% |
| Safari (mobile/tablet) | 0.29% |

So what browsers are these folks using? Some of the results here match the general population pretty closely (Desktop Chrome, for example), but there are disproportionate numbers of non-16px users on Android Webview, Opera Mini, Samsung Internet, and Desktop IE. Chrome and Safari’s mobile versions are notably absent from the top five. iOS Safari’s low numbers are likely the result of its poor support for font size customization. The last time I tested, I couldn’t find a way to change the font size at all (the OS setting doesn’t affect the browser)!

The Code

The idea here is pretty simple: I needed to find out the size the browser was going to use without any author-defined styles and set that as a GA Custom Dimension. However, we use Bootstrap, which applies a base font size of 62.5% (10px when the default is 16px) on the element.

I considered two possible approaches:

#1: Compute the style based on the root element and then reverse Bootstrap’s 62.5% modification.

const original = window.getComputedStyle(document.documentElement).fontSize;
const number = parseFloat(original, 10);
const unit = original.replace(/(\d*.\d+)|\d+/, '');
const defaultFontSize = (number * 1.6) + unit;

#2: Create a <div> and assign it a font-size of medium to reset its size to the default.

const div = document.createElement('div');
div.style.fontSize = 'medium';
document.body.appendChild(div);
const defaultFontSize = window.getComputedStyle(div).fontSize;
document.body.removeChild(div);

#2 seems more straightforward since it doesn’t rely on magic numbers or math, but it leaves out users who may set a custom font size via browser extensions or custom stylesheets rather than the browser/OS settings. That said, if you’re running this test on a site that has an explicit pixel size set on the root <html> element already (i.e. font-size: 16px), you may be forced to go this route.

For the Archive’s test, I went with #1. However, it has its own bit of inconvenience: older versions of Internet Explorer have rounding issues that result in values like 9.92px instead of 10px when applying Bootstrap’s 62.5% font-size. When we reverse that calculation we end up with 15.888px instead of 16px. We opted to track the 15.888px values in GA but treat them as equivalent to 16px when analyzing users.

Here’s what it looks like when it’s all put together:

function setDefaultFontSizeCustomDimension() {
// Ignore very old browsers.
if (!('getComputedStyle' in window)) {
return;
}
  // Get the <html> font size.
const original = window.getComputedStyle(document.documentElement).fontSize;
  // Undo the 62.5% size applied in the Bootstrap CSS.
const numPixels = parseFloat(original, 10);
const unit = original.replace(/(\d*\.\d+)|\d+/, '');
const defaultFontSize = (numPixels * 1.6) + unit;
  // Our Analytics integration is a little different, but here’s the standard style for reference.
ga('set', 'dimension1', defaultFontSize);
}

EDIT: If you’re wondering why I didn’t consider browser zoom as well, it’s because modern browsers handle zoom by modifying the size of the “reference pixel,” changing how many real pixels a single CSS “pixel” represents. So zoom changes the size of an element in terms of real pixels, but leaves its computed value in CSS the same as it was before, meaning our measurements will work just fine.

As a result of this “reference pixel” behavior, though, both the pixel density of the screen and the zoom level are represented by the same value in JS: window.devicePixelRatio. A non-Retina MacBook at 200% zoom could produce the same devicePixelRatio value as a Retina MacBook at 100%, so tracking it doesn’t provide us a lot of insights.

The Takeaway

Our team has since conducted some more qualitative research about how users tend to use features like browser zoom and custom font sizes, and are currently in the process of switching to relative units for most elements on Archive.org.

I encourage other companies and nonprofits to perform this same test. It’s really easy to set up for most sites (especially if your root font size is already relative) and will yield clear results to help guide your design and development decision-making. If 2 to 3% (or more!) of your users are relying on a custom font size, you should know that so you can either support that user preference or make a conscious decision to not support it. Doing anything less is frankly irresponsible, especially considering that users with larger font sizes may be using those sizes to compensate for visual disabilities.

It’s probably fantasy to hope that this puts an end to the holy war between pixels and rems/ems. I’d prefer to see web professionals spending their time gathering real user data and making informed decisions rather than arguing with each other. But then again, where’s the fun in that?

Like what you read? Give Evan Minto a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.