CSS Units
Understand px, em, rem, %, vw, vh and when to use each unit for sizing in CSS.
1. Introduction
Whenever you set a size in CSS — whether it is a font size, a width, a margin, or padding — you need to specify a unit. Writing font-size: 16 with no unit does not work. You must write font-size: 16px or font-size: 1rem.
CSS has many units, and choosing the right one matters. Some units are absolute (always the same size, like px). Others are relative (their size depends on something else, like em and %).
Understanding units is essential for building responsive layouts — pages that look good on mobile phones as well as large desktop screens.
2. Theory
Absolute Units
These have a fixed physical size and do not change based on anything else.
| Unit | Name | Use case |
|---|---|---|
px | Pixels | Most common — borders, precise sizing, layout |
pt | Points | Print stylesheets (avoid for screens) |
cm, mm | Centimetres, Millimetres | Print only |
On screen, px (pixels) is the only absolute unit you will regularly use.
Relative Units
These scale based on another value.
| Unit | Relative to | Use case |
|---|---|---|
em | Current element's font-size | Padding/margin relative to text size |
rem | Root element's font-size (<html>) | Font sizes — consistent scaling |
% | Parent element's size | Widths, fluid layouts |
vw | 1% of the viewport width | Full-width elements, fluid text |
vh | 1% of the viewport height | Full-height sections, hero areas |
vmin | 1% of the smaller viewport dimension | Responsive elements |
vmax | 1% of the larger viewport dimension | Rare usage |
ch | Width of the "0" character | Text containers (e.g. max-width: 65ch) |
px — Pixels
The most familiar unit. 1px on a screen is a display pixel. Note: on high-DPI screens (Retina), 1 CSS pixel = 2+ physical pixels, but the browser handles this automatically.
border: 1px solid #ccc;
padding: 16px;
width: 300px;
Good for: borders, shadows, precise fixed widths, small spacings. Avoid for font sizes (makes user preferences irrelevant).
em — Relative to Current Font Size
If the current element's font-size is 16px, then 1em = 16px, 2em = 32px, 0.5em = 8px.
p {
font-size: 16px;
padding: 1em; /* = 16px (same as font-size) */
margin: 1.5em; /* = 24px */
}
Problem with em: It compounds. If a parent is 2em and a child is also 2em, the child ends up 4em of the root — this is confusing.
rem — Relative to Root Font Size
rem always refers to the <html> element's font size (default: 16px in most browsers). It does NOT compound. This makes rem the preferred unit for font sizes.
html { font-size: 16px; } /* or just leave it default */
h1 { font-size: 2rem; } /* always 32px */
h2 { font-size: 1.5rem; } /* always 24px */
p { font-size: 1rem; } /* always 16px */
% — Percentage
Relative to the parent element's corresponding property.
.container { width: 800px; }
.sidebar { width: 25%; } /* = 200px (25% of 800px) */
.main { width: 75%; } /* = 600px */
/* For height, parent must have explicit height */
.hero { height: 100vh; } /* full viewport height — safer for full-screen */
vw and vh — Viewport Units
The viewport is the visible browser window. 100vw = 100% of the window width; 100vh = 100% of the window height.
.hero {
width: 100vw; /* full window width */
height: 100vh; /* full window height */
}
.sidebar {
height: 100vh; /* sidebar that fills the screen height */
}
/* Fluid font size */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
clamp() — Responsive Sizing
clamp(min, preferred, max) lets you set a minimum size, a preferred fluid size, and a maximum. This creates responsive sizing without media queries.
font-size: clamp(1rem, 2.5vw, 2rem);
/* minimum: 1rem (16px)
preferred: 2.5% of viewport width
maximum: 2rem (32px) */
3. Real World Example
A typical professional CSS file uses different units for different purposes:
- px:
border: 1px solid #ccc;,border-radius: 8px; - rem:
font-size: 1.125rem;,margin-bottom: 1.5rem; - %:
width: 100%;,max-width: 1200px; - vh:
min-height: 100vh;on the page wrapper - ch:
max-width: 65ch;on article text for ideal reading line length - clamp():
font-size: clamp(1rem, 2vw, 1.5rem);for fluid headings
4. Code Example
/* ===== UNIT EXAMPLES ===== */
/* Root font size — basis for rem */
html {
font-size: 16px; /* 1rem = 16px */
}
/* Typography — use rem */
h1 { font-size: 2.5rem; } /* 40px */
h2 { font-size: 2rem; } /* 32px */
h3 { font-size: 1.5rem; } /* 24px */
p { font-size: 1rem; } /* 16px */
small { font-size: 0.875rem; } /* 14px */
/* Spacing — use rem for consistency */
.card {
padding: 1.5rem; /* 24px */
margin-bottom: 2rem; /* 32px */
border-radius: 8px; /* px for small precise values */
border: 1px solid #e2e8f0; /* px for borders */
}
/* Layout — use % for fluid widths */
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
}
/* Full-screen hero */
.hero {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
}
/* Sidebar */
.sidebar {
width: 280px; /* fixed px for sidebar */
height: 100vh;
}
/* Fluid font with clamp */
.hero-title {
font-size: clamp(1.75rem, 5vw, 4rem);
}
/* Readable line length */
.article-body {
max-width: 65ch;
line-height: 1.7;
}
5. Code Breakdown
font-size: 2.5remon h1- With root at 16px, this equals 40px. If a user has set their browser default to 20px for accessibility, this scales to 50px automatically — respecting the user's preference. This is why rem is better than px for fonts.
width: 90%; max-width: 1200px;- A classic fluid layout pattern. On small screens (360px wide): 90% = 324px. On large screens (1400px wide): 90% = 1260px, but max-width caps it at 1200px. The content never gets too wide to read comfortably.
margin: 0 auto- The shorthand
0 automeans top/bottom margin = 0, left/right margin = auto. Auto margins distribute equally on both sides — this horizontally centres the element inside its parent. min-height: 100vh- Using
min-heightinstead ofheightallows content to grow beyond the viewport if needed.height: 100vhwould clip overflowing content. max-width: 65ch- The
chunit equals the width of the "0" character in the current font. 65ch = approximately 65 characters wide — typography research shows this is the optimal line length for reading.
6. Common Mistakes
-
Using
pxfor all font sizes. Pixel font sizes ignore browser text-size preferences and hurt accessibility. Useremfor font sizes. -
Confusing
emandrem.emis relative to the current element — it compounds and becomes unpredictable in nested elements.remalways refers to the root — far more predictable. -
Setting
height: 100%without a parent height. Percentage heights only work if the parent has an explicit height set. Useheight: 100vhfor full-screen instead. -
Forgetting units entirely.
margin: 16(withoutpx) will be ignored by the browser — except forline-heightwhich uniquely accepts unitless values. -
Using
vwfor widths causing horizontal scroll.100vwincludes the scrollbar width on some browsers, causing a tiny horizontal scroll. Usewidth: 100%for full-width elements instead.
7. Best Practices
- Use
remfor all font sizes — respects user accessibility preferences and scales consistently. - Use
pxfor borders, shadows, and small precise measurements — these should not scale with font size. - Use
%orvwfor widths — fluid layouts that adapt to screen size. - Use
vhfor full-screen sections — hero areas, full-page modals, sidebars. - Use
clamp()for responsive typography — fluid sizing without media queries. - Set
html { font-size: 16px; }explicitly or rely on browser default — do NOT set it to a percentage like62.5%(old trick that breaks accessibility). - Use
max-width: 65chon article/blog body text for optimal readability.
8. Practice Exercise
Create units.html and units.css. Build a page that demonstrates each unit:
- Set up a heading scale using
rem: h1=2.5rem, h2=2rem, h3=1.5rem, p=1rem - Create a
.containerthat is 90% wide with a max-width of 900px, centred withautomargins - Create a hero section with
min-height: 100vhand a gradient background - Create two columns inside a container: left 30% wide, right 70% wide (using %)
- Add a card with padding of
1.5remand a border of1px - Resize the browser window — notice how % widths adapt but px values stay fixed
9. Assignment
Build a full-page landing page layout using the right units throughout:
- A hero section with
100vhheight, centred text, and a fluid heading usingclamp() - A features section with three cards side by side, each taking
33.33%width with a max-width container - All font sizes in
rem - All spacing (padding, margin) in
rem - All borders in
px - Article text limited to
65chmax-width
10. Interview Questions
Q1: What is the difference between px, em, and rem?
Answer: px is an absolute pixel unit that never changes. em is relative to the current element's font-size — it compounds in nested elements. rem is always relative to the root element's font-size, so it is consistent and predictable.
Q2: Why should you use rem instead of px for font sizes?
Answer: Using rem respects the user's browser font size preferences (important for accessibility). If a user increases their browser's default font size for readability, rem values scale up accordingly while px values ignore this setting.
Q3: What is the difference between vh and %?
Answer: vh is relative to the viewport (browser window) height. % is relative to the parent element. For full-screen heights, 100vh is reliable; 100% only works if every ancestor has an explicit height set.
Q4: What does clamp() do?
Answer: clamp(min, preferred, max) returns the preferred value, but never below the minimum or above the maximum. It is useful for responsive typography — text grows as the viewport widens but never gets too small or too large.
Q5: What units would you use for padding?
Answer: It depends. rem is common and scales with font size. px is fine for small fixed spacings like border: 1px. Avoid em for padding unless you intentionally want it to scale with the element's font size. Some developers use rem exclusively for all spacing for consistency.
11. Additional Resources
- MDN Web Docs — CSS Values and Units (search "MDN CSS values and units")
- CSS-Tricks — The Lengths of CSS (search "css-tricks lengths of css")
- MDN — clamp() function (search "MDN clamp CSS")
- Every Layout — Intrinsic Web Design (search "every layout intrinsic design")
- Josh Comeau — The Surprising Truth About Pixels and Accessibility (search this title)