Design Tools

Pixel, REM, EM, and VW Explained for Responsive Design

Updated 10 Sept 202615 min readInformational guide
Four cards across the top name what each CSS unit actually measures against. The px card states that one CSS pixel is one inch divided by 96, that it is never a device pixel, and that zoom scales it while a raised default font size does not. The rem card states that rem is the root font size, 16px by default and changeable by the reader, and that the root should be set with 100 percent rather than a hard 16px. The em card states that em is the element's own font size on every property except font-size, where it is the parent's, which is why it compounds. The vw and vh card states that one unit is 1 percent of the viewport, that page zoom moves it while text-only scaling does not, and that svh, lvh and dvh fix mobile height. Four cards below give the rules that surprise people: em compounds only on font-size, so 1.25em inside 1.25em is 1.5625 rather than 1.25, and three levels of a nested list nearly doubles the text; relative units in media queries use the initial font size by specification, so 48rem is still 768px even under the 62.5 percent root trick; 100vw includes the scrollbar gutter, so a full-width block overflows and normal flow should use 100 percent instead; and vw text ignores a raised default font size, since zoom scales it but text-only scaling does not, which is a plausible way to fail WCAG success criterion 1.4.4. A green panel gives the fix as a line of CSS, font-size colon clamp of 2rem, 1rem plus 2.5vw and 4.5rem, explaining that it never falls below 2rem, resolves to 48px on a 1280px viewport, never exceeds 4.5rem, and still tracks the reader because a 1rem term sits inside the middle value. A closing band advises choosing the relationship before the unit: the root, the local text, the viewport, or a fixed visual detail.

A layout can look calm on a desktop and awkward on a phone without any single rule being obviously wrong. The heading is too large. The card padding feels heavy. A button wraps in a strange place. The design was not broken exactly; the units were too rigid for the range of screens and user settings it had to survive.

CSS units decide how sizes respond to context. Pixels, rems, ems, viewport units, and percentages each answer a different question. Good responsive design is not about replacing every px with rem. It is about choosing the unit that matches the job, and knowing the handful of rules that behave differently from the way most people assume.

BlinkCalc's Pixel Converter helps convert px, rem, em, pt, vw, and vh values, but the real value comes from knowing why you would choose one unit over another.

What px means

px stands for CSS pixel. It is the most familiar unit because it feels concrete:

.button {
  padding: 12px 16px;
  border-radius: 8px;
}

A CSS pixel is not a device pixel. In CSS the relationship runs the other way around: 1px is defined as exactly 1in / 96, so all the absolute units are anchored to each other, and the browser decides how many physical dots that becomes. On a high density phone screen one CSS pixel may be drawn with two or three device pixels; at 200% browser zoom it covers twice the area it did before. That is why px stays a stable design unit even though it is a poor description of hardware.

Pixels are useful for:

  • Borders
  • Hairline dividers
  • Icon sizes
  • Small fixed gaps
  • Canvas measurements
  • Precise visual details

Pixels are less flexible for body text and large layout spacing because they do not respond to a user's font-size preference. Browser zoom still scales them, but a reader who has raised the default text size in their browser settings, without zooming, sees pixel-sized text stay exactly where it was.

What rem means

rem means root em. It is the computed font-size of the root element, normally <html>. Browsers ship a default of font-size: medium, which resolves to 16px in every current desktop browser, but users can change it in browser settings and some do.

If the root resolves to 16px:

rempx equivalent
0.5rem8px
0.75rem12px
1rem16px
1.5rem24px
2rem32px

This makes rem useful for typography and spacing systems:

html {
  font-size: 100%;
}

.article-title {
  font-size: 2rem;
  margin-bottom: 1rem;
}

font-size: 100% is deliberate. It inherits whatever the user's preference is instead of overwriting it. Setting html { font-size: 16px } looks equivalent and is not: it pins the root to 16px and quietly discards the reader's setting, so every rem in the system stops honouring it.

You will also meet the "62.5% trick", where the root is set to 62.5% so that 1rem equals 10px and conversion becomes mental arithmetic. It keeps the user's preference proportionally (a reader on a 20px default gets a 12.5px root), but it makes every inherited default, including form controls and any third-party widget that assumes a 16px root, render smaller than intended. If you use it, set the body back to 1.6rem and test with a raised browser default.

One subtlety worth knowing: inside a declaration on the root element itself, rem refers to the root's initial value rather than the value being set, so html { font-size: 1.5rem } resolves against the browser default rather than recursing.

What em means

em is relative to a computed font size, but which one depends on where you use it, and this is the single most common source of surprise.

  • On any property other than font-size, 1em is the element's own computed font size.
  • On the font-size property itself, 1em is the font size inherited from the parent.

That difference is what makes the following work:

.badge {
  font-size: 0.875rem;
  padding: 0.4em 0.7em;
}

The padding resolves against the badge's own 0.875rem text, so it is 0.35rem and 0.6125rem. If a compact variant changes the badge's font size, the padding follows automatically. That is exactly what you want for components where breathing room should track the text inside.

The surprise appears with nesting on font-size. If a parent sets font-size: 1.25em and a child sets font-size: 1.25em, the child compounds to 1.5625 times the grandparent size, because each one resolves against its parent. Three levels of a nested list and text is nearly double. That can be useful in a controlled component and is a menace in user-generated content.

Use em when local scaling is the goal. Use rem when you want consistency from the root.

What vw and vh mean

vw means viewport width. vh means viewport height. One vw is 1% of the viewport width, and one vh is 1% of the viewport height, measured against the initial containing block.

.hero {
  min-height: 70vh;
  padding-inline: 6vw;
}

Viewport units are useful for layout areas that should relate to the browser window: full-screen sections, fluid spacing, and responsive media frames.

Two traps are worth naming.

100vw includes the classic scrollbar. On a desktop browser that reserves a gutter for a vertical scrollbar, the viewport width used by vw is the full window width, while the content area is narrower. A width: 100vw element therefore overflows by the scrollbar width and produces a horizontal scrollbar of its own. For a full-width block inside normal flow, width: 100% is almost always the right answer.

Text sized in vw does not respond to text-only scaling. Browser page zoom changes the viewport size, so vw-based text does grow. But a reader who raises only the default font size, without zooming, sees vw text stay exactly where it was. That is a plausible way to fail WCAG success criterion 1.4.4, which asks that text can be resized to 200% without loss of content or functionality. The fix is not to abandon viewport units but to keep a font-relative term in the mix:

.headline {
  font-size: clamp(2rem, 1rem + 2.5vw, 4.5rem);
}

That says: never below 2rem, never above 4.5rem, and in between grow from a 1rem base at 2.5% of viewport width. On a 1280px viewport the preferred value is 16 + 32, which is 48px. Because the middle term contains 1rem, a raised default font size still moves it.

svh, lvh, and dvh

Classic vh on mobile is measured against the large viewport, the one you get when the browser's address bar has retracted. So 100vh is taller than the visible area while the bar is showing, and a "full screen" panel gets clipped at the bottom.

The viewport unit variants fix this and have shipped across Chrome, Safari, and Firefox since 2022:

  • svh is 1% of the small viewport, the shortest state with all browser interfaces expanded. A 100svh panel always fits.
  • lvh is 1% of the large viewport, matching classic vh.
  • dvh is 1% of the dynamic viewport, which tracks the interfaces as they appear and retract.

dvh is the most accurate and the least calm: because it changes as the user scrolls and the address bar moves, any layout that depends on it reflows during the animation. For a hero or a modal that must never clip, 100svh is usually the safer default, with dvh reserved for elements where the exact fit genuinely matters.

Absolute vs relative units

Pixels are often described as absolute. Rem, em, vw, vh, and percentages are relative. The distinction is practical rather than moral. Absolute units are predictable. Relative units adapt.

Good interfaces usually use both:

Use caseOften suitable
Body font sizerem
Component paddingrem or em
Border widthpx
Icon sizepx, rem, or em
Page max widthrem, px, or ch
Full-height panelsvh, or dvh where exact fit matters
Fluid hero spacingclamp with rem plus vw
Rounded cornerspx or rem

The unit should express the relationship you want. If spacing should grow with text, use relative text-based units. If a border should remain a thin line, px is fine.

Typography and accessibility

Typography is where unit choices become noticeable. Fixed pixel text ignores a raised default font size, though browser zoom still scales it. Rem-based type is tied to the root font size and honours both.

A practical type scale might look like:

:root {
  font-size: 100%;
}

body {
  font-size: 1rem;
  line-height: 1.6;
}

h1 {
  font-size: clamp(2rem, 1rem + 3vw, 3.5rem);
  line-height: 1.1;
}

The body uses rem, while the heading uses a bounded fluid value with a rem term inside it, so it can respond to viewport width without becoming unlimited and without ignoring the reader's setting.

Accessibility is not only unit choice. Two WCAG 2.2 criteria are worth testing against directly:

  • 1.4.4 Resize Text (AA): text can be resized up to 200% without loss of content or functionality.
  • 1.4.10 Reflow (AA): content works at a width equivalent to 320 CSS pixels without requiring scrolling in two dimensions, which in practice means testing a 1280px window at 400% zoom.

A rem-based layout can still fail both if containers have fixed heights, hidden overflow, or a min-width wider than the space available.

Spacing systems

Spacing systems keep designs consistent. A common approach is to define spacing tokens based on rem:

:root {
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
}

Then components use tokens instead of random values:

.card {
  padding: var(--space-6);
  gap: var(--space-4);
}

This is easier to maintain than mixing 13px, 22px, and 37px across a codebase. It also helps design and development teams speak the same sizing language.

Pixels still have a place. A 1px border, 2px focus outline, or 8px radius may be perfectly reasonable. Consistency matters more than pretending one unit solves everything.

Choosing units by component

The easiest way to choose units is to think about the component's behaviour.

Component partSensible unit choiceReason
Body copyremFollows the root text scale
Button paddingemScales with the label
Icon inside textemMatches surrounding text size
Card max widthrem or chKeeps readable line length
Divider borderpxShould stay visually thin
Hero spacingclamp with rem and vwFluid but bounded
Modal heightsvh or dvh with limitsRelates to available screen space

This is a decision aid, not a rigid table. A design system may choose rem for icon sizes to keep all icons on a consistent scale. Another may use em so icons grow with button text. Either can work if the rule is intentional and tested.

Problems appear when a component mixes units without a reason. A card with font-size: 14px, padding: 1.375rem, gap: 9px, and a fixed height: 180px is hard to maintain because each value responds to something different.

Responsive design examples

Consider a card grid. On desktop, each card has room for generous padding. On mobile, the same padding crowds the content.

.card {
  padding: clamp(1rem, 2vw, 1.5rem);
  border-radius: 0.75rem;
}

The padding moves between 1rem and 1.5rem based on viewport width. It will not shrink into nothing or grow wildly.

For a button with text and an icon:

.button {
  font-size: 1rem;
  padding: 0.65em 1em;
  gap: 0.5em;
}

The padding and gap follow the button's own font size. If a compact variant changes that font size, the surrounding space adjusts proportionally.

For a full-screen layout:

.panel {
  min-height: 100svh;
}

Using svh rather than vh means the panel fits the shortest state of the mobile viewport, so nothing is clipped while the address bar is showing.

Breakpoints and fluid values

Breakpoints are still useful. Fluid units do not remove the need to change layout when the available space changes. A three-column desktop grid may need to become two columns, then one. No unit conversion makes three cramped columns readable on a narrow screen.

Use units and breakpoints together:

.cards {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 48rem) {
  .cards {
    grid-template-columns: 1fr;
  }
}

The gap changes fluidly, while the layout changes at a deliberate breakpoint.

There is a rule here that catches almost everyone. Relative units inside a media query do not use your root font size. The Media Queries specification states that relative length units in media queries are based on the initial value, so declarations never affect them. In practice 48rem and 48em in a media query both resolve against the browser's default font size or the user's preference, not against anything your CSS has set on <html>.

Two consequences follow. First, the 62.5% trick does not move your breakpoints: 48rem is still 768px for a reader on a 16px default, not 480px. Second, a reader who has raised their default to 20px gets breakpoints at 960px instead, which is usually the behaviour you want, because their text is larger and needs the simpler layout sooner. It is only surprising if you assumed the value tracked your root.

Also test long words, translated labels, user zoom, and increased text size. Responsive design is not only about screen width. It is about content and user settings too.

A small before-and-after

Here is a rigid version of a mobile-unfriendly card:

.promo-card {
  width: 420px;
  height: 240px;
  padding: 32px;
  font-size: 18px;
}

It may look fine in a desktop mockup. On a narrow screen the fixed width overflows. If the text wraps, the fixed height clips content. If the user raises their font size, the card has no room to adapt.

A more flexible version might be:

.promo-card {
  width: min(100%, 26rem);
  min-height: 15rem;
  padding: clamp(1rem, 3vw, 2rem);
  font-size: 1rem;
}

The card now respects the container width, keeps a reasonable maximum, lets height grow, and uses bounded fluid padding. This does not make the component perfect, but it removes several predictable failure points.

Testing unit choices

You can catch most unit problems with a short manual pass:

  • Zoom the browser to 200% and check whether text clips.
  • Zoom a 1280px window to 400% and check the layout reflows to a single column without horizontal scrolling.
  • Raise the browser's default font size, without zooming, and see what fails to move.
  • Resize the viewport from narrow to wide slowly, watching for a horizontal scrollbar that should not be there.
  • Test a long button label and a long card title.
  • Check a dense component, such as a table toolbar or settings panel.
  • Confirm focus outlines and borders still look intentional.

The default-font-size pass is the one most teams skip, and it is the one that exposes hard-coded px text and pure-vw headings.

When a value fails, change the relationship rather than only the number. A 320px sidebar that overflows may need minmax() or a breakpoint, not 300px. A 6vw heading that gets too large needs clamp(), not a slightly smaller viewport value. The fix usually comes from asking what the size should depend on.

Worked example: converting px to rem

Assume the root font size is 16px. To convert pixels to rem:

rem = px / root font size

So:

pxrem
10px0.625rem
14px0.875rem
18px1.125rem
24px1.5rem
40px2.5rem

If a design specifies a 24px heading and your base is 16px, use 1.5rem. If the base is 20px, 24px becomes 1.2rem. The base matters, and the conversion is only ever a design-time convenience: at run time the rem value tracks whatever the root actually resolves to.

Open the Pixel Converter when you need quick conversions or want to compare px, rem, em, and viewport units without doing the arithmetic repeatedly.

Finishing visual details

Unit choices affect structure, but small visual tools help polish components after the scale is right. The CSS Border Radius Generator is useful for testing corner values on cards, buttons, and media frames. The Box Shadow Generator helps tune depth without guessing blur and spread values. The CSS Gradient Generator can help build backgrounds, but check contrast if text sits on top.

These are finishing tools, not substitutes for responsive structure. A beautiful shadow will not fix a heading that overflows on mobile.

Common mistakes

Using px for every text size. It ignores a raised default font size, even though zoom still works.

Using vw for text without a rem term. Pure viewport text does not respond to text-only scaling and can fail WCAG 1.4.4.

Using 100vw for a full-width block. It includes the scrollbar gutter and causes horizontal overflow. Use 100%.

Forgetting that em compounds on font-size. Nested em-based font sizes multiply; em on other properties does not.

Pinning the root with html { font-size: 16px }. It discards the user's preference and silently defeats every rem below it.

Expecting media query rems to follow your root. They resolve against the initial font size, by specification.

Locking containers with fixed heights. Scalable text needs room to wrap and reflow.

Treating units as a design system by themselves. Tokens, layout rules, and testing still matter.

FAQ

What is the difference between px and rem? px is an absolute CSS unit, defined as one ninety-sixth of an inch, and it does not change with the user's font-size preference. rem is the computed font size of the root element, so it scales with that preference.

When should I use em? Use em when spacing or sizing should relate to the current element's own font size, such as button or badge padding. Be careful using it on font-size itself, where it resolves against the parent and therefore compounds.

What do vw and vh mean? They are viewport units. 1vw is 1% of viewport width and 1vh is 1% of viewport height. On mobile, prefer svh or dvh for full-height panels, because classic vh matches the taller viewport state and clips.

Are rem units always better than px? No. Rem is usually better for type and scalable spacing; px is appropriate for borders, focus rings, and precise details.

How do I convert px to rem? Divide the pixel value by the root font size. With a 16px root, 24px equals 1.5rem.

Can relative units improve accessibility? They support user font-size preferences better than pixel-only design, but an accessible result also needs reflow at 320 CSS pixels, sufficient contrast, readable line height, and real testing.

Should responsive design use only viewport units? No. Viewport units usually need clamp(), rems, percentages, and layout breakpoints around them.

Related guides

Sources

  • CSS length data type - MDN Web Docs. Source for 1px being defined as 1in / 96, for em resolving to the element's own computed font size except on font-size where it uses the inherited value, for rem resolving to the root font size and to its initial value when used within the root's own font-size, and for the definitions of svh, lvh, and dvh.
  • Media Queries Level 4 - W3C. Source for the rule that relative length units in media queries are based on the initial value, so they are never affected by declarations.
  • Understanding SC 1.4.4: Resize Text - W3C Web Accessibility Initiative. Source for the Level AA requirement that text can be resized up to 200% without loss of content or functionality.
  • Understanding SC 1.4.10: Reflow - W3C Web Accessibility Initiative. Source for the 320 CSS pixel reflow requirement at Level AA.

Specifications and browser behaviour were checked in September 2026. Viewport unit support and browser defaults change over time, so verify against current documentation before relying on any behaviour described here. All code samples are BlinkCalc illustrations.

Choose the relationship first

CSS units are small decisions that add up. Before choosing a unit, ask what the size should relate to: the root font size, the local text size, the viewport, or a fixed visual detail. That question leads to better choices than memorising a universal rule, and it makes responsive layouts easier to maintain. Where a rule surprises you, it is usually one of the four in this guide: em compounds on font-size, media query rems ignore your root, 100vw includes the scrollbar, and vw text does not answer to a raised default font size.