PX to REM Converter
Type a pixel value, get the rem — plus the CSS line to paste.
Common sizes at this root
| Pixels | rem |
|---|
Browsers use 16px unless html { font-size } sets something else.
How px and rem relate
One rem equals the computed font size of the root element — the <html> tag. Every browser ships with that root at 16px unless the user changed their default or your stylesheet overrode it, so the everyday conversion is simply value divided by 16 going one way and value multiplied by 16 coming back. The unit is not a different kind of pixel; it is a multiplier that resolves to pixels at render time, and that late resolution is the entire point.
Because the multiplier resolves against a value the reader controls, a layout written in rem quietly adapts to somebody who reads at 20px while a layout written in px stays frozen at whatever the designer picked. That is the practical difference behind every "should I use px or rem" argument.
Worked example: the 24px heading
A designer hands you a heading at 24px. With the default root of 16px, 24 / 16 = 1.5, so the CSS is font-size: 1.5rem;. Check it backwards: 1.5 x 16 = 24. Now suppose the reader has set their browser default to 20px. Your heading renders at 1.5 x 20 = 30px, keeping the same visual ratio to body text that the design intended. Had you written 24px, that reader would get a 24px heading sitting on 20px body copy — a hierarchy that has quietly collapsed from 1.5x down to 1.2x.
The same arithmetic covers the rest of a typical scale: 12px is 0.75rem, 14px is 0.875rem, 18px is 1.125rem, 32px is 2rem, 48px is 3rem. The reference table in the tool prints exactly these for whatever root you enter, which is faster than doing twelve divisions by hand every time a design system changes its base size.
Reverse direction: reading rem back to px
Inspecting somebody else's stylesheet, you find padding: 1.25rem 2.5rem;. At a 16px root that is 20px vertical and 40px horizontal — numbers you can compare against a Figma frame. Switch the tool to rem to px, and the arithmetic is 1.25 x 16 = 20. If the project uses the 62.5% trick and its root is 10px, the exact same declaration means 12.5px and 25px instead. Always check the root before trusting a conversion; it is the single most common source of "the numbers don't match the design" confusion.
Why accessibility guidance keeps pointing at rem
WCAG success criterion 1.4.4 (Resize Text) requires that text can be scaled up to 200% without loss of content or functionality. Full-page browser zoom passes that criterion regardless of unit, which is why some developers conclude px is fine. The gap is the browser's own default-font-size setting, used heavily by readers with low vision who prefer larger text without magnifying every image and border. Chrome, Firefox, Safari and Edge all expose it; text sized in px ignores it completely. Sizing type in rem, and container padding around type in rem, means one settings change does the right thing across the whole page.
There is a second, less discussed benefit: consistency. Because every rem points at one number, changing the root font size in a single media query rescales an entire type system. Bumping the root from 16px to 17px on wide screens is a one-line change; doing the same in px means touching every declaration.
The 62.5% trick, honestly
Writing html { font-size: 62.5%; } makes the root 10px on a default browser, so 1.8rem is 18px and mental conversion disappears. The upsides are real: no calculator, no odd decimals like 0.875rem, and user zoom and user font-size settings still work because 62.5% is relative, not absolute. The downsides are equally real. You must explicitly set body { font-size: 1.6rem; } or the whole document inherits 10px text, any component you paste in from a library sized in rem shrinks to 62.5% of its intended size, and every new developer on the project has to learn the local rule. On a greenfield codebase it is a defensible convention; on a shared design system it tends to cause more support questions than it saves keystrokes. If you use it, set the root field in this converter to 10 and the table becomes your project's real scale.
Migrating a px codebase to rem
Do not attempt a global find and replace. Convert in passes, starting where the payoff is highest. Pass one is type: every font-size and line-height. Pass two is the spacing that surrounds type — padding and margins inside text blocks — so that generous type does not get cramped by fixed gutters. Pass three is anything you deliberately keep in px: borders, shadow offsets, hairline dividers, sprite coordinates and image dimensions.
A useful shortcut for pass one is to search your stylesheet for font-size: and convert only the numbers you find, checking each against the table here. Most projects have fewer than forty distinct type sizes, and half of them collapse into a shared scale once you can see them side by side. Media query breakpoints are a separate decision: em breakpoints respond to the browser font size, px breakpoints do not, and mixing the two in one file is a debugging trap worth avoiding.
Limitations of this converter
It assumes a static root font size, which is what the overwhelming majority of stylesheets use. If your root is set with clamp() or a viewport unit, the rendered rem value changes as the window resizes, and a single number cannot describe it — convert against the smallest and largest root your clamp allows to get the range. Results are rounded to four decimal places, far beyond what any rendering engine distinguishes, and the tool does not touch em, which needs the parent's computed size rather than the root's and therefore cannot be answered by a two-field form.
Sources & further reading
Frequently asked questions
What is the difference between rem and em?
rem is always relative to the root element's font size — usually 16px — so 1.5rem is 24px anywhere on the page. em is relative to the font size of its own parent, so nested elements compound: 0.9em inside 0.9em inside 0.9em lands near 0.73 of the original. That compounding trap is why rem is the safer default whenever you want a predictable size.
Why use rem for font sizes instead of px?
A size in rem scales with whatever default font size the reader set in their browser, while a size in px ignores that preference completely. Someone who raised their default to 20px because 16px is hard to read gets no benefit from px-based type. WCAG 1.4.4 expects text to scale to 200% without breaking the layout, and rem-based type gets you most of the way there for free.
What is the 62.5% trick?
Setting html { font-size: 62.5% } makes the root 10px on a default browser, so 1rem = 10px and 2.4rem = 24px — the arithmetic becomes trivial. The cost is that you must reset body back to about 1.6rem or every unstyled element inherits 10px text, and any third-party CSS sized in rem shrinks by 37.5%. It still honours user zoom and user font-size settings, so it is a legitimate choice — just set the root field here to 10 to match.
When is px still the right unit?
Borders, box shadows, hairline rules and fixed raster artwork are usually better in px, because you want exactly one crisp rule rather than one that becomes 1.5px when someone scales their text. Media query breakpoints are a judgement call: em breakpoints react to the browser font size, px ones do not. The working rule is that anything tied to text should be rem, and anything tied to the device or a bitmap can stay px.