PX to REM Converter
To convert px to rem, divide the pixel value by the root font size: rem = px / root. At the browser default root of 16px, 24px / 16 = 1.5rem. Change the base below - 14px for Ant Design, 10px for the 62.5% trick - and the rem and em values follow it; the point value tracks the pixels instead, because 1px is always 0.75pt.
The em field assumes the element inherits the base font size above. In CSS, em resolves against the element's own font-size, and against the parent's font-size when you set font-size itself.
Bulk convert: paste CSS or a list of px values
Every px value is rewritten in rem against the base font size above.
How do I convert px to rem?
The formula is rem = px / root font size, and the reverse is px = rem x root font size. Only the font-size of the root html element counts, no matter how deeply the element is nested, which is what makes rem arithmetic predictable. At the 16px default: 10px = 0.625rem, 12px = 0.75rem, 14px = 0.875rem, 18px = 1.125rem, 20px = 1.25rem and 40px = 2.5rem.
Do not round the result. 15px is exactly 0.9375rem at a 16px root; rounding it to 0.94rem shifts the rendered size to 15.04px and breaks alignment across a grid. Browsers handle sub-pixel lengths and snap them to the device pixel grid when painting, so copy the exact value the converter gives you. The converter prints up to six decimals: exact for roots that divide evenly, such as 16px and 10px, and accurate to a millionth of a rem for one that does not, such as 14px.
px to rem chart at 16px, 14px and 10px root sizes
The same pixel value becomes three different rem values depending on the root your project sets, so this chart lists all three, plus the point equivalent (CSS defines 1px as 1/96 inch and 1pt as 1/72 inch, so 1px = 0.75pt). The 16px and 10px columns are exact. At a 14px root most values do not divide evenly, so they are rounded to four decimals and marked with the approximation sign; the converter above prints more digits.
| Pixels | rem (16 px root) | rem (14 px root) | rem (10 px root) | Points |
|---|---|---|---|---|
| 1px | 0.0625rem | ≈0.0714rem | 0.1rem | 0.75pt |
| 2px | 0.125rem | ≈0.1429rem | 0.2rem | 1.5pt |
| 4px | 0.25rem | ≈0.2857rem | 0.4rem | 3pt |
| 8px | 0.5rem | ≈0.5714rem | 0.8rem | 6pt |
| 10px | 0.625rem | ≈0.7143rem | 1rem | 7.5pt |
| 12px | 0.75rem | ≈0.8571rem | 1.2rem | 9pt |
| 14px | 0.875rem | 1rem | 1.4rem | 10.5pt |
| 16px | 1rem | ≈1.1429rem | 1.6rem | 12pt |
| 18px | 1.125rem | ≈1.2857rem | 1.8rem | 13.5pt |
| 20px | 1.25rem | ≈1.4286rem | 2rem | 15pt |
| 24px | 1.5rem | ≈1.7143rem | 2.4rem | 18pt |
| 28px | 1.75rem | 2rem | 2.8rem | 21pt |
| 32px | 2rem | ≈2.2857rem | 3.2rem | 24pt |
| 36px | 2.25rem | ≈2.5714rem | 3.6rem | 27pt |
| 40px | 2.5rem | ≈2.8571rem | 4rem | 30pt |
| 48px | 3rem | ≈3.4286rem | 4.8rem | 36pt |
| 64px | 4rem | ≈4.5714rem | 6.4rem | 48pt |
| 80px | 5rem | ≈5.7143rem | 8rem | 60pt |
| 96px | 6rem | ≈6.8571rem | 9.6rem | 72pt |
px vs rem vs em: which unit should I use?
The practical split: rem for anything that should follow the reader's text size, em for values that must track the element's own font-size, and px only where a length must stay physically fixed. The example column assumes a 16px root and a 16px parent.
| Unit | Relative to | 20px equals | Best for | Follows the reader's text size |
|---|---|---|---|---|
| px | Nothing - absolute (1px = 1/96 inch) | 20px | Hairline borders, focus rings, exact icon sizes | No |
| rem | The root html font-size | 1.25rem | Font sizes, spacing, breakpoints, whole type scales | Yes |
| em | The element's own font-size (the parent's when you set font-size) | 1.25em | Padding that must grow with the label it wraps | Yes |
| % | The parent's value for that property | 125% | Fluid widths and legacy font-size trees | Yes (font-size) |
Should I use px or rem for padding, margins and borders?
Use rem for padding and margins that should breathe when text grows: button padding, card gutters, section spacing, grid gaps. Keep px for hairlines. A 1px border is one crisp device-independent pixel, while the same border written as 0.0625rem can round down to nothing or blur at certain zoom levels, and the same applies to 2px focus rings and separators. That is why the bulk converter above leaves 1px and 2px values untouched by default and rewrites everything else.
Media queries are the other place rem earns its keep. Inside a media query, rem resolves against the browser's initial font-size rather than your html rule, so a 48rem breakpoint is 768px for a reader on defaults and grows for a reader who raised their text size. Breakpoints in px never move.
How do I convert px to rem in Figma, VS Code and Tailwind?
Figma measures in px, but Dev Mode can output rem: open the Inspect settings, choose Set unit scale and enter your root font size (1rem = 16px by default). VS Code extensions such as cssrem convert through autocomplete and expose the root as a setting - cssrem.rootFontSize, 16 by default - so check it matches before you trust the output on a 14px project. For a whole file, paste it into the bulk box above and set the base first. Tailwind's default scale is already rem-based at a 16px root: one spacing unit is 0.25rem (4px), so 16px is 4, 24px is 6 and 40px is 10.
Sources
About PX to REM Converter
This px to rem converter answers one question: what does a pixel value from your design file become in CSS, at the root font size your project actually uses? Move the base slider - 16px is the browser default, 14px is Ant Design's, 10px is the old 62.5% trick - and every rem and em figure on the page is recomputed against it, so you never have to remember which base a number was written for.
The base to type in is whatever your stylesheet sets on the html element - not the body, and not the font-size of the component you are styling. If no rule sets it, the browser default applies: 16px, unless the reader raised it. In DevTools, select the html node and read its computed font-size; that number is the divisor for the entire sheet. The four framework buttons fill it in for Tailwind, Bootstrap, Material UI and Ant Design.
The differentiator here is bulk mode: paste a stylesheet, a spec dump from Figma or a plain list of numbers and get a rem version back with a count of what changed, ready to copy or to download as CSV. Below the tool you will find the formula in both directions, a 1px to 96px chart at three root sizes with point equivalents, a unit comparison table and ten questions answered in full.
Use Cases
How to use
Set the base (root) font size: 16px is the browser default, 14px matches Ant Design, 10px gives you the 62.5% trick.
Type the pixel value into the Pixels field. The rem, em and pt fields update as you type.
Or work backwards: enter a rem value and read the pixel size it produces at the current root.
Tap any value in the 8px-96px quick chart to load it, or read the full table for 16px, 14px and 10px roots.
Paste a whole CSS block into the bulk converter to rewrite every px value at once, keeping 1px and 2px borders.
Copy the generated CSS declaration, or download the converted px/rem pairs as a CSV for your design handoff.
Pro Tips
- Set the base font size first: it drives every rem and em figure on the page - the fields, the quick chips and the bulk output - so switching to a 14px root rewrites them all at once.
- Keep 1px and 2px borders in px. Sub-pixel borders can round to zero at some zoom levels, which is why bulk mode skips them by default.
- pt does not depend on the root: 24px is 18pt whether your base is 16px or 10px, so the Points field stays put while the slider moves.
- Bulk mode re-runs whenever you move the base slider, so you can see the same stylesheet at a 16px and at a 14px root without pasting it twice.
- Reach for em only when a value must track its own element's font-size, such as button padding around a label, and keep the rest in rem so nothing compounds.
Frequently Asked Questions
Divide the pixel value by the root font size: rem = px / root. The browser default root is 16px, so 24px / 16 = 1.5rem and 10px / 16 = 0.625rem. Only the root element's font-size matters for rem, no matter how deeply the element is nested, and that is exactly what makes the arithmetic predictable across a whole stylesheet.
With the default 16px root, 1rem = 16px, 1.5rem = 24px and 2rem = 32px; multiply instead of divide, px = rem x root. If the root is 14px, as in Ant Design, 1rem drops to 14px and 1.5rem becomes 21px. A rem figure is meaningless without its root size, so always state the base alongside it.
A px font-size ignores the text size a reader chose in their browser, so someone who set their default to 20px still gets your hard-coded 14px. rem is measured against that setting, so every size scales together. WCAG 2.2 success criterion 1.4.4 expects text to survive 200% resizing, and a rem-based type scale does that without a single extra media query.
rem is always relative to the root html font-size. em is relative to the font-size of the element it is written on, except inside the font-size property itself, where it resolves against the parent's font-size. That is why nested font sizes compound: 0.9em inside 0.9em inside 0.9em is 0.729 of the original. rem never compounds, which is why it is the safer default for type scales and layout spacing.
Use rem for padding and margins that should breathe when text grows - button padding, card gutters, section spacing. Keep px for hairlines: a 1px border stays crisp, while the rem equivalent can round down to nothing or blur at some zoom levels. The bulk converter on this page leaves 1px and 2px values in px by default for exactly that reason.
Keep 16px unless a framework forces otherwise, because it matches the browser default. Ant Design ships a 14px root. The 62.5% trick sets html { font-size: 62.5% } so 1rem = 10px and the maths becomes px / 10: 24px is 2.4rem. It still follows the reader's own setting - 62.5% of a 20px default is 12.5px - but you then have to set body { font-size: 1.6rem } or every paragraph renders at 10px, and third-party components built for a 16px root come out too small. All three roots are in the chart above.
Read the value in the inspector and divide by your root: a 28px heading is 1.75rem at 16px, a 12px caption is 0.75rem. Dev Mode can also print rem for you - open the Inspect settings next to the language dropdown, choose Set unit scale and give it your root font size (1rem = 16px by default). Paste a whole exported block into the bulk box above to rewrite every value at once.
Yes, and it is usually better. Inside a media query rem resolves against the browser's initial font-size rather than your html rule, so a 48rem breakpoint equals 768px on defaults and grows for readers who enlarged their text. em behaves the same way there. Breakpoints written in px stay fixed no matter what the reader chose.
No. Browsers compute sub-pixel lengths and snap them to device pixels when painting, so 0.9375rem renders exactly as 15px at a 16px root. Rounding to 0.94rem moves it to 15.04px and that error accumulates across a grid or a vertical rhythm. Copy the exact value the converter prints and let the browser do the snapping.
CSS defines 1px as 1/96 inch and 1pt as 1/72 inch, so 1px = 0.75pt and 16px = 12pt; that is the ratio behind the pt column in the chart. Android's dp is a separate system where 1dp = 1px at 160 dpi, which is why a 16dp Material spacing lands near 16px on the web rather than on a rem conversion.