CSS Units Explained: px, em, rem, %, and Viewport Units
Learn what px, em, rem, percentages, and viewport units measure, how they respond to text and screen changes, and how to choose the right unit.
Choose a CSS unit by the thing you want a value to follow: use rem for a document-wide scale tied to the root font size, em for sizing tied to local typography, % when a property should follow its defined reference, viewport units such as vw or dvh when a value should track the viewport, and px when you want a value specified in CSS pixels. The reference frame matters more than whether a unit is called “absolute” or “relative.”
1. CSS unit comparison at a glance
| Unit | What it follows | Good fit | Watch for |
|---|---|---|---|
px |
A CSS pixel | Fine borders, small details, or dimensions authored in CSS-pixel terms | A CSS pixel is not necessarily one physical screen pixel. |
em |
The relevant element font size; for font-size, the parent’s font size |
Component spacing or sizing that should grow with its text | Nested font sizes can compound. |
rem |
The root element’s font size | A consistent scale across a page | Changing the root font size changes every dependent value. |
% |
The reference defined for the specific property | Proportions such as a child width relative to its containing block | There is no single universal percentage reference. |
vw, vh |
Viewport width or height | Layouts and type that should respond to viewport dimensions | Mobile browser controls can change the available viewport height. |
svh, lvh, dvh |
Small, large, or dynamic viewport height | Layouts that need explicit behavior as browser controls expand or retract | Choose the behavior that suits the layout and check target browsers. |
CSS classifies px as an absolute length unit, but “absolute” is a unit category, not a promise about hardware pixels. On a high-density display, one CSS pixel can map to multiple device pixels; fractional CSS lengths can also be rasterized across device-pixel increments. [MDN: <length>]
2. What a CSS pixel (px) means
A CSS pixel is a CSS length unit. Browsers map CSS pixels to the display’s device pixels according to the display and rendering environment, so 1px does not necessarily mean one physical pixel. Zoom and display density affect how CSS-pixel dimensions appear on screen.
.card {
border: 1px solid #cbd5e1;
border-radius: 6px;
padding: 16px;
}
Use pixels when a value is intentionally authored in CSS-pixel terms, such as a fine border or a detail designed alongside pixel-authored artwork. For typography and larger layout spacing, consider whether the value should respond to user text settings or a container before choosing px.
3. How em scales with local typography
em is font-relative. For a font-size declaration, it is calculated from the parent element’s font size. For other font-relative sizing, it is based on the element’s computed font size. This makes em useful when a component’s padding, icon size, or gap should scale with its text. [MDN: <length>]
.notice {
font-size: 1.125em;
padding: 1em 1.25em;
border-radius: 0.5em;
}
The padding and radius follow the notice’s computed text size. If you nest elements that each change font-size in em, those changes compound because each font-size calculation uses its parent’s size. That can be useful for deliberately nested scales, but it can also produce unexpectedly large or small text.
4. What rem means and why it is useful
rem means “root em”: it follows the font size of the root element, normally html. Unlike em, a rem value does not change just because it appears inside a nested component with a different font size. [MDN: <length>]
html {
font-size: 100%;
}
.page-title {
font-size: 2rem;
margin-block-end: 1rem;
}
.panel {
padding: 1.5rem;
gap: 1rem;
}
With the browser’s default root size of 16 CSS pixels, 1rem is typically 16 CSS pixels. If the root font size changes, all rem-based dimensions change together. Setting the root with a percentage preserves the user agent’s text-size baseline rather than hard-coding a pixel value.
5. Percentages: check the property’s reference
A percentage is contextual: the property definition determines what the percentage is measured against. For example, a child’s width: 50% is generally based on the containing block’s width. Other properties can use different references, so “percent is relative to the parent” is not a reliable general rule. Check the definition for the property you are using. [MDN: <percentage>]
.container {
width: min(100%, 70rem);
margin-inline: auto;
}
.container img {
display: block;
max-width: 100%;
height: auto;
}
Here, the image’s maximum width follows its containing block, helping it stay inside the available width. Percentages are often a good fit when the intended dependency is a property-specific reference dimension rather than the viewport.
6. Viewport units: vw, vh, and the newer variants
vw and vh represent 1% of the viewport width and height, respectively. They are useful when a dimension should respond to the viewport itself. For example, 50vw is half the viewport width.
.hero {
min-height: 100vh;
padding: 5vw;
}
.hero-title {
font-size: clamp(2rem, 5vw, 5rem);
}
On mobile, browser interface controls can expand or retract, affecting the visible area. The small, large, and dynamic viewport unit families make this behavior explicit: svh uses the small viewport, lvh the large viewport, and dvh the dynamic viewport. The same families include width variants such as svw, lvw, and dvw. The classic vh behavior corresponds to the large viewport in MDN’s current account. [MDN: viewport-percentage lengths]
.mobile-hero {
min-height: 100vh; /* fallback */
min-height: 100dvh; /* follows the dynamic viewport */
}
Use 100svh when the layout should fit within the smaller viewport while browser UI is present; this can leave unused space when the UI retracts. Use 100dvh when the layout should track the changing viewport. Test full-height mobile layouts in the browsers and conditions you support.
7. A practical way to choose
- Should the value follow the root text scale? Use
remfor shared typography and spacing scales. - Should it follow a component’s own text? Use
emfor local component sizing, and check nested font-size calculations. - Should it follow a property’s containing or other defined reference? Use
%after confirming that property’s reference. - Should it follow the viewport? Use
vw/vh, or an explicitsv*,lv*, ordv*unit when browser interface changes matter. - Is a CSS-pixel value intentional? Use
pxfor precision in CSS-pixel terms, with the understanding that rendering maps it to the display.
It is normal for a real interface to use several units together: rem for the type and spacing scale, percentages for fluid widths, viewport units for a viewport-sized hero, and pixels for a fine border. The right unit is the one whose reference frame matches the design dependency.
8. Complete responsive example
This example combines a root-based scale, local component sizing, a percentage width, viewport-responsive type, and a viewport-height fallback.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CSS units example</title>
<style>
html { font-size: 100%; }
* { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.5 system-ui, sans-serif; color: #172033; }
.hero {
min-height: 100vh;
min-height: 100dvh;
display: grid;
place-items: center;
padding: 5vw;
background: #eef4ff;
}
.card {
width: min(100%, 44rem);
padding: 1.5rem;
border: 1px solid #cbd5e1;
border-radius: 0.75rem;
background: white;
}
h1 { margin: 0 0 1rem; font-size: clamp(2rem, 5vw, 4rem); line-height: 1.1; }
.card p { margin: 0; font-size: 1.05em; }
@media (max-width: 40rem) {
.card { padding: 1rem; }
}
</style>
</head>
<body>
<main class="hero">
<article class="card">
<h1>A responsive layout</h1>
<p>The card follows its container, spacing follows the root scale, and the heading responds to viewport width.</p>
</article>
</main>
</body>
</html>
9. Troubleshooting common surprises
| Symptom | Likely cause | What to check or change |
|---|---|---|
A 1px line looks thicker or softer on another display |
CSS pixels map to device pixels according to display density and rendering; fractional placement can affect rasterization. | Inspect at the target zoom and display scale. Treat px as a CSS unit, not a hardware-pixel guarantee. |
| Nested text gets unexpectedly large or small | Nested font-size values in em compound against successive parent sizes. |
Use rem for a root-based scale, or simplify the nesting and calculate the intended local scale. |
| A percentage width does not match the viewport | The percentage follows the reference defined for that property, often a containing block for width. | Inspect the containing block and the property definition. Use viewport units only when viewport sizing is intended. |
| A full-height mobile section is obscured or leaves a gap | Browser interface controls change the visible viewport; the chosen viewport unit determines which viewport size is used. | Choose among svh, lvh, and dvh based on the desired behavior, then check target browsers. |
| Changing the root size changes many dimensions at once | That is the dependency of rem. |
Keep the root scale intentional and audit components that should instead follow local type or a container. |
| A viewport-based heading becomes too small or too large | Raw viewport units have no inherent design bounds. | Use clamp() to set a minimum, fluid preferred value, and maximum. |
10. Performance, reliability, and cost
These CSS units are part of ordinary style calculation; the choice among them is generally a design and behavior decision. The practical reliability concern is whether the chosen reference changes as expected across user text settings, nested components, containers, viewport sizes, and mobile browser controls. Avoid assuming that a viewport-sized or pixel-sized value means the same physical space in every viewing environment.
If you need screenshots to inspect a page at different viewport sizes, device presets, or page states, ScreenshotNeo is a website screenshot API and MCP server for developers. A screenshot service does not replace checking the layout in your supported browsers, especially for dynamic mobile viewport behavior.
11. Or skip the browser setup
Capture a page with one GET request. See the ScreenshotNeo API documentation for request options and configuration.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
12. FAQ
What is 1rem in CSS?
It is one times the root element’s font size. With a 16 CSS-pixel root size, it is 16 CSS pixels.
What does 1em depend on?
For font-size, it depends on the parent’s font size. For other font-relative sizing, it depends on the element’s computed font size.
Is px an absolute unit?
Yes, in CSS’s unit classification. That does not mean one CSS pixel always equals one physical display pixel.
Is % always relative to the parent?
No. The relevant property defines its percentage reference.
Should I use rem or em for spacing?
Use rem when spacing should follow the root scale; use em when it should scale with local typography.


