Tips・When you get stuck

Which CSS unit should I use?

px, rem, %, vw—which unit should you actually put after the number in CSS? Here we sort out what the four units really are and the "when in doubt, use this" guide, complete with a working demo.

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

UnitWhat it isExample
pxA fixed size (based on the screen’s dots)font-size: 16px
%A ratio of the parent’s sizewidth: 50% = half of the parent
remA multiple of the page’s base font size (16px by default)1.5rem = 24px
vw/vhA ratio of the screen’s width/height100vh = 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.

pxremMain use
12px0.75remAnnotations and supplementary text
14px0.875remSlightly smaller body text
16px1remStandard body text
20px1.25remSmall headings
24px1.5remHeadings
32px2remLarge 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.

What the slider recreates is the behavior when a user changes the font size in their browser settings. Only the rem paragraph follows along.

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.

UnitWhat it isWhere it shows up
emA multiple of that element’s own font sizeSyncing a button’s padding to its text, etc.
dvhThe actually visible screen heightCountering the 100vh slip on phones
frGrid-only. A share of the leftover spacegrid-template-columns: 1fr 2fr
chThe width of one “0” digitDeciding 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 sizerem (considerate, since it syncs with the user’s settings). px is OK while you’re practicing
  • Spacing and line thicknesspx (easy to fine-tune, and it won’t drift)
  • Width% or max-width (shrinks to match the screen)
  • Full screen height100vh

“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 course

Summary

  1. 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
  2. Setting text in rem is considerate—it syncs with the browser’s font-size setting
  3. 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.

FAQ

How are rem and em different?
rem is always a multiple of the page's base size (16px by default), while em is a multiple of "that element's own font size" (the parent's font size becomes the reference only when you use em on font-size). em tends to drift in the math when nested, so when in doubt, using rem is recommended.
Is it bad to write everything in px?
While you're practicing it's no problem. However, if you fix font sizes in px, the change may not take effect for people who've set a larger font size in their browser. For a page you're publishing, using rem for the text is the considerate choice.
How many px is 1rem?
By default it's 16px. If you want 24px, you can convert with 24 ÷ 16 = 1.5rem—just divide by 16.
Why does the bottom get slightly cut off on a phone even though I set 100vh?
It's because a phone's browser changes the screen height by the amount of the address bar. Using the newer unit dvh (the actually visible height) lets you avoid this problem. You write it like 100dvh, with the same feel as vh.