Complete Guide to CSS Units with Examples
CSS units fall into two camps: absolute (px, pt, in) and relative (em, rem, %, vw, vh, fr). This guide walks every unit you'll meet — including the modern dvh / svh / lvh fixes for mobile viewports — with real CSS examples and a cheat sheet for picking the right one.
CSS units are the measurements you use whenever you set width, height, padding, margin, font-size, or any other length-based property. They're how you tell the browser "make this 16 pixels wide" or "make this paragraph half the screen tall".
Pick the right unit and your layout flexes beautifully across phones, tablets, and 4K monitors. Pick the wrong one and you ship a site that breaks the moment a user zooms in.
CSS units fall into two big buckets:
- Absolute units — fixed sizes that don't care about screen, parent, or font (e.g.,
px,cm,in). - Relative units — sizes that scale based on something else: parent font, root font, viewport, or grid track (e.g.,
em,rem,%,vw,fr).
Modern responsive design leans almost entirely on relative units.
Absolute units render at the same physical size everywhere (in theory). They don't react to the viewport, parent, or user zoom preferences. Use them when you need precise, predictable measurements — print stylesheets, fixed icon sizes, hairline borders.
| Unit | Stands For | 1 unit equals | Typical use |
|---|---|---|---|
px | Pixel | 1 CSS pixel | Borders, shadows, small icons |
pt | Point | 1/72 of an inch | Print stylesheets |
pc | Pica | 12 points | Print typography |
in | Inch | 96 px | Print layouts |
cm | Centimeter | ~37.8 px | Print sizes |
mm | Millimeter | ~3.78 px | Print micro-sizing |
css.hairline-border { border: 1px solid #e5e7eb; } .print-page { width: 21cm; height: 29.7cm; } /* A4 */ .label { font-size: 10pt; } /* print */
Heads-up: A "CSS pixel" isn't always a hardware pixel. On a 2× retina display, 1 CSS pixel maps to 2 device pixels — which is exactly how your fonts stay sharp.
Relative units scale against something else. They're what makes a website feel native on a 360 px phone and a 2560 px ultrawide. Three relative units carry 90% of modern CSS work: %, em, and rem.
| Unit | Relative to | Common use |
|---|---|---|
% | Parent property's value | Widths, heights |
em | Parent's font-size | Spacing inside a component |
rem | Root <html> font-size (16 px) | Global typography & spacing |
ex | x-height of current font | Rare typographic tweaks |
ch | Width of the "0" glyph in current font | Form inputs, line lengths |
css:root { font-size: 16px; } /* 1rem = 16px */ .card { padding: 1.5rem; } /* 24px everywhere */ .card-title { font-size: 1.25em; } /* 1.25 × the card's text size */ .column { width: 50%; } /* half its parent */ .input { max-width: 60ch; } /* ~60 characters wide */
Why rem wins for spacing: every value re-scales when a user changes their browser font-size — no more inaccessible "tiny text on huge monitor" complaints.
Viewport units measure against the browser window itself. They're the secret sauce behind full-bleed heroes, sticky banners that hug the screen edge, and fluid typography.
| Unit | Equals |
|---|---|
vw | 1% of viewport width |
vh | 1% of viewport height |
vmin | 1% of the smaller dimension |
vmax | 1% of the larger dimension |
css.hero { height: 100vh; } /* full screen */ .hero-title { font-size: clamp(2rem, 5vw, 5rem); } /* fluid type */ .square { width: 50vmin; aspect-ratio: 1; } /* always square */
The classic 100vh has a famous mobile bug — it includes the URL bar, which shows and hides as you scroll, causing layouts to jump. The 2022 spec fixed this with three new variants:
| Unit | Means | When it's measured |
|---|---|---|
svh | Small viewport height | UI chrome (URL bar) is visible |
lvh | Large viewport height | UI chrome is hidden |
dvh | Dynamic viewport height | Adjusts in real-time as chrome moves |
css.mobile-hero { min-height: 100dvh; } /* iOS-safe full screen */
Same trio exists for width: svw, lvw, dvw. Rule of thumb: prefer dvh over vh for any mobile-first layout.
Beyond em and rem, CSS now offers a full toolkit for typography-driven sizing. These shine when you want spacing that breathes naturally with the text.
| Unit | Equals |
|---|---|
cap | Height of capital letters in the current font |
ch | Width of the 0 glyph |
ic | Width of an ideographic (CJK) character |
lh | Current line-height |
rlh | Root line-height |
css.article p { margin-bottom: 1lh; } /* exactly one line of breathing room */ .column { max-width: 70ch; } /* readable measure */ h1 { padding-top: 1cap; } /* aligned to capital height */
The fr unit only lives inside CSS Grid. It means a fraction of the leftover space after fixed tracks are subtracted. It's the cleanest way to build proportional column layouts.
| Definition | 1fr 1fr | 1fr 2fr | 200px 1fr |
|---|---|---|---|
| Two equal columns | ✅ | ❌ | ❌ |
| 1/3 vs 2/3 split | ❌ | ✅ | ❌ |
| Fixed sidebar + fluid main | ❌ | ❌ | ✅ |
css.layout { display: grid; grid-template-columns: 240px 1fr; /* sidebar + flexible main */ gap: 24px; } .gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
CSS animations and transitions speak only two time units:
| Unit | Means | Example |
|---|---|---|
s | Seconds | transition-duration: 0.3s; |
ms | Milliseconds | animation-delay: 200ms; |
css.btn { transition: background 200ms ease, transform .15s ease; } .spinner { animation: spin 1s linear infinite; }
Designers usually feel "snappy" at 150-250 ms and "elegant" at 300-500 ms. Anything over 600 ms tends to feel sluggish.
Angles power rotate(), conic-gradient(), and SVG transforms. Four units, all interchangeable — pick the one that reads cleanest.
| Unit | Full circle equals |
|---|---|
deg | 360deg |
rad | ≈ 6.2832rad |
grad | 400grad |
turn | 1turn |
css.tilted { transform: rotate(-3deg); } .flip { transform: rotate(0.5turn); } /* 180° */ .dial { background: conic-gradient(#10b981 0 0.3turn, #1f2937 0); }
Resolution units appear in @media queries and image-resolution. They describe pixel density, not size.
| Unit | Means |
|---|---|
dpi | Dots per inch |
dpcm | Dots per centimeter |
dppx | Dots per CSS pixel (1 = 96dpi) |
css@media (min-resolution: 2dppx) { .logo { background-image: url('logo@2x.png'); } }
| Need | Reach for |
|---|---|
| Borders, shadows, hairline lines | px |
| Global font + spacing scale | rem |
| Spacing inside one component | em |
| Width that hugs the parent | % |
| Hero that fills the screen | 100dvh |
| Fluid type | clamp(min, vw, max) |
| Readable column width | ch (60-80) |
| Grid columns | fr + minmax() |
| Animation duration | ms (under 1 s) |
| Rotation | deg (or turn) |
| High-DPI image | dppx in media query |
- Using
pxfor font-size everywhere — breaks user zoom. Default torem. - Hard-coding
100vh— lops the bottom off mobile pages. Use100dvh. - Mixing
emdeeply — nested components compound; a1.2eminside another1.2embecomes1.44emof the grandparent. Useremto break the chain. - Setting
width: 100%onbox-sizing: content-box— overflows by the padding. Setbox-sizing: border-boxonce globally. - Ignoring
dpi/dppx— shipping low-res images on retina screens looks fuzzy.
💡 Think Like a Designer: Pick one spacing scale (almost always
rem) and stick to it. Inconsistent units are the #1 reason a design system feels "off".
Keep Reading
Complete Guide to CSS Variables with Examples
Read on to explore complete guide to css variables with examples — a beginner-friendly walkthrough by Codekilla.
CSS Selectors Explained — Complete Guide
Read on to explore css selectors explained — complete guide — a beginner-friendly walkthrough by Codekilla.
CSS :has() Pseudo-Class Guide
Read on to explore css :has() pseudo-class guide — a beginner-friendly walkthrough by Codekilla.
