Which unit should I use? 32 situations, each with the unit to reach for, the reason, a line of CSS and one thing to watch. Any of them is two choices away.
Find your unit in two steps
Step 1 of 2
What will vary once this is live? Pick the closest match. Each choice leads to one more question and then to an answer.
The reader's text size or zoom The width or orientation of the window The browser toolbars on a phone The box the component is placed in The font that draws the text How tall a line of text is Paper, or a screen with more dots Nothing varies: I need an angle or a duration Step 2 of 2
You chose: The reader's text size or zoom
What are you setting? Type sizes and the space between blocks Padding inside a button, badge or tag that has its own text size A media query breakpoint A thin border, outline or shadow that should not grow with the text Back Start over
Step 2 of 2
You chose: The width or orientation of the window
What should follow the window? A heading that grows with the window A band that must span the whole window from inside a narrow parent A square or circle that has to fit on screen in both orientations A decoration that has to cover the screen however it is turned Back Start over
Step 2 of 2
You chose: The browser toolbars on a phone
Keep the first screen's button in view before anyone scrolls Match the visible area at every moment, as a chat composer or a bottom sheet does Fill the whole screen once the toolbars have retracted A full-height panel in a layout made for desktop windows Back Start over
Step 2 of 2
You chose: The box the component is placed in
What does the component do with the width it gets? Scale a heading or a gap with the width of its box Split the leftover width of a grid between columns A child that takes a share of its parent's width Size a chart to the fixed height of its panel Back Start over
Step 2 of 2
You chose: The font that draws the text
What do you want to measure in the font? A comfortable line length for reading A line length that must not change when a component switches font An icon as tall as the capital letters of its label An inline icon as tall as the lowercase letters around it A line of Chinese, Japanese or Korean text counted in characters Back Start over
Step 2 of 2
You chose: How tall a line of text is
Whose line height is the measure? A gap between paragraphs that equals one line of their own text Section spacing in whole lines of body text, the same everywhere Back Start over
Step 2 of 2
You chose: Paper, or a screen with more dots
What are you preparing? Body text in a print stylesheet The margins of a printed page Serve a sharper image to dense screens Offer two files for one image and let the browser choose Back Start over
Step 2 of 2
You chose: Nothing varies: I need an angle or a duration
What turns or takes time? A rotation or gradient direction that people will edit by hand A spinner or loop that ends where it began An angle that comes from the Math functions of JavaScript Short interface feedback that you tune in small steps A fade or slide that takes about half a second Back Start over
Every scenario The same answers as the steps above, in one list. Each heading has an address of its own.
The reader's text size or zoom Second question: What are you setting?
Type sizes and the space between blocks Use rem
rem multiplies the font size of the html element, so everything written in it follows the default text size the reader picked.
Example h1 {
font-size : 2 rem ;
margin-block-end : 1.5 rem ;
} Watch out Leave the font size on html alone. A root size in pixels switches that setting off for every rem on the page.
Padding inside a button, badge or tag that has its own text size Use em
Padding in em is a multiple of the font size on that very tag, so when the tag's text gets bigger or smaller the padding goes with it.
Example .tag {
font-size : 0.875 rem ;
padding : 0.25 em 0.6 em ;
} Watch out Keep em out of font-size on nested elements: the factor is applied again at every level of nesting.
A media query breakpoint Use em
A breakpoint in em moves with the reader's default font size, where one in px stays at a fixed number of pixels.
Example @media ( min-width : 40 em ) {
.nav { display : flex ; }
} Watch out Write all breakpoints in one unit. Em ones shift with the default size and px ones do not, so a mix can change order.
A thin border, outline or shadow that should not grow with the text Use px
px ignores the default text size, which is what a one-pixel line needs.
Example .rule {
border-block-end : 1 px solid ;
} Watch out Page zoom still scales px, and a CSS pixel is not always one screen pixel.
The width or orientation of the window Second question: What should follow the window?
A heading that grows with the window Use vwrem
Put vw inside clamp() beside a rem term: the vw part tracks the window and the rem part ties the size to the reader's settings.
Example h1 {
font-size : clamp ( 1.5 rem , 1 rem + 2.5 vw , 3 rem );
} Watch out Text sized in vw alone ignores zoom and may fail the text-resize requirement, WCAG 1.4.4.
A band that must span the whole window from inside a narrow parent Use vw
vw is measured against the window, so the element does not care how wide its parent is.
Example .band {
inline-size : 100 vw ;
} Watch out 100vw includes the width of a classic vertical scrollbar, which can add a horizontal one.
A square or circle that has to fit on screen in both orientations Use vmin
vmin is a hundredth of the shorter side of the window, so a box under 100vmin cannot be bigger than the window along either axis.
Example .dial {
inline-size : 70 vmin ;
aspect-ratio : 1 ;
} Watch out Do not size text with it alone. Like vw, it ignores zoom.
A decoration that has to cover the screen however it is turned Use vmax
vmax is a hundredth of the longer side, so a shape sized in it reaches past the shorter side as well.
Example .glow {
inline-size : 150 vmax ;
aspect-ratio : 1 ;
border-radius : 50 % ;
} Watch out A shape this big is larger than the screen in the other direction and overflows unless a parent clips it.
Second question: What should a full-height box do while the toolbars move?
Keep the first screen's button in view before anyone scrolls Use svh
svh is the height with the toolbars fully shown, the smallest the screen gets, so nothing sized to it hides behind them.
Example .opening {
min-block-size : 100 svh ;
} Watch out When the toolbars retract, the box is shorter than the screen and a strip behind it shows.
Use dvh
dvh follows the toolbars as they show and hide, so the box is always exactly as tall as what can be seen.
Example .thread {
block-size : 100 dvh ;
} Watch out The box is resized each time the toolbars move, so give it children that can take a change of height: a scrolling middle between a fixed top and bottom.
Fill the whole screen once the toolbars have retracted Use lvh
lvh is the height with the toolbars retracted, the largest the screen gets.
Example .scenery {
min-block-size : 100 lvh ;
} Watch out Text and buttons that must stay visible while the toolbars are shown do not belong in a box sized this way.
A full-height panel in a layout made for desktop windows Use vh
vh is a hundredth of the viewport height and the shortest thing to write when toolbars are not part of the problem.
Example .panel {
min-block-size : 60 vh ;
} Watch out On phones 100vh matches the viewport with the toolbars retracted, so the bottom can hide behind the browser's controls.
The box the component is placed in Second question: What does the component do with the width it gets?
Scale a heading or a gap with the width of its box Use cqi
cqi is a hundredth of the container's inline size, so it measures the box the component sits in and not the window.
Example .card-wrap {
container-type : inline-size;
}
.card h2 {
font-size : clamp ( 1.5 rem , 8 cqi , 3 rem );
} Watch out Set container-type on the wrapper, not on the heading: an element's own container-type serves its descendants and not itself.
Split the leftover width of a grid between columns Use fr
fr hands out the free space of a grid track list in proportion to the numbers you write.
Example .gallery {
display : grid ;
grid-template-columns : 1 fr 2 fr ;
gap : 1 rem ;
} Watch out A plain 1fr track will not shrink below its content. Write minmax(0, 1fr) when a long word or wide image must not widen the grid.
A child that takes a share of its parent's width Use %
A percentage is a share of a reference value, and for a width the reference is the width of the parent.
Example .sidebar {
inline-size : 30 % ;
} Watch out Percentages in padding and margin are measured against width on every side, so padding-block: 10% is not a tenth of the height.
Size a chart to the fixed height of its panel Use cqh
cqh is a hundredth of the container's height, so the chart keeps its share of the panel.
Example .panel {
container-type : size;
block-size : 20 rem ;
}
.panel .chart {
block-size : 80 cqh ;
} Watch out A size container ignores its children when it works out its own size, so give it a height or it can collapse to zero.
The font that draws the text Second question: What do you want to measure in the font?
A comfortable line length for reading Use ch
ch is the width of the zero in the current font, so a cap of 65ch follows whichever font draws the paragraph.
Example .story {
max-inline-size : 65 ch ;
} Watch out ch counts one glyph, the zero. Most letters of prose are narrower, so 65ch holds more than 65 characters.
A line length that must not change when a component switches font Use rchch
rch measures the zero in the font of the root element, so the width stays put whatever family the component uses.
Example .story {
max-inline-size : 65 ch ;
}
@supports ( width : 1 rch ) {
.story { max-inline-size : 65 rch ; }
} Watch out A browser that does not know the unit drops the whole declaration, so keep a ch line before it. The unit page shows current support.
An icon as tall as the capital letters of its label Use cap
cap is the height of the capitals in the current font, so the icon stays level with its label in any font.
Example .btn svg {
block-size : 1 cap;
} Watch out Older browsers ignore the unit, so write a fallback declaration before the cap one.
An inline icon as tall as the lowercase letters around it Use ex
ex follows the x-height of the font in use, so the icon scales with the lowercase letters.
Example .inline-icon {
inline-size : 2 ex ;
block-size : 2 ex ;
} Watch out x-height varies more between fonts than font-size does, and if the intended font fails to load, every ex value changes with the fallback.
A line of Chinese, Japanese or Korean text counted in characters Use ic
ic is the width of the ideograph 水 in the current font, so 40ic is a line of about forty full-width characters.
Example .note {
max-inline-size : 40 ic ;
} Watch out A font without CJK glyphs cannot measure the ideograph, and the unit then falls back to 1em.
How tall a line of text is Second question: Whose line height is the measure?
A gap between paragraphs that equals one line of their own text Use lh
lh is the line height of the paragraph that carries it, so the gap stays one line whatever the font size.
Example p + p {
margin-block-start : 1 lh;
} Watch out With line-height: normal, 1lh depends on the font's own metrics, and a line can grow taller when tall inline content sits in it.
Section spacing in whole lines of body text, the same everywhere Use rlh
rlh takes the line height set on html, so every section counts its gaps in the same line.
Example section {
padding-block : 2 rlh ;
} Watch out A component with larger text gets no taller gaps from it. For the component's own lines, use lh.
Paper, or a screen with more dots Second question: What are you preparing?
Body text in a print stylesheet Use pt
A point is 1/72 of an inch, the unit in which printers and designers quote type sizes.
Example @media print {
body { font-size : 11 pt ; }
} Watch out On a screen 12pt is always 16px, so points say nothing about the real size of a display.
The margins of a printed page Use in
An inch is 96px, 2.54cm and 72pt, so one inch value anchors every other physical size on the sheet.
Example @page {
margin : 0.75 in ;
} Watch out Nothing on screen is measured with a ruler. 1in always draws as 96 CSS pixels, and only paper output makes it physical.
Serve a sharper image to dense screens Use dppx
dppx counts device dots per CSS pixel, the same number that window.devicePixelRatio reports.
Example @media ( min-resolution : 2 dppx ) {
.hero-art { background-image : url ( "hero-2x.webp" ); }
} Watch out Page zoom changes the ratio too, so at 200% zoom on a 1x display the query already matches 2dppx.
Offer two files for one image and let the browser choose Use x
x is the short spelling of dppx, and the form image-set() descriptors are written in.
Example .badge {
background-image : image-set (
url ( "badge.png" ) 1x ,
url ( "badge-2x.png" ) 2x ,
url ( "badge-3x.png" ) 3x
);
} Watch out x is accepted only where a resolution fits. It is not a multiplier for widths or font sizes.
Nothing varies: I need an angle or a duration Second question: What turns or takes time?
A rotation or gradient direction that people will edit by hand Use deg
A full turn is 360deg, a number people can read and adjust at a glance.
Example .arrow {
rotate : 45 deg ;
} Watch out A bare number is not an angle in transform functions. rotate(45) is invalid and the whole transform is dropped.
A spinner or loop that ends where it began Use turn
1turn is one full rotation, so the last keyframe lands on the first without a number to remember.
Example @keyframes spin {
to { rotate : 1 turn ; }
} Watch out Values above 1turn spin more than once in an animation, but a static 2.5turn looks like 0.5turn.
An angle that comes from the Math functions of JavaScript Use rad
Math.sin and its relatives work in radians, so handing CSS radians skips a conversion.
Example .needle {
rotate : 1.5708 rad ;
} Watch out CSS trigonometric functions read a plain number as radians, so sin(1) is one radian and sin(90deg) is the one that equals 1.
Short interface feedback that you tune in small steps Use ms
ms keeps small durations as whole numbers, so 150ms reads more clearly than 0.15s.
Example .toast {
transition : transform 200 ms ease-out ;
} Watch out For long animations 2s reads easier than 2000ms.
A fade or slide that takes about half a second Use s
s is the base unit of time in CSS and reads best for whole and half-second timings.
Example .menu {
transition : transform 0.4 s ease-in-out ;
} Watch out Zero is not exempt: transition-duration: 0 is invalid, and 0s is the form that works.