CSS Units Explained: When to Use px, rem, em, vh, and vw
Stop guessing which CSS unit to use. This practical guide breaks down every CSS unit with real-world examples, comparison tables, and decision frameworks for responsive design.
CSS Units Explained: When to Use px, rem, em, vh, and vw
Choosing the right CSS unit is one of the most confusing parts of frontend development. Use the wrong one, and your layout breaks on mobile. Use the right one, and your design adapts beautifully across every screen size.
This guide cuts through the confusion with clear examples, a decision framework you can actually use, modern CSS units you might not know about, and accessibility considerations that matter for real-world projects.
The Complete CSS Unit Reference
Before diving into when to use each unit, let's map out what they all do:
| Unit | Type | Relative To | Best For |
|---|---|---|---|
px |
Absolute | Nothing | Borders, shadows, fine details |
rem |
Relative | Root font size | Typography, spacing |
em |
Relative | Parent font size | Component-scoped sizing |
vh |
Viewport | Viewport height | Full-screen sections |
vw |
Viewport | Viewport width | Hero text, fluid layouts |
% |
Relative | Parent element | Fluid grids |
When to Use px (Pixels)
Pixels are absolute — they never change based on context.
Use px for:
- Borders:
border: 1px solid #e5e7eb - Box shadows:
box-shadow: 0 4px 6px rgba(0,0,0,0.1) - Outline widths
- When you need pixel-perfect precision
Avoid px for:
- Font sizes (breaks accessibility)
- Layout widths (not responsive)
- Spacing that should scale
/* Good — these should be fixed */
.card {
border: 1px solid #e5e7eb;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
border-radius: 8px;
}
/* Bad — these should be relative */
.card {
width: 300px; /* Won't adapt to screen size */
font-size: 16px; /* Ignores user preferences */
}
When to Use rem
rem stands for "root em" — it's relative to the <html> element's font size (default 16px).
The power of rem: If a user changes their browser's default font size for accessibility, everything in rem scales proportionally.
Use rem for:
- Font sizes
- Padding and margin
- Width and height of components
- Any spacing that should respect user preferences
html {
font-size: 16px; /* default */
}
.heading {
font-size: 2rem; /* 32px — scales if user changes root size */
}
.container {
padding: 1.5rem; /* 24px */
max-width: 64rem; /* 1024px */
}
Quick conversion: 1rem = 16px by default. So 0.875rem = 14px, 1.25rem = 20px, etc.
When to Use em
em is relative to the parent element's font size, not the root.
The compounding problem: Nested em values multiply, which can cause unexpected results:
.parent { font-size: 20px; }
.child { font-size: 1.2em; } /* 24px */
.grandchild { font-size: 1.2em; } /* 28.8px — not 24px! */
Use em for:
- Component-level scaling (button padding, input sizes)
- Media queries:
@media (max-width: 48em) { ... } - When you want child elements to scale with their parent
/* Great use case — button scales with its font size */
.btn {
font-size: 1rem;
padding: 0.5em 1em; /* 8px 16px — scales if font-size changes */
}
.btn-lg {
font-size: 1.25rem;
padding: 0.5em 1em; /* 10px 20px — automatically larger */
}
When to Use vh and vw
Viewport units are relative to the browser window size.
Use vh for:
- Full-height hero sections:
min-height: 100vh - Sticky footers
- Elements that should fill the visible area
Use vw for:
- Fluid typography:
font-size: clamp(1rem, 2.5vw, 2rem) - Background sizing
- Elements that span the full viewport width
/* Full-screen hero */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
}
/* Fluid heading — scales with viewport but has limits */
.fluid-heading {
font-size: clamp(1.5rem, 4vw, 3rem);
}
Pro tip: On mobile,
100vhcan cause issues because the browser chrome (address bar) affects the viewport height. Usedvh(dynamic viewport height) for better mobile support:min-height: 100dvh.
The Decision Framework
When you're unsure which unit to use, follow this flowchart:
- Does it need to be exact? →
px(borders, shadows) - Should it respect user font size? →
rem(fonts, spacing) - Should it scale with parent? →
em(component internals) - Should it fill the screen? →
vh/vw(hero sections, fluid type) - Should it be fluid within a container? →
%(grids, layouts)
Common Patterns That Work Everywhere
Here's a battle-tested combination:
/* Typography — rem for accessibility */
body { font-size: 1rem; }
h1 { font-size: 2.25rem; }
h2 { font-size: 1.75rem; }
p { font-size: 1rem; line-height: 1.75; }
/* Spacing — rem for consistency */
.section { padding: 4rem 1.5rem; }
.card { padding: 1.5rem; margin-bottom: 2rem; }
/* Layout — mix of units */
.container { max-width: 64rem; margin: 0 auto; padding: 0 1rem; }
.hero { min-height: 100dvh; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
/* Details — px for precision */
.card { border: 1px solid #e5e7eb; border-radius: 8px; }
Mixing Units with calc()
The calc() function lets you combine units for precise, responsive layouts:
/* Sidebar + fluid content */
.layout {
display: grid;
grid-template-columns: 250px 1fr;
}
/* Fixed sidebar, fluid content with padding */
.content {
width: calc(100% - 250px);
padding: calc(2rem + 1vw);
}
/* Responsive spacing that never goes below 16px */
.gap {
margin-bottom: calc(1rem + 2vw);
}
/* Fluid image with max-width constraint */
.fluid-image {
width: clamp(200px, 50vw, 800px);
height: auto;
}
Modern CSS Units You Should Know
CSS has evolved beyond the basic units. Here are newer options:
Container Query Units (cqw, cqh, cqi, cqb)
Relative to the nearest container ancestor — not the viewport:
.parent {
container-type: inline-size;
}
/* cqi = 1% of container's inline (width) size */
.child {
font-size: clamp(0.875rem, 3cqi, 1.5rem);
padding: 2cqi;
}
Why this matters: Viewport units (vw) respond to the browser window. Container units (cqi) respond to the actual component size — much more useful for reusable components.
Dynamic Viewport Units (dvh, svh, lvh)
Mobile browsers have dynamic toolbars that change the viewport height:
/* dvh = dynamic viewport height (changes with toolbar) */
.hero { min-height: 100dvh; }
/* svh = small viewport height (toolbar fully shown) */
.modal { max-height: 100svh; }
/* lvh = large viewport height (toolbar hidden) */
.overlay { height: 100lvh; }
The fr Unit (CSS Grid)
fr distributes available space in grid layouts:
.grid {
display: grid;
/* 2:1 ratio between columns */
grid-template-columns: 2fr 1fr;
}
Accessibility and User Preferences
CSS units directly impact accessibility:
Why rem matters for accessibility:
- Some users set their browser's default font size to 20px or 24px
- If you use
pxfor font sizes, you override their preference - If you use
rem, everything scales proportionally
/* Bad — forces 16px regardless of user preference */
body { font-size: 16px; }
/* Good — respects user's default size */
body { font-size: 1rem; }
/* Also good — uses the browser default directly */
body { font-size: 100%; }
Respecting reduced motion:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Common Mistakes with CSS Units
1. Using px for Font Sizes
The most common mistake. It breaks accessibility and ignores user preferences. Switch to rem — it takes 5 minutes and makes your site more inclusive.
2. Using vw Alone for Typography
/* Bad — text becomes unreadably small on mobile */
h1 { font-size: 5vw; } /* 20px on desktop, 16px on mobile... too small */
/* Good — bounded with clamp() */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
3. Forgetting That em Compounds
/* Problem: nested em values multiply */
.nav { font-size: 0.875em; }
.nav li { font-size: 0.875em; } /* 0.875 × 0.875 = 0.766em of original */
.nav li a { font-size: 0.875em; } /* 0.766 × 0.875 = 0.67em — too small! */
/* Solution: use rem for consistent sizing */
.nav { font-size: 0.875rem; }
.nav li { font-size: 0.875rem; }
.nav li a { font-size: 0.875rem; }
4. Using 100vh on Mobile
Mobile browsers include the address bar in viewport height calculations, causing scrollbars. Use 100dvh instead.
Try It Yourself
Understanding CSS units is one thing — seeing them in action is another. Use our CSS Unit Converter to quickly convert between px, rem, em, and other units while building your stylesheets.
Key Takeaways
- Default to
remfor font sizes and spacing — it's the most accessible choice - Use
pxsparingly — only for things that should never scale (borders, shadows) - Avoid
emfor nesting — it compounds in confusing ways - Use
clamp()withvwfor fluid typography that doesn't go extreme - Combine units — real-world CSS uses multiple units together intentionally
- Use
dvhinstead ofvhfor mobile-friendly full-height layouts - Use container units (
cqi) for component-scoped responsive design - Never override user font size — use
remor%instead ofpx
The best CSS isn't about picking one unit — it's about knowing when each one shines.
Understanding CSS units is one thing — converting them is another. Use our CSS Unit Converter to quickly convert between px, rem, em, and other units while building your stylesheets.
Try It Yourself
Put what you've learned into practice with our free online tools.
Related Articles
Regex Explained: A Practical Guide to Regular Expressions
Master regular expressions with practical examples. Learn regex syntax, common patterns, and how to use regex for validation, search, and data extraction.
HTTP Status Codes Explained: What Every 404, 301, and 500 Really Means
From 200 OK to 503 Service Unavailable, HTTP status codes tell the story of every web request. This guide decodes every important status code with real-world examples and debugging tips.
Color Palette Generator: How to Choose Colors That Work Together
Great design starts with great color choices. Learn the science behind color theory, how to build harmonious palettes, and the tools designers use to pick perfect color combinations.