PX to REM Converter

Convert px to rem one value at a time, look up common sizes in the table, or paste a stylesheet and convert every pixel value in it at once. The converter skips comments, strings and url() paths, so icon-24px.svg stays a filename.

Convert a value

em assumes the parent's font size equals the base. 1pt = 1/72 inch = 1.333px.

pxrempt
CSS with px
Converted CSS

1 PX to REM Converter example

Base 16, Keep 1px on, Skip @media on. The border stays a 1px hairline and the breakpoint stays in pixels. Every other px value becomes rem.

Before

.card {
  padding: 16px 24px;
  margin-bottom: -8px;
  border: 1px solid #e2e8f0;
  font: 14px/1.5 system-ui;
}
@media (min-width: 768px) {
  .card { padding: 32px; }
}

After

.card {
  padding: 1rem 1.5rem;
  margin-bottom: -0.5rem;
  border: 1px solid #e2e8f0;
  font: 0.875rem/1.5 system-ui;
}
@media (min-width: 768px) {
  .card { padding: 2rem; }
}

2 rem follows the reader's text size setting

A rem is the font size of the root element. Say a visitor sets their browser's default text size to 20px because 16px is too small for them. Everything sized in rem grows with it, and everything sized in px stays the same. Browser zoom scales both units, so the difference only shows for people who changed the text size setting, and those are the readers who need it.

Set Base to the root font size your CSS uses. That is 16px unless your CSS sets html { font-size }. The older 62.5% trick makes 1rem equal 10px so the math is easy. If your stylesheet uses it, set Base to 10.

3 What to leave in px

Hairline borders

Keep 1px borders in px. As 0.0625rem, a border becomes 0.75px for someone whose default text size is 12px, and browsers round fractional borders inconsistently. Keep 1px leaves both 1px and -1px unchanged.

Media queries

rem in a media query always uses the browser default, never your html font-size. Converting breakpoints makes them follow the user's text setting. Turn on Skip @media if you want the layout to switch at fixed widths instead.

em is relative to the parent

Choose em output only for spacing that should scale with the element's own text, such as button padding. Nested em font sizes compound, so 1.2em inside 1.2em is 1.44 times the base.

What the converter skips

The converter leaves zero values alone, along with anything inside comments, quoted strings and url(), and px inside identifiers such as a class named .w-16px. It rounds results to four decimal places.

How to use the PX to REM Converter tool

  1. Set Base (px) to your root font size: 16 unless your CSS sets html { font-size } to something else, 10 if you use the 62.5% trick.
  2. Type into any of the px, rem, em or pt boxes and the other three update. Click a row in the table to copy that rem value.
  3. To convert a stylesheet, paste it into the CSS with px panel or click Dummy Data. The tool converts every px value as you type.
  4. Choose rem or em in CSS to, and use Keep 1px and Skip @media to leave hairlines and breakpoints in pixels.
  5. Click Copy CSS to take the converted stylesheet. The counter shows how many values were changed.

How to convert px to rem in code and in your build

JavaScript

const pxToRem = (px, base = 16) => +(px / base).toFixed(4) + "rem";

console.log(pxToRem(24));      // "1.5rem"
console.log(pxToRem(14, 10));  // "1.4rem"

// Convert every px value in a CSS string, leaving 0 and 1px alone.
// (No handling of comments or url() here; the tool on this page does that.)
function convertCss(css, base = 16) {
    return css.replace(/(-?\d*\.?\d+)px\b/g, (m, n) => {
        const v = Math.abs(parseFloat(n));
        return v === 0 || v === 1 ? m : pxToRem(parseFloat(n), base);
    });
}

console.log(convertCss(".card { padding: 16px 24px; border: 1px solid; }"));
// .card { padding: 1rem 1.5rem; border: 1px solid; }

In a build pipeline, the postcss-pxtorem plugin does this on every compile, so you can keep writing px in source if you prefer.

SCSS function

@use "sass:math";

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

.card {
    padding: rem(16px) rem(24px);   // 1rem 1.5rem
    font-size: rem(14px);           // 0.875rem
    border: 1px solid #e2e8f0;      // hairline stays in px
}

math.div replaced the / operator for division in Dart Sass. The old slash form prints a deprecation warning and will stop working in a future release.

Python

import re

def px_to_rem(css: str, base: float = 16) -> str:
    def repl(m):
        value = float(m.group(1))
        if abs(value) in (0, 1):
            return m.group(0)
        return f"{round(value / base, 4):g}rem"
    return re.sub(r"(-?\d*\.?\d+)px\b", repl, css)

print(px_to_rem(".card { padding: 16px 24px; margin: -8px; border: 1px solid; }"))
# .card { padding: 1rem 1.5rem; margin: -0.5rem; border: 1px solid; }

Common errors and how to fix them

Everything is 1.6 times too large after converting
The stylesheet assumed html { font-size: 62.5% } (1rem = 10px) but the values were converted with base 16, or the other way around. Set Base to the root size your CSS uses and convert again.
Text inside nested components keeps getting bigger
The values were converted to em, and em font sizes compound through each level of nesting. Convert font-size to rem and keep em only for spacing that should follow the element's own text.
Borders disappear or look blurry on some screens
A 1px border converted to 0.0625rem produces a fractional width when the root size is not exactly 16px. Keep hairline borders in px.
A class name or image path changed after conversion
A plain find-and-replace also hits text like .mt-16px or icon-24px.svg. This tool skips identifiers, comments, strings and url(). If you write your own regex, make it skip the same places.

Good to know

The rem unit arrived with CSS3 and has been supported by every browser since IE9. Before it, em was the only relative option, and em values compound through nested elements, which made layout sizing hard to predict. rem avoids that by always measuring from the html element.

Convert to rem so your layout follows the browser's default font size setting. Page zoom scales px and rem equally, so zoom is unaffected. What px ignores is the separate text size setting, which many people with low vision change. WCAG 1.4.4 asks that text can be resized to 200% without loss of content, and rem-based layouts make that easier to meet.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

How do I convert px to rem?

Divide the pixel value by the root font size. With the default 16px root, 24px is 24 / 16 = 1.5rem and 12px is 0.75rem. If your CSS sets html { font-size: 62.5% }, the root is 10px and you divide by 10 instead.

What is the difference between rem and em?

rem is relative to the root element's font size, so it means the same thing everywhere on the page. em is relative to the font size of the element itself (or its parent, when used for font-size), so nested em values compound.

Is 1rem always 16px?

Only by default. 1rem equals the html element's font size, which is 16px in every major browser unless the user changed their default text size or your CSS overrides it. That user setting is the main reason to use rem.

Should I convert 1px borders to rem?

Usually not. A hairline should stay 1px, and 0.0625rem turns into a fractional width when a user's text size is not 16px. The Keep 1px option leaves 1px and -1px untouched.

How many pixels is 1pt?

In CSS, 1pt is 1/72 of an inch and 1px is 1/96 of an inch, so 1pt = 1.333px and 12pt = 16px. Points are for print stylesheets; on screen, use px or rem.

Related

Once the sizes are in rem, lay them out with the CSS grid generator or the flexbox generator. To tidy the converted stylesheet, run it through the CSS formatter.

More CSS & Design Tools

Browse all css & design tools

Copied to clipboard!