CSS Math Functions: calc(), min(), max() and clamp()

Do maths in CSS: mix units with calc(), pick the smaller or larger value with min() and max(), and build fluid sizes with clamp().

Lesson 32 of 49Intermediate15 min read

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

CSS
.main { width: calc(100% - 300px); }
.box { padding: calc(1rem + 2px); }
.col { width: calc(100% / 3); }
  • calc() supports +, -, * and /.
  • You can mix units: %, px, rem, vw and 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), not calc(2rem * 1rem).
  • calc() works beautifully with variables: calc(var(--gap) * 2).

min() and max()

FunctionReturnsExampleMeaning
min(a, b)The smaller valuewidth: min(100%, 600px)Up to 600px, but shrink on small screens
max(a, b)The larger valuefont-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

CSS
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. Mixing rem and vw, as in 1rem + 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 % and px.
  • Always put spaces around + and - inside calc().
  • 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.

Example 1

calc() for a fixed sidebar

.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;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 4The sidebar has a fixed width.
  2. Line 11The main area takes the full width minus the sidebar and the gap.
Example 2

min() and max() in one line

Resize the result panel and watch both boxes.

.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;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2Full width on narrow screens, capped at 360px on wide ones.
  2. Line 11The text grows on large screens but never drops below 16px.
Example 3

Fluid heading and spacing with clamp()

.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;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2Padding grows with the screen, between 16 and 64 pixels.
  2. Line 8The heading scales smoothly from about 26px on phones to 56px on wide screens.

Common CSS Math Functions Mistakes

No spaces around minus

Don't
.box { width: calc(100%-20px); }
Do
.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()

Don't
.card { width: max(100%, 600px); } /* always at least 600px, overflows phones */
Do
.card { width: min(100%, 600px); }

To cap a size, use min().

clamp() with only vw in the middle

Don't
p { font-size: clamp(14px, 2vw, 20px); }
Do
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.

Fill in the blankseasy

Make the box the full width minus 40px.

.box {
  width: (100% - 40px);
}
Multiple choiceeasy

What does clamp(1rem, 4vw, 2rem) return on a very wide screen?

Multiple choicemedium

Which line caps a width at 500px but lets it shrink on phones?

Multiple choicemedium

Why is calc(100%-10px) ignored?

Fix the bugmedium

The panel should be its container's width minus 50px, and the title should be clamped between 20px and 32px. Fix the CSS.

.wrap { width: 400px; }
.panel { width: calc(100%-50px); background: #e0f2fe; }
.title { font-size: clamp(32px, 3vw); }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • 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.

  1. What can calc() do that a plain value can't?

    • Use colours
    • Run JavaScript
    • Change HTML
    • Mix different units, such as % and px
  2. Which function works as a minimum limit?

    • min()
    • max()
    • calc()
    • round()
  3. What order do clamp()'s arguments go in?

    • max, preferred, min
    • preferred, min, max
    • min, preferred, max
    • Any order
  4. Can calc() use CSS variables?

    • Yes, for example calc(var(--gap) * 2)
    • No
    • Only colour variables
    • Only inside :root
  5. 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

  1. Make .container width: min(100% - 32px, 600px) and center it with margin-inline: auto
  2. Give .title a font-size of clamp(1.5rem, 1rem + 2vw, 2.5rem)
  3. Make .side 120px wide and .content calc(100% - 120px) wide
.row { display: flex; }
.side, .content { box-sizing: border-box; padding: 8px; background: #f1f5f9; }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Container is capped and centered
  • Title uses clamp
  • Side is 120px
  • Content fills the rest