PX to REM Converter
px ⇄ rem at any root size — one value, or your whole stylesheet.
runs entirely in your browser16px is 1rem at a 16px root font size.
Common values at a 16px root
Click or tap a row to load it into the converter.
Convert a whole CSS block
.card {
padding: 1.5rem 1rem;
border: 0.063rem solid #ddd;
font-size: 0.875rem;
}Converts on your device. Nothing you type or paste leaves this page.
The formula, and what the root font size actually is
One rem is the computed font size of the root element — the html element — so converting between the two units is a single division: rem = px ÷ root font size. Browsers ship a default root of 16px, which is where 1rem = 16px, 24px = 1.5rem, and 10px = 0.625rem come from. Change the root and every rem in the document changes with it; that is the entire point of the unit.
The root is set by whatever rule wins on the html element. If nothing in your CSS touches it, the root is the visitor's browser default, which is 16px unless they changed it. That last clause is the part most conversion tables leave out: the 16 in the formula is not a constant in the spec, it is a default the user is allowed to move.
Set the root font size field on this page to whatever your project uses and the converter, the common-values table, and the batch output all recompute against it together. Most tools freeze their tables at 16 and quietly stop being right the moment you deviate.
px or rem — the decision, concretely
Use rem for anything that should scale with the reader: body text, headings, the padding and margins around them, and the widths that keep a line of text at a comfortable measure. Use px for things that are artifacts of the display rather than the content: hairline borders, a 1px focus ring offset, the exact pixel dimensions of an icon that was drawn on a pixel grid.
The accessibility argument is narrower and more specific than it is usually stated. Browser zoom scales everything, px included, so zoom is not the problem. The setting that matters is the browser's default font size preference — the one in the appearance settings that a reader with low vision may have moved from 16px to 20px or 24px. Text sized in rem follows that preference. Text sized in px ignores it completely, and a layout that mixes the two will have its type grow while its containers stay put.
This is why the conversion usually runs one way in practice. A design file hands you pixels, because that is what design tools measure in, and the codebase wants rem, because that is what respects the reader. The batch converter below exists for exactly that handoff.
The 62.5% trick, and what it costs
Writing html { font-size: 62.5% } makes 1rem equal 10px for a visitor on the 16px default, which turns the arithmetic into moving a decimal point: 24px is 2.4rem, 18px is 1.8rem. It is written as a percentage rather than as font-size: 10px on purpose — a percentage is relative to the visitor's own default, so someone who raised theirs to 20px gets a 12.5px root and keeps their scaling. A hard 10px would take that away and is the version to avoid.
What it costs is every assumption anyone else made. Third-party CSS, component libraries, and Tailwind's default scale are all authored against a 16px root, so dropping them into a 62.5% document renders them at roughly five-eighths of their intended size. That is fixable — you rescale the offending styles — but it is real work, and it is why the trick has fallen out of fashion.
There is one place the trick does not reach, and it surprises people: media conditions. Font-relative units inside a media query resolve against the initial font size, not against anything your CSS declares on the root element, so a 48rem breakpoint is 768px whatever you did to html. The batch converter on this page follows that rule — it converts breakpoints against 16 even when you have set a different root — because converting them against your root would silently move every breakpoint in the file.
Converting a whole stylesheet
Paste CSS into the batch box and every length in the source unit is converted in place. Everything else is preserved exactly as written, so the result diffs cleanly against what you pasted: selectors, comments, colours, and the values in other units all come back byte for byte.
Three things are deliberately left alone, because rewriting them would change what the page does rather than what it measures. Text inside quotes is a literal, so content: "16px" stays as it is. The bodies of url() are addresses, so a file named sprite-16px.png keeps its name. Comments are left intact so a note recording an old value still records it. Identifiers are protected the same way — a class called .p-16px and a custom property called --space-16px are names, not measurements.
The leave 1px values as px toggle covers the one case where a blanket conversion is usually wrong. Hairline borders are drawn against the display, not the type, and 0.0625rem is both harder to read and slightly more likely to land on a subpixel. Turn it on and 1px and -1px survive the conversion untouched while everything else converts.
The box also accepts a bare list of numbers. Paste 12 16 24 out of a design file and you get the converted values back with the unit attached, which is faster than converting them one at a time and is the same arithmetic either way.
Rounding, and why the numbers look the way they do
Conversion is done at full precision and rounded only when it is printed, so nothing here ever shows 0.30000000000000004. Trailing zeros are trimmed as well: 0.5rem rather than 0.500rem, because the latter is noise in a diff.
The batch converter offers two, three, or four decimal places, defaulting to three. Three is enough for any real value at a 16px root — the awkward ones are the odd pixel sizes, where 13px is exactly 0.8125rem and rounds to 0.813rem, a difference of eight thousandths of a pixel. The converter fields above show four places because they answer what a value IS rather than how you want it written, so typing 13 there gives you the exact 0.8125rem.
Copying anywhere on this page copies what you can see. The displayed value is the value, which matters when a rounded number is about to be pasted into a file.
fair questions
- Is 1rem equal to 16px?
- By default, yes — browsers ship a 16px root font size, so 1rem computes to 16px. It stops being true in two situations: your own CSS sets a different font size on the html element, or the reader changed their browser's default font size preference. To check yours, open devtools and read the computed font-size on the html element.
- What is 24px in rem?
- 1.5rem at the default 16px root, because 24 ÷ 16 = 1.5. At a 10px root it is 2.4rem instead. The general formula is rem = px ÷ root font size, and the table above lists the sizes people convert most often at whatever root you set.
- Should I use px or rem in CSS?
- Use rem for type and for the spacing around type, so it scales when a reader raises their browser's default font size. Use px for display artifacts that should not scale — hairline borders, focus-ring offsets, and icons drawn on a pixel grid. Browser zoom scales both, so zoom is not the deciding factor; the browser's font size preference is.
- Does rem depend on the parent element?
- No — that is em. A rem always resolves against the root element's font size, no matter how deeply nested it is, which is what makes it predictable. An em resolves against the font size of the element it is used on, except when it is used on font-size itself, where it resolves against the parent's. That difference is why nested em values compound and nested rem values do not.
- Can I convert my whole stylesheet at once?
- Yes — paste it into the batch box. Every length in the source unit converts and everything else is preserved byte for byte, including comments, quoted strings, url() bodies, and identifiers like .p-16px. The 1px toggle keeps hairline borders in pixels. Nothing is uploaded; the conversion runs in your browser.
- Why do media query breakpoints convert differently?
- Because the spec says they do. Font-relative units inside a media condition resolve against the initial font size rather than against whatever your CSS sets on the root element, so a 48rem breakpoint means 768px regardless. This converter follows that rule and converts breakpoints against 16 even when you have set a different root — otherwise a stylesheet using a 10px root would come back with every breakpoint moved.
related tools
this site is built on Guardrails, the guard-railed boilerplate for shipping real products with AI agents.