Px to Rem in CSS: Complete Conversion Guide

If you have ever wondered whether to write padding: 16px or padding: 1rem, this guide is for you. We'll cover what rem actually means, why accessibility-conscious developers reach for it, the exact conversion formula, and how to migrate an existing stylesheet without breaking your design.

Need to convert a value right now?

Open Px to Rem Converter →

The conversion formula

One formula, no surprises:

rem = px ÷ root_font_size
px  = rem × root_font_size

The browser's default root font size is 16px. So the math people memorise:

16px → 1rem
24px → 1.5rem
32px → 2rem
8px  → 0.5rem
14px → 0.875rem

If your stylesheet sets html { font-size: ... } to anything other than 16px, divide by that value instead.

What rem actually is

rem stands for "root em". It is a length unit relative to the font size of the root element — the <html> element. The browser sets a default of 16px on html, but the user can change this in their browser settings, and your CSS can change it too.

Compare it to its cousin em:

  • em is relative to the parent element's font size — and compounds when nested. A 1.2em heading inside a 1.2em container is actually 1.44× the parent's parent size.
  • rem is relative to the root only — no compounding. 1rem is always the same size everywhere on the page.

This is why most modern design systems standardise on rem: a single source of truth that scales the entire UI when needed.

Why rem beats px for accessibility

Open Chrome's settings → Appearance → Font size. You'll see options for "Very small", "Small", "Medium", "Large", "Very large". This setting changes the default font size of the html element. A user with low vision may set it to "Very large" (typically 24px instead of 16px).

Now imagine your button:

/* Pixel-based — ignores user preference */
.button { padding: 12px 24px; font-size: 16px; }

/* Rem-based — scales with user preference */
.button { padding: 0.75rem 1.5rem; font-size: 1rem; }

For a user with the "Very large" setting, the rem version's padding becomes 18px 36px and font becomes 24px — the entire button grows proportionally. The pixel version stays at 12px 24px, with text the user can barely read inside an undersized button.

The WCAG 2.2 — Resize Text success criterion expects content to scale up to 200% without loss of content or functionality. Rem-based layouts pass this naturally; pixel-based layouts often fail.

The 62.5% trick — convenient but controversial

You'll often see this in production CSS:

html { font-size: 62.5%; }
/* 62.5% of 16px = 10px */

body { font-size: 1.6rem; } /* = 16px */
.card { padding: 2.4rem; }  /* = 24px */

Setting the root to 62.5% makes 1rem equal 10px, and the math becomes trivial: 1.6rem is 16px, 2.4rem is 24px, 0.8rem is 8px. Many designers love this because they can think in pixels but write rems.

The problem: you've overridden the user's browser font size preference. A user who set their browser to 20px now gets 20px × 62.5% = 12.5px as the root — smaller than they wanted. The accessibility benefit of rem is partially defeated.

The fix: always restore body text to a sensible size: body { font-size: 1.6rem; } means default text is 16px-equivalent of their root, not yours. The 62.5% only affects sizes you explicitly set. This is a reasonable compromise — but plain rem with no 62.5% override is the purest path.

When to still use px

Don't convert blindly. Some things genuinely belong in pixels:

  • Bordersborder: 1px solid #ccc stays a hairline at any zoom level. 0.0625rem rounds inconsistently across browsers and can look fuzzy.
  • Box shadows — Same idea. A 0 2px 4px rgba(0,0,0,0.1) shadow has a designed look that doesn't benefit from scaling.
  • Outline width — Focus rings and outlines are usually defined as 2px or 3px for visual consistency.
  • Image dimensions — When you need an image to fit a known pixel grid (favicons, sprites, app icons), use px or no unit at all.
  • Media query breakpoints — Modern recommendation is em (which respects browser zoom), but px is still common and acceptable.

Migrating an existing stylesheet

You don't have to convert everything at once. A pragmatic migration:

  1. Convert font sizes first. They have the biggest accessibility impact.
    /* Before */
    h1 { font-size: 32px; }
    p  { font-size: 16px; }
    
    /* After */
    h1 { font-size: 2rem; }
    p  { font-size: 1rem; }
  2. Convert spacing — padding, margin, gap. These also benefit from scaling.
    /* Before */
    .card { padding: 24px; margin-bottom: 16px; }
    
    /* After */
    .card { padding: 1.5rem; margin-bottom: 1rem; }
  3. Leave borders, shadows, and 1–2px decorative widths alone. They are fine as px.
  4. Test with browser zoom + custom font size. Set Chrome to "Very large" font and zoom to 200%. Your layout should remain usable.

For large stylesheets, our Px to Rem Converter has a bulk mode — paste your CSS, click "Convert px → rem", and review the output before committing.

Common conversions reference

Assuming the standard 16px root:

Pixels Rem Common use
8px0.5remTight spacing, small gaps
12px0.75remCaptions, helper text
14px0.875remSecondary text, labels
16px1remBody text (default)
18px1.125remSlightly larger body
20px1.25remLead paragraphs, h4
24px1.5remCard padding, h3
32px2remSection spacing, h2
48px3remLarge headings, h1
64px4remHero text, big margins

Sass / SCSS helpers

If you write Sass, a small function turns the conversion into a one-liner:

// _functions.scss
@function rem($px, $base: 16) {
  @return ($px / $base) * 1rem;
}

// usage
.card {
  padding: rem(24);     // → 1.5rem
  font-size: rem(14);   // → 0.875rem
}

Note: in modern Sass (1.65+), division uses math.div():

@use "sass:math";

@function rem($px, $base: 16) {
  @return math.div($px, $base) * 1rem;
}

CSS-only with custom properties

You can do the same in plain CSS using a custom property:

:root {
  --base-font-size: 16;
}

.card {
  /* calc with unit-less variable */
  padding: calc(24 / var(--base-font-size) * 1rem);
}

This is verbose but eliminates the build step. Most teams just compute the rem values upfront and write them directly.

Need to convert a stylesheet? Use the free Px to Rem Converter →