The core difference
A pixel is a fixed CSS length. A rem is a multiple of the root font size, which is 16px by default but can change. So 1rem is 16px until the root size changes, and then every rem value changes with it, while px values stay put.
Accessibility
Many people raise the default text size in their browser or operating system. Font sizes set in rem follow that setting. Font sizes set in px do not, so those readers get no benefit. Browser zoom scales both px and rem, but the text-size setting only affects rem. WCAG success criterion 1.4.4 requires that text can be resized up to 200 percent without loss of content, and rem-based sizing makes that much easier to achieve.
When px is fine
- Borders, outlines and hairlines.
- Box shadows and other decorative effects.
- Fixed assets such as small bitmap icons.
The 62.5 percent trick
Setting html { font-size: 62.5% } makes the root 10px, so 1.6rem equals 16px and the maths is easy. The percentage keeps the reader preference. The cost is that every component and third-party widget that assumes a 16px root now looks smaller, so you must set the body font size back to 1.6rem. Setting the root to a fixed 10px is worse, because it overrides the reader setting.
A practical rule
Use rem for text and for spacing that should scale with text. Use px for details that should stay thin or fixed. Avoid setting font-size on html in px.
Convert your values
Use the px to rem converter, which can convert a whole stylesheet, or the rem to px converter for the other direction. For em as well, read rem vs em.
Convert instantly. Turn px into rem, or rem into px, with your own root size.