CSS Units

Pixels, rems, percentages, viewport units and fluid sizes.

Lesson 11 of 49Beginner14 min read

Almost every size in CSS needs a unit: 16px, 2rem, 50% or 100vh. Choosing the right unit is the key to layouts that adapt to any screen, and to text that respects visitors who set a larger font size in their browser.

Units fall into two groups. Absolute units, like pixels, are always the same size. Relative units depend on something else, such as the font size, the parent element or the size of the browser window. Most modern CSS uses relative units for text and layout, and pixels for small fixed details.

Absolute units: px

px (pixels) is a fixed size. It's easy to understand and ideal for borders, shadows and other small details. However, if you size text in pixels, it may ignore the font size a visitor has chosen in their browser settings, which matters to people with low vision.

A CSS pixel isn't always one physical dot on the screen. High-resolution phones use several physical dots for each CSS pixel, which is why a 16px font looks a similar size on a laptop and a phone.

Font-relative units: rem and em

  • rem is relative to the root (<html>) font size, which is usually 16px. 1rem is 16px and 1.5rem is 24px, wherever you use it. It's the best default for font sizes and spacing.
  • em is relative to the current element's font size. It's great for button padding, because bigger text automatically gets bigger padding. Be careful with nesting, though: an em inside an em multiplies, which can produce surprising sizes.

If a visitor increases their browser's default text size, everything sized in rem grows with it, keeping the layout in proportion.

Space-relative units: %, vw, vh and ch

  • % is a percentage of the parent element's size. width: 50% means half the width of the parent.
  • vw is 1% of the viewport width, so 100vw is the full window width.
  • vh is 1% of the viewport height, so 100vh is the full screen height. On phones, 100dvh adjusts for browser toolbars that appear and disappear.
  • ch is the width of the "0" character. max-width: 65ch keeps lines of text a comfortable length.

Fluid sizes with min(), max() and clamp()

CSS
width: min(600px, 90%);              /* whichever is smaller */
font-size: clamp(1.5rem, 4vw, 3rem); /* grow with the screen, within limits */

clamp(minimum, preferred, maximum) makes text grow smoothly from phone to desktop without any media queries. The heading is never smaller than 1.5rem or larger than 3rem, and in between it follows the window width.

CSS Units Syntax

Units at a glance

border: 1px solid;        /* absolute */
font-size: 1.125rem;      /* root-relative */
padding: 0.5em 1em;       /* element-relative */
width: 50%;               /* parent-relative */
min-height: 100vh;        /* viewport-relative */
max-width: 65ch;          /* character-relative */
font-size: clamp(1rem, 3vw, 2rem);

CSS Units Summary

  • px is fixed; relative units depend on the font size, parent or viewport.
  • rem is relative to the root font size and is the safest choice for text.
  • em is relative to the element's own font size and multiplies when nested.
  • %, vw and vh size things relative to the parent or the browser window.
  • min(), max() and clamp() create fluid sizes with sensible limits.

CSS Units Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

rem vs em

Both buttons use the same padding values. The second button has bigger text, so its em padding grows too.

.btn {
  font-size: 1rem;
  padding: 0.5em 1em;
  border: 2px solid #15161b;
  border-radius: 0.5em;
  background: #ffd23f;
}

.big {
  font-size: 1.5rem;
}

.note {
  font-size: 0.875rem;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 21rem = 16px (the browser default).
  2. Line 3Padding in em is relative to this button's own font size.
  3. Lines 10 to 121.5rem is 24px, so 0.5em padding becomes 12px and the button scales up neatly.
  4. Line 15rem is always relative to the root, so this note is predictable.
Example 2

Percentages and viewport units

Open it in the playground and try the phone/tablet sizes.

.parent { width: 300px; background: #e1e6ff; padding: 6px 0; }
.half { width: 50%; background: #4467ff; color: white; }

.banner { width: 60vw; background: #ffe3d7; margin: 10px 0; }

.readable { max-width: 40ch; }
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 250% of the 300px parent = 150px.
  2. Line 460% of the window's width, so it changes when the window resizes.
  3. Line 6About 40 characters wide, whatever the font size.
Example 3

A fluid headline with clamp()

Resize the result (or the window): the heading grows and shrinks smoothly but never gets too small or too big.

.fluid {
  font-size: clamp(1.5rem, 6vw, 3.5rem);
  line-height: 1.1;
}

.box {
  width: min(400px, 90%);
  padding: 1rem;
  background: #d6f4e4;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2At least 1.5rem, ideally 6% of the viewport width, never more than 3.5rem.
  2. Line 7400px wide on big screens, 90% of the parent on small ones.

Common CSS Units Mistakes

Font sizes in px everywhere

Don't
body { font-size: 14px; }
h1 { font-size: 32px; }
Do
body { font-size: 1rem; }
h1 { font-size: 2rem; }

rem respects the user's browser font setting; fixed pixels can override it for people who need larger text.

Forgetting the unit

Don't
.box { width: 300; margin: 20; }
Do
.box { width: 300px; margin: 20px; }

Numbers without units are invalid for lengths (except 0) and get ignored.

CSS Units in Real Projects

Modern responsive sites

Designers increasingly use fluid type with clamp(), layout widths with min() and %, and full-screen hero sections with 100dvh. This "intrinsic design" approach means fewer media queries and layouts that look right at every size in between.

CSS Units Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Make the text 1.25 times the root font size and the box half its parent's width.

.card {
  font-size: 1.25;
  width: 50;
}
Multiple choiceeasy

If the root font size is 16px, what is 2rem?

Multiple choicemedium

What does 100vh mean?

Predict the outputmedium

A parent has font-size: 20px. Its child has font-size: 1.5em. How big is the child's text?

.parent { font-size: 20px; }
.child { font-size: 1.5em; }
Fix the bugmedium

The card should be 320px wide on big screens but never wider than 90% of its container, and the title should use rem. Fix the invalid values.

.wrap { width: 300px; }

.card {
  width: min(320, 90);
  background: #fff1c2;
}

.title {
  font-size: 1.5;
}
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Card is 90% of its 300px container (270px)
  • Title is 1.5rem (24px)

CSS Units Quiz

3 questions to check what you learned.

  1. Which unit is relative to the root element's font size?

    • em
    • rem
    • px
    • vw
  2. What does clamp(1rem, 5vw, 3rem) return on a very wide screen?

    • 1rem
    • 5vw
    • 3rem
    • An error
  3. max-width: 65ch limits text to about…

    • 65 characters per line
    • 65 pixels
    • 65% of the screen
    • 65 words

CSS Units Challenge

Make a fluid hero

Style the hero so that:

  1. .hero has a min-height of 60vh
  2. .hero h1 uses clamp() for its font-size
  3. .hero p has max-width in ch units
  4. .hero has padding in rem
.hero { background: #15161b; color: white; font-family: sans-serif; }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Hero is at least 60% of the viewport height
  • Padding is 2rem-ish (in rem)
  • h1 font-size uses clamp()
  • Paragraph max-width uses ch