Every developer has been there — staring at a layout wondering: should I use px or rem here? What about em? Or %? Picking the wrong unit causes broken layouts, poor accessibility, and headaches during responsive design. This guide explains every major CSS unit clearly, with real-world examples, so you never second-guess yourself again.
A Quick Overview: Absolute vs Relative Units
CSS units fall into two families:
- Absolute units — Fixed size, never change regardless of screen or user settings. Example:
px,pt,cm. - Relative units — Scale based on something else (parent element, root font size, viewport). Example:
rem,em,%,vw,vh.
| Unit | Type | Relative To | Best Used For |
|---|---|---|---|
px | Absolute | Device pixels (CSS pixels) | Borders, box shadows, precise icons |
rem | Relative | Root <html> font size | Font sizes, spacing, layout padding |
em | Relative | Parent element's font size | Component-level spacing, buttons |
% | Relative | Parent element's dimension | Fluid widths, images, containers |
vw | Relative | 1% of viewport width | Full-width sections, hero text |
vh | Relative | 1% of viewport height | Full-screen sections, modals |
vmin | Relative | Smaller of vw or vh | Square elements, responsive icons |
vmax | Relative | Larger of vw or vh | Full-bleed backgrounds |
ch | Relative | Width of "0" character | Readable text column widths |
clamp() | Function | Combines min, preferred, max | Fluid typography & spacing |
1. px — Pixels (The Absolute Unit)
A CSS pixel (px) is the most familiar unit. It maps to a logical pixel on screen — not a physical device pixel (retina screens may use 2–3 physical pixels per CSS pixel). It is fixed and does not change with user browser zoom preferences in the same accessible way relative units do.
/* ✅ Good uses of px */ border: 1px solid rgba(255,255,255,0.1); box-shadow: 0 4px 24px rgba(0,0,0,0.3); border-radius: 8px; /* ❌ Avoid px for font-size — it ignores browser zoom */ font-size: 16px; /* user can't scale this with browser settings */
px for font sizes overrides a user's browser text-size preference, which can make your site inaccessible for people with visual impairments. Always use rem for font sizes.2. rem — Root Em (The Modern Standard)
rem stands for Root Em. It is always relative to the font-size set on the <html> element. By default, browsers set html { font-size: 16px; }, so 1rem = 16px.
The beauty of rem is that if a user increases their browser's default font size (for accessibility), everything sized in rem scales proportionally.
/* Default: html font-size is 16px */ html { font-size: 16px; } /* So these are equivalent: */ font-size: 1rem; /* = 16px */ font-size: 1.5rem; /* = 24px */ font-size: 0.875rem;/* = 14px */ /* A useful trick — set base to 62.5% for easy math */ html { font-size: 62.5%; } /* 1rem = 10px */ font-size: 1.6rem; /* = 16px — easy! */
rem for font sizes, padding, margin, and gap. It keeps your entire spacing system proportional and accessible across all devices and user preferences.3. em — Em (Context-Aware Relative Unit)
em is relative to the font-size of its own parent element, not the root. This makes it powerful for component-level scaling — but also dangerous because it compounds (inherits and multiplies) when nested.
/* Parent has font-size: 20px */ .parent { font-size: 20px; } /* Child: 1em = 20px (inherited from parent) */ .child { font-size: 1em; } /* = 20px */ .child { font-size: 0.8em; } /* = 16px */ /* ⚠️ Compounding problem with nested ems */ .grandchild { font-size: 0.8em; } /* = 0.8×16 = 12.8px — unintended! */
When to use em: It shines for padding and margin inside a component, where you want spacing to scale with the component's own font size. For example, a button's padding defined in em will naturally grow when the button's text is larger.
/* Button padding scales with its own font-size */ .btn { font-size: 1rem; padding: 0.75em 1.5em; /* relative to button's own font */ } .btn-lg { font-size: 1.25rem; /* padding auto-scales — no extra CSS needed! */ }
4. % — Percentage
Percentages are relative to the parent element's size. They are the foundation of fluid, responsive layouts — especially for widths and heights.
/* Fluid image — always fills its container */ img { width: 100%; height: auto; } /* Two-column layout */ .col { width: 50%; } /* Note: padding/margin % is relative to parent WIDTH, not height */ .aspect-box { width: 100%; padding-top: 56.25%; /* 16:9 aspect ratio trick */ }
5. vw & vh — Viewport Units
vw (viewport width) and vh (viewport height) are each 1% of the browser window's dimensions. They are perfect for full-screen layouts.
/* Full-screen hero section */ .hero { width: 100vw; height: 100vh; } /* Fluid typography that scales with screen width */ h1 { font-size: 5vw; } /* Better: use clamp() to set min and max */ h1 { font-size: clamp(2rem, 5vw, 4rem); }
100vh includes the browser toolbar height, causing content to be cut off. Use min-height: 100svh (small viewport height) for mobile-safe full-screen sections. It is now supported in all modern browsers.6. vmin & vmax
vmin is 1% of the smaller of vw or vh. vmax is 1% of the larger. These are great for responsive square elements or typography that should adapt to any orientation.
/* Square element that fits any screen orientation */ .avatar { width: 20vmin; height: 20vmin; }
7. ch — Character Width
1ch equals the width of the "0" character in the current font. It is the perfect unit for setting readable line lengths. Typographers recommend 60–75 characters per line for optimal readability.
/* Optimal readable text column */ .article-body { max-width: 68ch; margin: 0 auto; }
8. clamp() — The Modern Fluid Unit
clamp(min, preferred, max) is not a unit itself, but a CSS function that combines three values. It is the cleanest way to write fluid, responsive typography and spacing with zero media queries.
/* Font size: min 1rem, scales with viewport, max 3rem */ h1 { font-size: clamp(1.75rem, 4vw + 1rem, 3.5rem); } /* Padding: min 1rem, scales, max 4rem */ .section { padding: clamp(1rem, 5vw, 4rem); } /* Container width */ .container { width: clamp(320px, 90%, 1200px); }
clamp() is the future of responsive design. Combine it with rem for font sizes and vw for the fluid middle value to create layouts that are perfectly readable on every screen — no breakpoints required.When to Use Which Unit — The Cheat Sheet
| Property | Recommended Unit | Why |
|---|---|---|
| Font size (global) | rem | Respects browser accessibility settings |
| Font size (component) | em or rem | Use em for component self-scaling |
| Padding & margin | rem | Consistent spacing system |
| Button padding | em | Scales with button's font size |
| Layout widths | % or ch | Fluid, fills parent container |
| Borders, shadows | px | Always crisp, no scaling needed |
| Full-screen sections | 100vh / 100svh | Fill viewport, use svh on mobile |
| Fluid typography | clamp(rem, vw, rem) | Scales smoothly without breakpoints |
| Readable text column | ch | Typographically correct line length |
| Responsive icons/squares | vmin | Adapts to screen orientation |
Real-World Example: A Fully Responsive Card
.card { width: clamp(280px, 90%, 480px); /* fluid width */ padding: 2rem; /* consistent spacing */ border-radius: 16px; /* fixed rounding */ border: 1px solid rgba(255,255,255,0.1); /* crisp border */ } .card h2 { font-size: clamp(1.25rem, 2.5vw, 1.75rem); /* fluid heading */ margin-bottom: 0.75rem; } .card p { font-size: 1rem; max-width: 55ch; /* readable line length */ line-height: 1.7; } .card .btn { font-size: 1rem; padding: 0.75em 1.5em; /* scales with btn font */ margin-top: 1.5rem; }
Common Mistakes to Avoid
- Using
pxfor font sizes — Always useremto preserve browser accessibility settings. - Nesting
emdeeply — Compounding effect causes unpredictable sizes. Preferremfor global spacing. - Using
100vhon mobile — The toolbar overlay causes overflow. Use100svhor a JS-based fallback. - Setting widths in
px— Use%,rem, orclamp()for fluid, responsive containers. - Ignoring
clamp()— It replaces dozens of breakpoint-based media query rules with a single line.
Final Thoughts
Choosing the right CSS unit is not just a technical decision — it directly impacts your site's accessibility, responsiveness, and maintainability. The golden rules are simple: use rem for typography and global spacing, em for component-level scaling, % for fluid containers, px for precise decorative details, and clamp() whenever you want fluid, breakpoint-free scaling.
Master these units and your CSS will be cleaner, more readable, and work beautifully on every screen — from a 320px mobile to a 4K monitor.
Want a website built with pixel-perfect, accessible CSS from day one? Get a free quote from Pixel Precision Web today.