CSS Units & Functions — Complete Guide with Examples
In this tutorial, you'll learn about CSS Units & Functions. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
CSS provides many units and functions for sizing and calculations. Choosing the right one makes your layouts responsive, accessible (respects user font-size preferences), and much easier to maintain.
What You'll Learn
By the end of this tutorial, you'll understand absolute vs relative units, use rem for fonts and em for spacing, use %, vw, vh, vmin, vmax for responsive sizing, use ch for readable line lengths, and use calc(), min(), max(), clamp() for powerful calculations.
Prerequisite: You should understand the box model. CSS Box Model covers what you need.
Where This Fits
flowchart LR
A["Box Model"] --> B["**Units & Functions**"]
B --> C["Positioning"]
C --> D["Flexbox & Grid"]
D --> E["Responsive Design"]
style B fill:#f97316,stroke:#c2410c,color:#fff
style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
style E fill:#22c55e,stroke:#16a34a,color:#fff
Absolute vs Relative Units
Absolute units are fixed sizes. They don't change regardless of the viewport, parent element, or user settings.
Relative units scale based on context — the viewport size, the parent's font size, or the root font size. They're essential for Responsive Design and Accessibility.
Absolute Units
Only px is commonly used for screen display:
.box { width: 300px; font-size: 16px; border: 1px solid #ddd; }
Other absolute units (pt, cm, mm, in) are for print stylesheets only.
When to use px: Borders (1px), images (fixed pixel dimensions), and precise layout constraints.
Relative Units — The Building Blocks of Responsive Design
| Unit | Relative to | Best For |
|---|---|---|
% |
Parent element | Width, height of containers |
em |
Parent's font-size | Padding, margin that scales with font |
rem |
Root font-size (<html>) |
Font sizes (accessible and predictable) |
vw |
Viewport width (1vw = 1% of width) | Full-width sections, hero areas |
vh |
Viewport height (1vh = 1% of height) | Full-screen sections |
vmin |
Smaller of vw/vh | Elements that should fit both dimensions |
vmax |
Larger of vw/vh | Rarely used |
ch |
Width of "0" character | Line length for readability |
ex |
Height of "x" character | Niche typography uses |
rem — The Best Unit for Font Sizes
rem stands for "root em". 1rem = the font size of the <html> element (usually 16px by default in browsers).
html { font-size: 16px; } /* Default browser setting */
body { font-size: 1rem; } /* 16px */
h1 { font-size: 2.5rem; } /* 40px */
h2 { font-size: 2rem; } /* 32px */
p { font-size: 1rem; } /* 16px */
small { font-size: 0.875rem; } /* 14px */
Why rem over px for fonts? If the user has set their browser to prefer larger text (Accessibility setting), the root font size might be 20px instead of 16px. With rem, your font sizes scale proportionally. With px, they stay fixed and small.
em — Scales with Its Parent
em is relative to the parent element's font size:
.card { font-size: 18px; }
.card p { font-size: 1em; } /* 18px (1 × 18px) */
.card .btn { font-size: 0.9em; } /* 16.2px (0.9 × 18px) */
em is great for padding and margins that should scale with the font:
.btn {
font-size: 1rem;
padding: 0.5em 1em; /* Scales automatically if font size changes */
}
.btn-lg {
font-size: 1.25rem; /* Bigger font → bigger padding automatically */
}
The em trap: Nested ems compound:
/* ❌ Nested ems compound */
.parent { font-size: 1.5em; } /* 1.5 × 16 = 24px */
.child { font-size: 1.5em; } /* 1.5 × 24 = 36px (oops!) */
This is why rem is preferred for font sizes and em is used mainly for spacing that should scale with a specific component's font.
% — Relative to Parent
.child { width: 50%; } /* Half the parent's width */
.child { padding: 10%; } /* 10% of parent's WIDTH (not height) */
Key gotcha: Percentage padding/margin is calculated based on the parent's width, not height. This is why the padding-bottom trick for responsive aspect ratios works.
vw and vh — Relative to Viewport
.hero { height: 100vh; } /* Exactly full viewport height */
.full-width { width: 100vw; } /* Exactly full viewport width */
.scaling-text { font-size: 5vw; } /* Scales with viewport width */
100vw gotcha: 100vw includes the scrollbar width, which can cause horizontal overflow. Use width: 100% instead for full-width containers.
ch — Character Width for Readability
The ideal line length for reading is about 50-75 characters. ch makes this easy:
article {
max-width: 65ch; /* ~65 characters wide — perfect for reading */
}
CSS Functions
calc() — Arithmetic with Mixed Units
calc() lets you combine different units with +, -, *, /:
.sidebar { width: calc(100% - 250px); } /* Fluid - fixed */
.card { width: calc(33.333% - 1rem); } /* 3 columns with gap */
.banner { height: calc(100vh - 80px); } /* Full height minus nav */
.column { width: calc(100% / 3 - 20px); } /* Third minus gap */
Space rules: calc(100% - 20px) works. calc(100%-20px) does NOT. Spaces around the operator are required for + and -.
min() and max() — Pick a Value
min() picks the smallest value. max() picks the largest.
/* Width: 100% until 1200px, then capped */
.container { width: min(100%, 1200px); }
/* Width: at least 300px */
.element { width: max(300px, 50%); }
/* Padding: at least 16px but no more than 48px */
.element { padding: min(48px, 5vw); }
Why min() beats media queries: Instead of writing max-width: 1200px and then a media query for smaller screens, min(100%, 1200px) does it in one line.
clamp() — The Ultimate Responsive Function
clamp(MIN, PREFERRED, MAX) clamps a value between a minimum and maximum:
/* Fluid typography: min 1.5rem, preferred 4vw, max 3rem */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
/* Fluid width: min 280px, preferred 50%, max 600px */
.card { width: clamp(280px, 50%, 600px); }
/* Fluid padding: min 16px, preferred 2vw, max 32px */
.container { padding: clamp(16px, 2vw, 32px); }
Without clamp(): You'd need 3 media queries. With clamp(): One line.
var() — Custom Properties (CSS Variables)
:root {
--primary: #3498db;
--gap: 1rem;
}
.button {
background: var(--primary);
margin: var(--gap);
}
attr() — HTML Attributes in CSS
[data-tooltip]::after {
content: attr(data-tooltip);
}
url() — Reference External Files
background: url('bg.jpg');
@font-face { src: url('font.woff2'); }
env() — Device Environment
/* Safe area for notched phones (iPhone X+) */
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
Which Unit Should I Use? (Decision Table)
| What you're sizing | Best unit | Why |
|---|---|---|
| Font size | rem |
Respects user preferences, predictable |
| Padding/margin (component) | em |
Scales with component's font size |
| Container width | %, min(), clamp() |
Responsive, fluid |
| Full-screen section | vh, vw |
Fills viewport |
| Line length | ch |
Readable text blocks |
| Border | px |
Shouldn't scale |
| Media queries | px, em |
Consistent breakpoints |
Common Unit Mistakes
1. Using px for Font Sizes
/* ❌ Wrong: doesn't respect user font-size preferences */
body { font-size: 14px; }
/* ✅ Correct: rem respects user settings */
body { font-size: 1rem; }
2. Using em for Font Sizes (Compounding Problem)
/* ❌ Wrong: nested ems compound unpredictably */
.card { font-size: 1.25em; }
.card .title { font-size: 1.5em; } /* This is 1.5 × 1.25 × 16px = 30px */
/* ✅ Correct: rem stays consistent */
.card { font-size: 1.25rem; }
.card .title { font-size: 1.5rem; } /* Always 1.5 × 16px = 24px */
3. Forgetting Spaces in calc()
/* ❌ Wrong: no spaces around + */
width: calc(100%-20px);
/* ✅ Correct */
width: calc(100% - 20px);
4. Using 100vw Instead of 100%
/* ❌ Wrong: causes horizontal scrollbar (scrollbar adds width) */
.full-width { width: 100vw; }
/* ✅ Correct */
.full-width { width: 100%; }
5. Setting height: 100% Without Parent Height
/* ❌ Wrong: 100% of nothing = nothing */
body { height: 100%; } /* body has no explicit height */
.full-page { height: 100%; } /* 100% of 0 = 0 */
/* ✅ Correct: chain the height */
html, body { height: 100%; }
.full-page { height: 100%; }
Try It Yourself
See units and functions in action:
Common Mistakes Beginners Make
1. Skipping the Fundamentals
Many beginners jump straight to advanced topics without mastering the basics. Take time to understand the core concepts before moving on.
2. Not Practicing Enough
Reading tutorials without writing code leads to shallow understanding. Code along with every example and experiment on your own.
3. Ignoring Error Messages
Error messages tell you exactly what went wrong. Read them carefully — they usually point to the line and type of issue.
4. Copy-Pasting Without Understanding
It's tempting to copy code from tutorials, but typing it yourself and understanding each line builds real skill.
5. Giving Up Too Early
Every developer hits frustrating bugs. Take breaks, ask for help, and remember that struggling is part of learning.
Practice Questions
Q1: What's the difference between em and rem?
{{< details "Show answer" >}}
em is relative to the parent's font size. rem is relative to the root (<html>) font size. em compounds with nesting; rem does not.
{{< /details >}}
Q2: What's clamp() and when would you use it?
{{< details "Show answer" >}}
clamp(MIN, PREFERRED, MAX) returns a value between a minimum and maximum, scaling fluidly in between. Used for fluid typography and responsive sizing without media queries.
{{< /details >}}
Q3: What happens if no spaces are around operators in calc()?
{{< details "Show answer" >}}
calc(100%-20px) fails. Spaces around + and - are required. * and / don't require spaces but it's good practice.
{{< /details >}}
Q4: What unit should you use for line lengths for good readability?
{{< details "Show answer" >}}
ch — which is the width of the "0" character. max-width: 65ch creates a readable text width of about 65 characters.
{{< /details >}}
Q5: Why is 100vw problematic?
{{< details "Show answer" >}}
100vw includes the scrollbar width, which can cause horizontal overflow on desktop. Use width: 100% instead for full-width containers.
{{< /details >}}
Challenge
Build a responsive "Article Page" without any media queries:
<h1>withclamp()for fluid size- Article text with
max-width: 65ch - A sidebar using
min()orclamp() - Cards in a grid using
calc()for gaps - Full-height hero section using
vh
FAQ
FAQ
What's Next?
Now learn positioning and flexbox:
What's Next
Congratulations on completing this Css Units Functions tutorial! Here's where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro