CSS has more units than most developers realize, and choosing the right one affects accessibility, responsiveness, and maintainability. The most common units — px, rem, em, vw, and vh — each have specific strengths and tradeoffs. This guide explains what each unit does, how they relate to each other, and how to convert between them.
The Five Core CSS Units
px (pixels)
Pixels are the most familiar unit. A pixel is a single dot on the screen. When you set font-size: 16px, the text renders at exactly 16 pixels tall. Pixels are absolute — they do not change based on parent size, user preferences, or viewport dimensions.
Use pixels when: you need precise, fixed dimensions — border widths, shadows, icon sizes, and elements that should not scale.
rem (root em)
Rem stands for "root em." It is relative to the root element's font size (the <html> tag). By default, browsers set the root font size to 16px. So font-size: 1.5rem equals 24px at default settings.
Use rem when: you want sizes that scale proportionally if the user changes their browser's default font size. This is critical for accessibility — users who increase their font size for readability will benefit from rem-based layouts.
em
Like rem, em is relative — but it is relative to the parent element's font size, not the root. If a <div> has font-size: 20px and you set a child <span> to font-size: 1.5em, the span renders at 30px (1.5 × 20).
This creates a compounding problem: nested elements multiply their parent's em value, making sizes unpredictable deep in the DOM. This is why most modern CSS methodologies prefer rem over em for font sizes.
vw (viewport width)
Vw is a percentage of the viewport width. 1vw equals 1% of the browser window's width. So on a 1400px-wide viewport, 1vw = 14px. On a 375px phone, 1vw = 3.75px.
Use vw when: you want typography or elements to scale fluidly with the viewport. Hero text that grows and shrinks with the screen is a classic use case.
vh (viewport height)
Vh works like vw but for the viewport height. 100vh equals the full height of the browser window. Useful for full-screen sections and hero areas.
Converting Between Units
The conversion depends on the root font size, which defaults to 16px in all modern browsers:
| From | To | Formula |
|---|---|---|
| px | rem | px ÷ 16 = rem |
| rem | px | rem × 16 = px |
| px | vw | (px ÷ viewport width) × 100 = vw |
| vw | px | (vw × viewport width) ÷ 100 = px |
| em | px | em × parent font size = px |
For example:
24px → rem: 24 ÷ 16 = 1.5rem
1.5rem → px: 1.5 × 16 = 24px
32px → vw (on 1400px viewport): (32 ÷ 1400) × 100 = 2.29vw
The ToolShack CSS Unit Converter handles these conversions instantly — enter a value in any unit and see the equivalent in all other units simultaneously.
Practical Recommendations
Use rem for font sizes
font-size: 1rem for body text, font-size: 2rem for headings. This ensures your typography scales with user preferences and maintains accessibility.
Use px for borders and small decorative elements
border: 1px solid #ddd, border-radius: 4px, box-shadow: 0 2px 8px rgba(0,0,0,0.1). These should not scale.
Use vw for fluid typography
font-size: clamp(1rem, 2.5vw, 2rem) creates text that scales between 16px and 32px based on viewport width. The clamp() function sets minimum and maximum bounds so text never gets too small or too large.
The clamp() Function: Best of All Worlds
Modern CSS offers a function that combines multiple units elegantly. clamp(min, preferred, max) sets a minimum value, a preferred responsive value, and a maximum:
/* Fluid heading: 16px minimum, scales with viewport, 48px maximum */
h1 { font-size: clamp(1rem, 4vw, 3rem); }
/* Fluid spacing: 16px minimum, scales with viewport, 64px maximum */
.section { padding: clamp(1rem, 5vw, 4rem); }
This approach replaces complex media queries with a single line of CSS that adapts to any screen size.
Conclusion
Understanding CSS units is fundamental to building responsive, accessible websites. Use rem for font sizes, px for fixed decorative elements, and vw/vh for fluid scaling. The ToolShack CSS Unit Converter makes conversions effortless, and clamp() lets you combine units for fluid layouts without media queries.