Values and visual language
Length units
Choose pixels, rems, ems, percentages, viewport units, and character units according to what a size should respond to.
Every length in CSS is relative to something. Even pixels. To choose a unit, ask: what should this size follow when things change?
The units you’ll actually use:
pxis the CSS pixel. It’s a reference unit, not a physical dot. On a high-density display one CSS pixel covers several device pixels.remis relative to the root font size, set on thehtmlelement. By default that’s16px, so1.5remis24px.emis relative to the element’s own font size. Onfont-sizeitself it uses the parent, since the element has no size yet.%is relative to the containing block, usually the parent. What it measures depends on the property.vwandvhare 1% of the viewport width and height.chis the width of the0character in the current font. It’s the natural unit for line length.
Why I default to rem
Users can raise the default font size in their browser settings. rem values scale with it, px values don’t. So I write font sizes, spacing, and max widths in rem, and keep px for things that shouldn’t scale, like a 1px border.
em is useful inside a component: a button’s padding in em grows with the button’s text. But em compounds. Nested elements with font-size: 1.2em get bigger and bigger. rem doesn’t have that problem.
Readable line length
A rule I put on almost every page:
.article {
width: min(100% - 2rem, 65ch);
margin-inline: auto;
}
65ch is about 65 characters per line, a comfortable measure. min() picks the smaller value: full width minus a gutter on a narrow screen, 65 characters on a wide one. margin-inline: auto centers it.
Viewport units on mobile
100vh sounds like “the full screen”. On phones it often isn’t, because the address bar slides in and out. A 100vh panel can end up with its bottom hidden behind browser UI.
Newer units fix this. svh is the small viewport, bars visible. lvh is the large one, bars hidden. dvh updates live as they move. My advice: let content decide the height with min-height, and reach for dvh only when you really need a full-height panel.
Percentages need context
width: 50% is half the containing block’s width. But padding-top: 50% is also relative to the containing block’s width, not its height. When a percentage does something odd, check the used pixel value in the Computed panel instead of guessing what it’s relative to.
Try the course page with these changes: resize the window, zoom to 200%, and set the browser’s default font size to 20px. Text should never get clipped and the page should never scroll horizontally. If it does, some value is using the wrong unit.
Lesson completed