CSS units look simple until you have to choose the right one for typography, spacing, layout, animation, or responsive behavior. A bad default can make text too rigid, layouts too fragile, or components scale in ways you did not intend.
The useful mental model is not just absolute vs relative. CSS units fall into several groups, and each group answers a different question: should the value stay fixed, scale with the font, follow the viewport, respond to the container, or control motion and media behavior?
The short version
If you only remember a few rules, remember these:
1 Use rem for most UI
Use rem for most font sizes and spacing in app UI.
2 Use em for local scale
Use em when a component should scale from its own text size.
3 Use px for fixed detail
Use px for hairlines, borders, and values that should stay visually fixed.
4 Use viewport units intentionally
Use viewport units like vw and vh for full-screen or hero-style layouts.
5 Use container queries for components
Use container query units like cqw and cqh when the component should react to its own container, not the whole page.
6 Use fr for grid tracks
Use fr only for CSS Grid track distribution.
The main categories
CSS units are easiest to understand if you separate them by what they relate to.
| Category | Examples | What they are relative to |
|---|---|---|
| Absolute length | px, cm, mm, Q, in, pt, pc | Physical units or a fixed CSS reference |
| Font-relative length | em, rem, ex, ch, ic, lh, rlh | The current font, root font, glyph metrics, or line height |
| Viewport-relative length | vw, vh, vmin, vmax, vi, vb, svw, svh, lvw, lvh, dvw, dvh | The viewport or viewport variants on mobile |
| Container-relative length | cqw, cqh, cqi, cqb, cqmin, cqmax | The size of the nearest query container |
| Percentage | % | A property-specific reference, usually the parent or containing box |
| Grid flex | fr | Free space in CSS Grid |
| Angle | deg, grad, rad, turn | Rotations and gradients |
| Time | s, ms | Animation and transition duration |
| Frequency | Hz, kHz | Audio or related niche media features |
| Resolution | dpi, dpcm, dppx, x | Output density |
The big surprise for many developers is that CSS units are not just length values. Once you include time, angle, frequency, and resolution, you get the full picture of how CSS expresses size, motion, and display characteristics.
Absolute length units
Absolute length units are the ones people usually learn first. They feel fixed, and for day-to-day UI work, most of them are not used very often.
The common set is px, cm, mm, Q, in, pt, and pc. In practice, px is the unit you will use most often. The rest exist mainly for print, legacy workflows, or conversion compatibility.
px is not the same thing as a physical device pixel. In CSS, it is a reference pixel that behaves consistently across screens. That is why it is safe for borders and one-off visual details, even though it is not truly physical.
.card {
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 12px;
padding: 16px;
}
That is a reasonable use of px. If you changed the border width to rem, it would grow with text settings and often feel awkward. Fixed visual accents are one of the few places where px is still the right tool.
Font-relative units
Font-relative units are the workhorses of modern CSS. They let your interface scale with typography instead of staying locked to a hardcoded number.
rem
rem is relative to the root element font size, usually the html font size. This makes it the safest default for app-level sizing because the whole interface can scale together if the root font size changes.
Use rem for body text, component padding, and layout widths that should stay readable across accessibility settings.
html {
font-size: 100%;
}
.panel {
font-size: 1rem;
padding: 1.5rem;
border-radius: 0.75rem;
gap: 1rem;
}
.panel h2 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
em
em is relative to the element's own computed font size. That makes it ideal when you want a component to scale from its own text context.
Use em for buttons and pills that should scale with text, nested components that need local proportional spacing, and pseudo-elements or decorative offsets tied to the current font size.
.chip {
font-size: 0.875rem;
padding: 0.5em 0.8em;
border-radius: 9999px;
}
.chip svg {
width: 1em;
height: 1em;
}
The key difference is that em compounds. That is useful when you want local scaling, but it can get messy if you apply it too deeply and forget what the inherited font size already is.
ch, lh, and the smaller font-relative units
These are the more specialized font-relative units.
ex is based on the x-height of the font. ch is based on the width of the 0 glyph. ic relates to the advance measure of ideographic characters. lh equals the computed line height of the element, and rlh equals the root element's line height.
These units are not everyday defaults, but they are useful in typography-heavy layouts. Use ch for readable text widths. A line length around 45 to 75 characters is usually easier to scan.
.prose {
max-width: 68ch;
line-height: 1.65;
}
.form-field {
margin-bottom: 1lh;
}
The lh unit is underrated. It is excellent for vertical rhythm because it follows the element's own line height instead of a guessed pixel value.
Percentage units
% is not a length category by itself. It depends on the property.
For width and height, the percentage usually refers to the containing block. For padding and margin, it often uses the inline size of the containing block, which surprises people the first time they try to use percentage padding for vertical spacing.
Use % when the browser already knows the right reference box and you want the element to fill a proportional share of it.
.figure {
width: 100%;
aspect-ratio: 16 / 9;
}
.sidebar {
width: 28%;
}
.content {
width: 72%;
}
Percentages are powerful, but only if the containing size is well defined. For height, that means the parent must usually have an explicit height somewhere in the chain.
Viewport-relative units
Viewport units scale relative to the browser viewport rather than the font or container.
The classic ones are vw, vh, vmin, and vmax. More recent logical variants include vi and vb, which track the inline and block axes. Mobile-safe variants such as svw, svh, lvw, lvh, dvw, and dvh address the browser chrome problems that made classic viewport sizing unreliable on phones.
Use viewport units for full-height sections, hero typography that should scale with screen size, and layouts that are deliberately tied to the viewport.
.hero {
min-height: 100svh;
padding-inline: clamp(1rem, 4vw, 3rem);
}
.hero h1 {
font-size: clamp(2.25rem, 6vw, 5rem);
}
The newer mobile viewport units are important. If you have ever seen a full-screen panel jump when the address bar appears or disappears, the stable and dynamic viewport variants exist to fix exactly that kind of issue.
Container query units
Container query units are the newest important part of the unit story. They let an element size itself based on its own query container rather than the viewport.
These units include cqw, cqh, cqi, cqb, cqmin, and cqmax.
Use them when a component can live in different layout regions and should adapt to the available space inside each one.
.card-grid {
container-type: inline-size;
}
.card-title {
font-size: clamp(1rem, 4cqw, 1.75rem);
}
.card {
padding: clamp(1rem, 3cqw, 2rem);
}
Container units solve a real limitation of viewport units: a sidebar card does not care how wide the whole browser is. It cares how much room its own container has.
Grid flex units
fr is special. It is not a generic length unit. It is the flexible fraction unit used by CSS Grid to divide remaining space.
Use fr when you want tracks to share free space in proportion to each other.
.layout {
display: grid;
grid-template-columns: 280px 1fr;
gap: 1.5rem;
}
The fr unit belongs to grid track sizing, not to padding, margins, or font sizes. That is why it feels like a unit but behaves more like a distribution rule.
Angle, time, frequency, and resolution units
These unit families do not size boxes, but they are still part of the complete CSS unit system.
deg, grad, rad, and turn are used for rotation, gradients, and conic effects.
s and ms control transition and animation durations.
Hz and kHz show up in niche media and audio-related contexts.
dpi, dpcm, dppx, and x describe pixel density for screens and image output.
.spinner {
animation: spin 1.2s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(1turn);
}
}
.thumbnail {
background-image: image-set(
url('/img/card.png') 1x,
url('/img/card@2x.png') 2x
);
}
These units usually stay out of your way until you need them. Then they become necessary.
What to use in real projects
The safest default strategy is simple.
1 Typography
Use rem for base sizes and em for components that should scale with local text size.
2 Spacing
Use rem for app-wide spacing and em for spacing that should track a component's own scale.
3 Responsive layout
Use %, vw, vh, or container query units depending on whether the reference should be the parent, the viewport, or the component container.
4 Motion
Use ms and s for transitions and animations, and keep durations short unless the interaction is intentionally slow.
Common mistakes
Three mistakes show up again and again.
A practical cheat sheet
| Need | Best first choice | Why |
|---|---|---|
| Stable borders or hairlines | px | Fixed visual detail |
| App-wide spacing | rem | Scales with root typography |
| Component-local padding | em | Tracks local font size |
| Full-width or fluid sections | % or vw | Follows available space |
| Full-screen panels | 100svh | Safer on mobile than old viewport patterns |
| Cards inside reusable layout blocks | cqw | Responds to the container |
| Grid track splits | fr | Shares free space cleanly |
| Animation timing | ms or s | Matches motion semantics |
| Rotations and gradients | deg or turn | Clear angle syntax |
Final rule
The best CSS unit is the one that matches the thing you are trying to express.
If the design should follow the root typography, use rem. If it should follow the component, use em or container units. If it should follow the screen, use viewport units. If it should stay fixed, use px. If it is not a length at all, use the matching family for angle, time, frequency, or resolution.
That is the real complete list: not just the names of the units, but the job each one is meant to do.