Sometimes a size isn't a single number. A sidebar might need to be "the full width minus 300 pixels", or a heading "5% of the screen, but never smaller than 28 pixels or bigger than 56". Before CSS had maths, these needed JavaScript or a pile of media queries. Now four functions handle them: calc(), min(), max() and clamp().
calc() does arithmetic and, crucially, can mix units such as percentages and pixels. min() and max() choose between values, and clamp() keeps a value between a minimum and a maximum while letting it grow in between. Together they power fluid design, where sizes scale smoothly with the screen instead of jumping at breakpoints.
In this lesson you'll learn each function, the syntax rules that trip people up (like the spaces around + and -), and practical recipes for responsive widths, fluid typography and spacing.
calc(): arithmetic with mixed units
.main { width: calc(100% - 300px); }
.box { padding: calc(1rem + 2px); }
.col { width: calc(100% / 3); }calc()supports+,-,*and/.- You can mix units:
%,px,rem,vwand more. The browser works out the result when it lays out the page. - Spaces are required around
+and-.calc(100%-20px)is invalid;calc(100% - 20px)works. - With
*and/, at least one side must be a plain number:calc(2 * 1rem), notcalc(2rem * 1rem). calc()works beautifully with variables:calc(var(--gap) * 2).
min() and max()
| Function | Returns | Example | Meaning |
|---|---|---|---|
min(a, b) | The smaller value | width: min(100%, 600px) | Up to 600px, but shrink on small screens |
max(a, b) | The larger value | font-size: max(16px, 1vw) | At least 16px, bigger on wide screens |
The naming feels backwards at first. min() sets a maximum (it picks the smaller option, so the value can never go above the cap), and max() sets a minimum. width: min(100%, 600px) does the same job as width: 100%; max-width: 600px in a single line. Both functions accept more than two values.
clamp(): a value with limits
h1 { font-size: clamp(1.75rem, 1rem + 3vw, 3.5rem); }clamp(MIN, PREFERRED, MAX) uses the preferred value, but never goes below the minimum or above the maximum.
- MIN: the smallest allowed value, used on phones.
- PREFERRED: usually includes a viewport unit (
vw) so it grows with the screen. Mixingremandvw, as in1rem + 3vw, keeps text zoomable. - MAX: the largest allowed value, used on big screens.
This is the core of fluid typography, covered more in responsive typography.
Where you can use math functions
Anywhere a length, number, angle or time is allowed: width, margin, padding, gap, font-size, border-radius, grid-template-columns, transform: rotate(calc(...)), transition-duration and more. Newer CSS also has round(), mod(), rem(), abs() and trigonometry functions such as sin(), which are supported in current browsers for more advanced effects.
CSS Math Functions Syntax
Math functions
.sidebar-layout { width: calc(100% - 280px); }
.card { width: min(90%, 480px); }
.text { font-size: max(1rem, 1.2vw); }
h1 { font-size: clamp(2rem, 1.2rem + 4vw, 4rem); }
.section { padding-block: clamp(24px, 6vw, 80px); }
.grid { gap: calc(var(--space) * 2); }CSS Math Functions Summary
calc()does arithmetic and can mix units such as%andpx.- Always put spaces around
+and-insidecalc(). min()picks the smaller value, so it works as a maximum;max()works as a minimum.clamp(min, preferred, max)keeps a fluid value within limits.- Math functions reduce the need for media queries.
CSS Math Functions Examples
Each example runs in the page. Edit the code and press Run to see what changes.
calc() for a fixed sidebar
<div class="layout">
<aside>Sidebar 160px</aside>
<main>Main area: the rest</main>
</div>.layout { display: flex; gap: 12px; font-family: sans-serif; }
aside {
width: 160px;
background: #fde68a;
padding: 12px;
box-sizing: border-box;
}
main {
width: calc(100% - 160px - 12px);
background: #bfdbfe;
padding: 12px;
box-sizing: border-box;
}Line-by-line explanation
- Line 4The sidebar has a fixed width.
- Line 11The main area takes the full width minus the sidebar and the gap.
min() and max() in one line
Resize the result panel and watch both boxes.
<div class="card">min(100%, 360px): never wider than 360px</div>
<p class="text">max(16px, 2.5vw): never smaller than 16px</p>.card {
width: min(100%, 360px);
background: #dcfce7;
padding: 14px;
border-radius: 10px;
box-sizing: border-box;
font-family: sans-serif;
}
.text {
font-size: max(16px, 2.5vw);
font-family: sans-serif;
}Line-by-line explanation
- Line 2Full width on narrow screens, capped at 360px on wide ones.
- Line 11The text grows on large screens but never drops below 16px.
Fluid heading and spacing with clamp()
<section class="hero">
<h1>Fresh bread, every morning</h1>
<p>Baked in small batches from 6am.</p>
</section>.hero {
padding: clamp(16px, 5vw, 64px);
background: #fff7ed;
font-family: sans-serif;
}
h1 {
font-size: clamp(1.6rem, 1rem + 4vw, 3.5rem);
line-height: 1.1;
margin: 0 0 8px;
}Line-by-line explanation
- Line 2Padding grows with the screen, between 16 and 64 pixels.
- Line 8The heading scales smoothly from about 26px on phones to 56px on wide screens.
Common CSS Math Functions Mistakes
No spaces around minus
.box { width: calc(100%-20px); }.box { width: calc(100% - 20px); }Without spaces, -20px is read as a negative number next to 100%, which is invalid, so the whole declaration is ignored.
Mixing up min() and max()
.card { width: max(100%, 600px); } /* always at least 600px, overflows phones */.card { width: min(100%, 600px); }To cap a size, use min().
clamp() with only vw in the middle
p { font-size: clamp(14px, 2vw, 20px); }p { font-size: clamp(1rem, 0.9rem + 0.4vw, 1.25rem); }A pure vw value ignores the user's zoom and font settings. Add a rem part so text stays resizable.
CSS Math Functions in Real Projects
Math functions in practice
Modern design systems define a fluid type scale with clamp(), so headings look right on any screen without breakpoints. Utopia.fyi, a popular fluid type calculator, generates clamp() values for you. Layouts use calc(100vh - var(--header-height)) to fill the screen below a fixed header, and min() containers have replaced many max-width patterns in modern codebases.
CSS Math Functions Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Make the box the full width minus 40px.
.box {
width: (100% - 40px);
}
calc() mixes percentages and pixels.What does clamp(1rem, 4vw, 2rem) return on a very wide screen?
Which line caps a width at 500px but lets it shrink on phones?
Why is calc(100%-10px) ignored?
The panel should be its container's width minus 50px, and the title should be clamped between 20px and 32px. Fix the CSS.
<div class="wrap"><div class="panel"><h2 class="title">Title</h2></div></div>.wrap { width: 400px; }
.panel { width: calc(100%-50px); background: #e0f2fe; }
.title { font-size: clamp(32px, 3vw); }- Panel is 350px wide
- Title size is between 20px and 32px
- Uses clamp with three values
CSS Math Functions Quiz
5 questions to check what you learned.
What can calc() do that a plain value can't?
- Use colours
- Run JavaScript
- Change HTML
- Mix different units, such as % and px
Which function works as a minimum limit?
- min()
- max()
- calc()
- round()
What order do clamp()'s arguments go in?
- max, preferred, min
- preferred, min, max
- min, preferred, max
- Any order
Can calc() use CSS variables?
- Yes, for example calc(var(--gap) * 2)
- No
- Only colour variables
- Only inside :root
Why add a rem part to a fluid font size like 1rem + 2vw?
- So the text still responds to the user's zoom and font size settings
- It's faster
- vw doesn't work alone
- To support old browsers
CSS Math Functions Challenge
A fluid card layout
- Make
.containerwidth: min(100% - 32px, 600px)and center it withmargin-inline: auto - Give
.titleafont-sizeofclamp(1.5rem, 1rem + 2vw, 2.5rem) - Make
.side120pxwide and.contentcalc(100% - 120px)wide
<div class="container">
<h2 class="title">Weekly menu</h2>
<div class="row"><div class="side">Day</div><div class="content">Dish</div></div>
</div>.row { display: flex; }
.side, .content { box-sizing: border-box; padding: 8px; background: #f1f5f9; }
- Container is capped and centered
- Title uses clamp
- Side is 120px
- Content fills the rest