CSS Tutorial
CSS Units
px, em, rem, %, vw, and ch. Pick a unit that scales with the thing you actually care about.
A number needs a yardstick
16 is not a size. 16px is. CSS lengths are a number plus a unit (or 0, which may omit the unit). The unit answers: relative to what? A pixel is a screen dot (on today’s browsers, a CSS pixel). An em is the element’s font size. A rem is the root font size. A percent is the parent. vw is the viewport. ch is the width of the “0” character.
Harbor studio’s page should grow with the reader’s type size, cap a measure so lines do not run too long, and keep a photo inside the window. Those are three different relatives. Three units.
The units you will use
| Unit | Relative to | Use it for |
|---|---|---|
px | A CSS pixel | Hairline borders, a 1px rule, a max-width cap |
em | The element’s own font-size (or parent, when setting font-size) | Padding that grows with the text in that box |
rem | The root (html) font-size | Type scale, page padding, most spacing |
% | The parent’s matching size | Fluid widths: width: 100% |
vw | 1% of the viewport width | Full-bleed banners, with care |
ch | Width of the “0” glyph in the current font | A readable measure: max-width: 65ch |
Prefer rem for font-size on the page. If a visitor enlarges root type in the browser, your headings and spacing follow. Hard-coded px type fights that. Try the snippets at/css/try.
em versus rem
Both are font-relative. rem always looks at html. em looks at the current element, so it compounds when you nest. A button with font-size: 1.25em inside a card that is already 1.25em is larger than you meant. That compounding is a feature for padding that should match the button type, and a bug when you thought you were setting a global step.
Example
<style>
html { font-size: 100%; }
body {
font-family: system-ui, sans-serif;
color: #0c4a6e;
background: #f0f9ff;
margin: 1.25rem;
font-size: 1rem;
}
.card {
background: #fff;
padding: 1em;
border: 1px solid #7dd3fc;
border-radius: 0.5rem;
max-width: 22rem;
}
.card h2 {
margin: 0 0 0.4rem;
font-size: 1.25rem;
color: #0d9488;
}
.nested {
font-size: 1.25em;
background: #ccfbf1;
padding: 0.5em 0.75em;
margin-top: 0.75rem;
}
</style>
<h1>Harbor studio</h1>
<article class="card">
<h2>Tide desk</h2>
<p>Heading uses rem — locked to the root.</p>
<p class="nested">This box uses em. Its padding grows with its own type.</p>
</article>Percent and viewport
width: 100% means “as wide as the parent content box.” It does not mean “as wide as the screen” unless the parent already is. width: 100vw is 100% of the viewport width, including the area under a scrollbar — which can create a horizontal scroll. For a column that fills its card, use percent (or just block layout). For a hero that must track the window, vw is the blunt tool.
Example
<style>
body {
font-family: system-ui, sans-serif;
color: #0c4a6e;
background: #f0f9ff;
margin: 1.25rem;
}
.frame {
width: 70%;
max-width: 24rem;
padding: 0.75rem;
background: #fff;
border: 1px solid #bae6fd;
}
.banner {
width: 50vw;
max-width: 100%;
padding: 0.85rem 1rem;
background: #0ea5e9;
color: #fff;
border-radius: 0.4rem;
box-sizing: border-box;
}
h2 { margin: 0; font-size: 1.1rem; }
</style>
<div class="frame">
<div class="banner">
<h2>Harbor studio</h2>
<p>The frame is 70% of its parent. The banner is 50vw, capped at 100% so it cannot overflow the frame.</p>
</div>
</div>ch for a comfortable line
Reading width is about characters, not pixels. Around 45–75 characters per line is the usual range.max-width: 65ch caps the paragraph at roughly 65 “0” widths in the current font. Narrow the preview: the text still fills the window. Widen it: the measure stops so the line does not cross the room.
Example
<style>
body {
font-family: system-ui, sans-serif;
color: #0c4a6e;
background: #f0f9ff;
margin: 1.25rem;
}
h1 {
color: #0d9488;
font-size: 1.5rem;
}
.prose {
max-width: 45ch;
line-height: 1.6;
}
</style>
<h1>Harbor studio</h1>
<p class="prose">
Open 8–16. The darkroom is bookable by the hour. This paragraph stops at 45ch so a wide window
does not stretch a sentence into a ruler.
</p>Mix units on purpose: rem for type and gaps, % or max-width for columns, ch for text measure, px for a 1px border. The next chapter, box-sizing, decides whether padding eats into those widths.
Worked examples
The short listings above show one property. These sheets paint documents you would actually ship: a lab dashboard, a clinic form, a marks table, a nav bar.
CSS does not invent meaning. HTML already said what the pieces are. Cascade, specificity, and the box model decide how they look. The numbers are classroom values — current, pH, pulse, 3-4-5 — so the style has something real to sit on.
Preview them in the CSS editor at /css/try. Change one property and watch the page paint. The tags stay the same.
Maths
rem, em, %, ch
rem is the root font size. em is the parent. % is of the containing block for width. ch is the width of the “0” glyph — handy for measure.
vw is 1% of viewport width. 80vw on a phone is fine; on a 5K monitor you still want max-width. px is a CSS pixel, not a lab millimetre.
1rem = root font-size (often 16px)
Example
<style>
h1 { font-size: 1.75rem; }
p { max-width: 32ch; }
</style>
<h1>Area 12 m²</h1>
<p>About thirty-two characters per line so the formula notes wrap.</p>Physics
Padding in em scales with type
If the chip’s font-size grows, 0.5em padding grows with it. rem padding would stay tied to the page root. Pick the unit that should follow the thing you care about.
Example
<style>
.box { font-size: 18px; padding: 0.5em 1em; background: #e0f2fe; }
</style>
<p class="box">I = 0.45 A</p>