What rem actually measures
A rem is one root em: the computed font size of the html element. Unlike em, which resolves against the font size of the current element and therefore compounds through nested elements, rem always resolves against the same single value no matter how deeply nested the rule is. That predictability is why design systems standardized on it.
In every mainstream browser the default root font size is 16 pixels unless something changes it, which is why 16 is the default here and why 1rem equals 16px in most projects. Divide a pixel value by the root size to get rem, multiply to go back. 24px is 1.5rem, 14px is 0.875rem, and 13px is 0.8125rem.
If your project sets a different root size, change the field. Some codebases set html to 62.5 percent so that 1rem equals 10px and the arithmetic becomes trivial, which makes 24px into 2.4rem instead. The converter follows whatever number you give it, and an invalid or non-positive entry falls back to 16 rather than producing nonsense.
- A rem resolves against the html font size, so it never compounds like em
- Default root size is 16, which makes 1rem equal 16px
- Set the root to 10 and 24px becomes 2.4rem instead of 1.5rem
Why rem matters for accessibility
This is the practical reason to convert rather than a stylistic preference. A user who has increased the default text size in their browser settings is changing the root font size, and every rem-based value scales with it. A pixel value ignores that setting completely.
The consequence shows up in real layouts. A component sized in pixels with text sized in rem will overflow when someone doubles their font size, because the text grew and the box did not. Sizing the padding, the gaps, and the max-widths in rem alongside the text keeps the whole component in proportion.
Not everything should be rem, though. Borders are the standard exception: a 1px border is meant to be a hairline and looks wrong scaled up, so leaving it in pixels is deliberate. The same argument often applies to small decorative offsets and to anything that should stay pinned to the device pixel grid.
The bulk CSS conversion, and its rough edges
The bulk box takes a block of CSS and rewrites every pixel value in it. It handles decimals and negative numbers, and it turns 0px into a bare 0, which is what most style guides prefer anyway. For converting an existing stylesheet to rem it removes a great deal of tedious arithmetic.
It works by pattern matching over the text rather than by parsing the CSS, and that is worth knowing before you paste something important. It will convert a px value inside a comment, inside a string, and inside a url. It does not know that your 1px borders were meant to stay in pixels, and it will convert those too, so review the output rather than pasting it back unread.
The bulk direction is px to rem only; there is no bulk rem to px pass. And the whole conversion is textual, so anything it rewrote incorrectly has to be put back by hand. On a small block that is trivial. On a large stylesheet, convert in sections and check as you go.
- Handles decimals and negatives, and turns 0px into 0
- Pattern-based, so it also rewrites px inside comments, strings, and url()
- Bulk mode is px to rem only, and it will convert your 1px borders