REM vs PX: Which CSS Unit Should You Use?
Use rem for font sizes and spacing, and px for borders and tiny fixed details. rem scales when someone increases their browser's font size; px does not.
By Mohamed Farhan · Updated Oct 19, 2026
REM, PX and EM compared
| Unit | Relative to | Scales with user font size | Use it for |
|---|---|---|---|
| px | Nothing: a fixed CSS pixel | No | Borders, shadows, small fixed details |
| rem | Root (html) font size | Yes | Font sizes, spacing, layout widths |
| em | Font size of the element itself | Yes | Padding inside buttons, icons next to text |
| % | Parent element's size | Indirectly | Fluid widths |
Why rem is better for accessibility
Many people set a larger default font size in their browser. When your CSS uses px for text, that setting is ignored and the page stays small. With rem, every size built on the root grows proportionally, so the layout keeps its rhythm at the user's preferred size.
Browser zoom scales both px and rem, so the difference shows up specifically with the font size setting, which is exactly the setting many low-vision users rely on.
A practical setup
:root {
/* keep the browser default: 1rem = 16px */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
}
body { font-size: 1rem; line-height: 1.5; }
h1 { font-size: 3rem; } /* 48px */
.card {
padding: var(--space-6);
border: 1px solid #e5e5e5; /* px for hairlines */
}What px actually means
A CSS pixel is not a physical screen pixel. It is a reference unit defined so that one CSS pixel looks roughly the same size on every device at a typical viewing distance. On high-density screens, one CSS pixel may be drawn with two, three or more physical pixels. That is why a 16px font looks similar on a laptop and a phone, even though the phone has many more physical pixels per inch.
Because px is fixed relative to that reference, it does not respond to the user's preferred font size. If someone sets their browser to use larger text, any text sized in px stays the same.
What rem and em mean
rem is relative to the root element's font size. With the default root of 16px, 1rem is 16px everywhere in the document, which makes rem predictable: you always know what 1.5rem means.
em is relative to the font size of the element itself (or its parent, for the font-size property). That makes em useful for values that should scale with a component's own text, such as padding inside a button or the size of an icon next to a label. The downside is compounding: nested elements with em font sizes multiply each other, so a list inside a list inside a list can grow or shrink unexpectedly.
Zoom vs font size settings
Browser zoom (Ctrl or Cmd plus) scales everything, including px, so zoom alone does not show the difference between units. The difference appears when users change the default font size in browser settings, which many people with low vision rely on, often together with zoom.
With rem-based typography and spacing, the page reflows with larger text and keeps its proportions. With px-based typography, the setting is ignored, and users have to fall back to zoom, which may cause horizontal scrolling on some layouts. Supporting both is part of meeting the WCAG requirement that text can be resized up to 200 percent without loss of content or function.
A simple decision rule
- Font sizes: rem.
- Padding, margins and gaps: rem, so spacing grows with text.
- Component-relative details: em, for example button padding or icon size next to text.
- Borders, outlines and shadow offsets: px, so they stay crisp.
- Layout widths that hold text: rem or ch, so line lengths stay comfortable at larger text sizes.
- Breakpoints: em or px; em breakpoints respond to user font size settings.
Common mistakes
- Setting html { font-size: 10px }. This overrides the user's preference entirely. If you want 1rem to equal 10px, use 62.5% instead so it still scales from the user's setting.
- Mixing px and rem for the same kind of value. If headings are in rem but their margins are in px, spacing will look wrong when text is scaled.
- Using em for font sizes in deeply nested components. Compounding em values make sizes hard to predict; rem avoids this.
- Converting 1px borders to rem. A 0.0625rem border can render as 0 or 2 device pixels depending on scale; keep borders in px.
A worked example with 24px
Here is how 24px might appear in real CSS. The card title uses 1.5rem, spacing uses rem values from the same 16px base, and the border stays in px so it remains a crisp hairline. If a visitor's default font size is 20px, the title grows to 30px and the spacing grows with it, while the border stays 1px.
.card-title {
font-size: 1.5rem; /* 24px */
line-height: 1.25;
margin-bottom: 0.5rem; /* 8px */
}
.card {
padding: 1.5rem; /* 24px */
border: 1px solid #e7e5e4; /* stays px */
}Converting in Sass, CSS variables and JavaScript
If you convert values often, let your tools do it. In Sass, a small function such as rem($px) that returns math.div($px, 16px) * 1rem turns rem(16px) into 1rem at compile time. In plain CSS, you can keep the pixel value readable with calc(16 / 16 * 1rem), which modern browsers resolve to 1rem.
In JavaScript, for example when generating inline styles or design tokens, divide by the root font size: 16 / 16 = 1. If you need the live root size (for users who changed their default), read parseFloat(getComputedStyle(document.documentElement).fontSize) instead of assuming 16.
Naming 16px as a design token
Design systems rarely use raw numbers in components. Instead, 16px would live in a token such as --font-size-base for type or --space-4 for spacing, defined once as 1rem. Components then reference the token, so a later change to the scale updates every use at once.
If your team uses Figma variables or a tokens file (for example in the W3C design tokens format), store the value in px for designers and generate the rem version in the build step. That keeps both sides speaking the same language while the shipped CSS stays accessible.
How browsers resolve rem
When the browser computes a rem value, it multiplies it by the computed font size of the html element. That font size starts from the user's default (16px unless they changed it), then applies whatever your CSS sets on html. So 1rem means "1 times the root size", and it is resolved once per page, unlike em, which is recalculated at every level of nesting.
Because the root is shared, rem values are predictable across the whole document: a 1rem gap in a sidebar is exactly the same size as a 1rem gap in a modal, regardless of the text size inside each.
16px = 1rem at a 16px root font size
Sources and further reading
- MDN: CSS length units · Definitions of px, rem, em and other length units.
- MDN: font-size · How font sizes and relative units are computed.
- WCAG 2.1: Resize Text · Why text must scale up to 200% without breaking.
- MDN: clamp() · The CSS function used for fluid type.
Conversion pages
Questions people ask
Should I use rem or px for font size?
Use rem. It respects the user's browser font size setting, which px ignores, so text stays accessible.
Should I use rem or px for padding and margins?
rem is usually best so spacing scales with text. Use px for hairline borders and other details that should never grow.
What is the difference between rem and em?
rem is relative to the root font size and is predictable everywhere. em is relative to the current element's font size, so it compounds when nested.
Do media queries use rem or px?
Either works, but em or rem in media queries respond to user font size settings, which can produce more accessible breakpoints.
Is rem better for SEO?
Search engines do not rank pages by CSS unit, but rem improves accessibility and mobile readability, which supports a better user experience.
Should I use rem for icons?
Use rem or em for icons that sit next to text so they scale with it. Fixed decorative icons can stay in px.

↘ Building Inspo AI | AI-Powered Design Research & Builder Platform | Design Engineer.