font-size: 16px, width: 50%, margin: 1rem—the unit that goes after a number in CSS: you end up wondering which one to use, right? In this article, we’ll sort out what the four common ones really are and the “when in doubt, use this” guide.
What the four units really are
| Unit | What it is | Example |
|---|---|---|
px | A fixed size (based on the screen’s dots) | font-size: 16px |
% | A ratio of the parent’s size | width: 50% = half of the parent |
rem | A multiple of the page’s base font size (16px by default) | 1.5rem = 24px |
vw/vh | A ratio of the screen’s width/height | 100vh = the full screen height |
The important thing is that “what size it’s based on” differs for each. Only px is fixed; the other three grow and shrink in sync with something.
px is “the size as-is”
The most intuitive unit. It becomes exactly the size of the number you wrote. It suits places where you don’t want things to grow or shrink, like the thickness of a border (border: 1px) or fine spacing.
.card {
border: 1px solid #eee; /* the line thickness should always stay 1px */
border-radius: 12px; /* the corner radius can be fixed too */
padding: 16px; /* fixed inner spacing is easy to handle */
}Put another way, px doesn’t change no matter how narrow or wide the screen is. A flexible spec like “full width on a phone, half on a computer” can’t be written in px—that’s where the next three come in.
% is decided by “the parent’s size”
width: 50% is “half of the parent’s width.” When the screen gets narrower the parent shrinks too, so it shrinks along with it. It’s the go-to when you want widths to be flexible.
img {
max-width: 100%; /* the standard "don't spill out of the parent" */
}rem is a multiple of “the base font size”
rem is a multiple where the page’s base font size (16px by default) is 1. 1rem = 16px, 1.5rem = 24px. You can convert by dividing by 16. The conversions for commonly used sizes are as in this table.
| px | rem | Main use |
|---|---|---|
| 12px | 0.75rem | Annotations and supplementary text |
| 14px | 0.875rem | Slightly smaller body text |
| 16px | 1rem | Standard body text |
| 20px | 1.25rem | Small headings |
| 24px | 1.5rem | Headings |
| 32px | 2rem | Large headings |
rem’s real strength is that it syncs with the browser’s font-size setting. On the page of someone who has set “make text larger,” text written in rem gets properly bigger. Text written in px won’t get bigger even if they change the setting.
vw/vh are decided by “the screen’s size”
100vw = the full screen width, 100vh = the full screen height. It’s the standard when building a hero section that fits the screen exactly.
.hero {
height: 100vh; /* a hero the full height of the screen */
}Other units you’ll see now and then
You won’t reach for these often, but it’s reassuring to be able to read them.
| Unit | What it is | Where it shows up |
|---|---|---|
em | A multiple of that element’s own font size | Syncing a button’s padding to its text, etc. |
dvh | The actually visible screen height | Countering the 100vh slip on phones |
fr | Grid-only. A share of the leftover space | grid-template-columns: 1fr 2fr |
ch | The width of one “0” digit | Deciding an input field’s width by character count, etc. |
em is very similar to rem, but its reference is “that element’s own font size” rather than “the whole page.” With padding: 1em, the spacing equals that element’s font size. However, only when you use em on font-size itself does the parent’s font size become the reference, so nesting multiplies the ratios and it tends to drift—when in doubt, choosing rem is fine.
When in doubt, use this guide
- Font size →
rem(considerate, since it syncs with the user’s settings).pxis OK while you’re practicing - Spacing and line thickness →
px(easy to fine-tune, and it won’t drift) - Width →
%ormax-width(shrinks to match the screen) - Full screen height →
100vh
“Text in rem, width in %, fine adjustments in px”—just remember these three lines and you’ll rarely be stuck in practice. Applied to real CSS, it looks like this.
h1 { font-size: 2rem; } /* text in rem */
p { font-size: 1rem; }
.container {
max-width: 800px; /* decide only the cap in px */
width: 100%; /* and normally use % to fit the screen */
}
.card {
padding: 16px; /* fix spacing in px */
border: 1px solid #eee; /* the line in px too */
}
.hero { height: 100vh; } /* only full screen height in vh */CSSLet's change the text sizeFor the basics of specifying font size, head to this lesson in the CSS courseSummary
- The difference between units is “what they grow and shrink relative to”—only px is fixed, % is the parent, rem is the base font size, vw/vh is the screen
- Setting text in
remis considerate—it syncs with the browser’s font-size setting - When in doubt: “text in rem, width in %, fine adjustments in px”
Once you can choose units deliberately, you get closer to flexible pages that don’t break on any screen.