Units
Every length in CSS needs a unit. The right unit is the difference between a layout that adapts and one that breaks on the first phone it meets.
Absolute: px
HTML
<style>
.box { width: 200px; height: 60px; padding: 8px; background: #eef0ff; border: 2px solid #5a48f5; font: 16px system-ui; }
</style>
<div class="box">200px wide, always</div>A CSS pixel is a fixed size on screen (high-resolution screens draw each one with several physical pixels). Pixels are right for borders and fine details, but rigid for text and layout.
Relative to the font: rem and em
remis relative to the root font size, the<html>element's, which is 16px by default.2remis 32px.emis relative to the current element's font size, so it compounds when nested.
HTML
<style>
body { font-family: system-ui; }
.em { font-size: 1.2em; }
.rem { font-size: 1.2rem; }
.em, .rem { border-left: 3px solid #5a48f5; padding-left: 8px; margin: 4px 0; }
</style>
<div class="em">1.2em
<div class="em">1.2em inside 1.2em
<div class="em">and again: it keeps growing</div>
</div>
</div>
<div class="rem">1.2rem
<div class="rem">1.2rem inside 1.2rem
<div class="rem">always the same size</div>
</div>
</div>Percentages
A percentage is relative to the parent, usually to its width:
HTML
<style>
* { box-sizing: border-box; }
.parent { width: 300px; background: #f2f2f6; font: 14px system-ui; }
.child { width: 50%; padding: 8px; background: #d9f7ea; }
</style>
<div class="parent">
<div class="child">50% of 300px = 150px</div>
</div>Viewport units
| Unit | Means |
|---|---|
vw | 1% of the viewport's width |
vh | 1% of the viewport's height |
dvh | 1% of the dynamic viewport height, which allows for a phone's browser bars sliding in and out |
vmin, vmax | 1% of the smaller or larger dimension |
HTML
<style>
body { margin: 0; font-family: system-ui; }
.hero { height: 60vh; display: grid; place-items: center; color: white; font-size: 6vw;
background: linear-gradient(135deg, #5a48f5, #0aa9cf); }
</style>
<div class="hero">60vh tall, 6vw text</div>In this preview, the "viewport" is the preview box; on a real page, it's the browser window. On phones, height: 100vh can be taller than what's visible because of the address bar, and 100dvh fixes that.
calc(): mixing units
HTML
<style>
* { box-sizing: border-box; }
.layout { display: flex; font: 14px system-ui; }
.side { width: 120px; padding: 8px; background: #fff4dc; }
.main { width: calc(100% - 120px); padding: 8px; background: #eef0ff; }
</style>
<div class="layout">
<div class="side">120px</div>
<div class="main">calc(100% - 120px)</div>
</div>calc() adds, subtracts, multiplies and divides, and it can mix units, which nothing else can. The spaces around + and - are required.
min(), max() and clamp()
HTML
<style>
* { box-sizing: border-box; }
body { font-family: system-ui; }
.card { width: min(100%, 400px); padding: 12px; border-radius: 8px; background: #eef0ff; }
.title { font-size: clamp(1.2rem, 5vw, 2.4rem); margin: 0; }
</style>
<div class="card">
<h2 class="title">Fluid heading</h2>
<p>This card is 400px wide, or the full width when that's narrower. The heading grows with the viewport, but never below 1.2rem or above 2.4rem.</p>
</div>min(a, b)uses the smaller value:width: min(100%, 400px)means "400px, but never wider than the parent".max(a, b)uses the larger one.clamp(minimum, preferred, maximum)uses the preferred value, held between the limits. It's the standard way to make text scale smoothly.
Which unit when?
| For | Use |
|---|---|
| font sizes | rem |
| spacing that scales with text | rem or em |
| borders, shadows, hairlines | px |
| widths inside a layout | %, fr (in grids) or min() |
| full-screen sections | dvh and vw |
| a readable line length | ch: max-width: 65ch is about 65 characters |
Finished this lesson?Mark it complete to earn +20 XP and move your progress on.