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

Let CSS do the math for you. Learn how calc() mixes units, how min() and max() pick the right value, and how clamp() builds fluid sizes that scale smoothly between a floor and a ceiling.

Published August 8, 202610 min readBy ACY Partner Indonesia
CSS math functions — calc, min, max, and clamp
300 × 250Ad Space AvailablePlace your ad here

Most of the time you hand CSS a fixed value — width: 300px, font-size: 18px — and that’s that. But real layouts are rarely so tidy. You’ll hit moments where the value you want isn’t a single number you can type out, but a calculation: “the full width, minus this sidebar,” or “20% of the viewport, but never smaller than 16 pixels.” For years that meant reaching for JavaScript or giving up and eyeballing it.

CSS has a better answer: math functions. With calc(), min(), max(), and clamp(), the browser does the arithmetic for you, live, as the screen resizes. They’re the secret behind layouts that flex gracefully without a single line of JavaScript, and once you get them they quietly become part of your everyday toolkit. Let’s walk through all four.

calc(): doing arithmetic right in CSS

The calc() function lets you write a math expression as a value. The browser evaluates it and uses the result:

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

That reads as “100% of the available width, minus 40 pixels.” This is the headline feature of calc(): it can mix units freely. Percent and pixels, rem and vw, em and px — things you could never combine by hand, because the browser only knows what 100% resolves to at render time. You can’t precompute 100% - 40px yourself; calc() can, on the fly.

You get the four basic operators:

Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
.sidebar {
  width: calc(100% / 3);          /* exactly one third */
}

.banner {
  height: calc(100vh - 80px);     /* full screen height minus a fixed header */
}

.spacing {
  margin: calc(1rem + 5px);       /* a rem plus a few pixels */
}

That 100vh - 80px pattern is a classic: a hero section that fills the whole screen except for a fixed 80px navbar sitting above it. No JavaScript measuring required — the browser keeps it correct as the window resizes.

The spaces around + and - are mandatory

Inside calc(), you must put a space on both sides of the + and - operators. calc(100% - 40px) works; calc(100%-40px) is silently ignored and your value just doesn’t apply. The reason is that -40px could be read as a single negative number, so the spaces tell CSS you mean subtraction. For * and / the spaces are optional, but it’s a good habit to space everything consistently.

You can nest expressions with parentheses, and you can even nest calc() inside calc() (though plain parentheses usually do the job):

.card {
  width: calc((100% - 2 * 16px) / 3);   /* 3 columns with two 16px gaps */
}

Here you’re carving a row into three equal columns while accounting for the gaps between them — the kind of thing that’s genuinely painful to hardcode but trivial with a quick expression.

min(): pick the smallest value

min() takes a list of values and uses whichever is smallest at that moment. It sounds backwards at first, but it’s incredibly handy for setting a cap:

.container {
  width: min(90%, 1200px);
}

Read that as: “use 90% of the available width, unless that would exceed 1200px — then cap it at 1200px.” On a small phone, 90% is the smaller number, so the container is fluid and breathes with the screen. On a huge monitor, 1200px becomes the smaller number, so the content stops sprawling and stays a comfortable, readable width. One line replaces a width plus a max-width plus a media query.

.title {
  font-size: min(8vw, 64px);   /* scales with the screen, but never past 64px */
}

The mental shortcut: min() sets a maximum. Because it always grabs the smaller value, the largest item in the list acts as a ceiling that the result can never climb above.

max(): pick the largest value

max() is the mirror image — it uses whichever value is largest, which makes it perfect for setting a floor:

.text {
  font-size: max(16px, 2vw);
}

This says: “scale the font with the viewport at 2vw, but never let it drop below 16px.” On a tiny screen, 2vw might compute to something like 8px — too small to read comfortably — so max() falls back to the larger 16px and keeps your text legible. On a wide screen, 2vw wins and the text grows.

.gutter {
  padding: max(1rem, 3vw);   /* comfortable padding that never gets cramped */
}

The mental shortcut here is the flip of the last one: max() sets a minimum. It always grabs the larger value, so the smallest item in the list becomes a floor the result can never sink below.

min sets a max, max sets a min

The naming trips up almost everyone at first. Remember it by what the function guarantees: min() guarantees the result won’t go above its biggest argument (a maximum), and max() guarantees it won’t go below its smallest argument (a minimum). Say it out loud a couple of times — “min caps, max floors” — and it sticks.

clamp(): a floor, a target, and a ceiling

Now for the star of the show. clamp() combines both ideas into one elegant function. It takes three values — a minimum, a preferred value, and a maximum:

.heading {
  font-size: clamp(1.5rem, 4vw, 3rem);
}

The order is always minimum, preferred, maximum, and here’s how to read it:

  • The browser wants to use the middle value, 4vw — a size that scales with the screen.
  • But it will never let the result fall below 1.5rem (the floor).
  • And it will never let it climb above 3rem (the ceiling).

So on a small phone, the heading sits at its 1.5rem floor. As the screen grows, the 4vw preferred value takes over and the text scales up smoothly. On a giant monitor, it stops at 3rem and refuses to get any bigger. You get fluid typography that flows naturally between two sensible limits — and it’s all in a single line.

This is the modern way to do responsive font sizes. Before clamp(), you’d write a base size and then layer on media queries to bump it up at each breakpoint, creating jumpy, stair-stepped jumps in size. clamp() makes the change continuous and smooth instead.

/* Fluid spacing and widths work too — not just fonts */
.section {
  padding-block: clamp(2rem, 6vw, 5rem);
}

.wrapper {
  width: clamp(320px, 90%, 1200px);
}

clamp(a, b, c) is just shorthand for max(a, min(b, c))

If you ever want to prove to yourself how clamp() works, it’s literally equivalent to max(MIN, min(PREFERRED, MAX)). The inner min() caps the preferred value at the maximum, and the outer max() lifts it up to the minimum if it fell too low. clamp() just wraps that pattern in one readable function — which is exactly why it’s so popular.

Combining functions

These functions compose. You can drop a calc() expression inside a min(), max(), or clamp(), which unlocks more expressive rules:

.hero-title {
  /* floor 2rem, scale fluidly, ceiling that leaves room on huge screens */
  font-size: clamp(2rem, 1.5rem + 3vw, 4rem);
}

That preferred value, 1.5rem + 3vw, is a small calculation in its own right — a fixed base plus a screen-relative part. (Notice you don’t even need to write calc() here; inside clamp(), min(), and max(), math expressions are allowed directly.) This particular shape — a rem base plus a vw slope — is the go-to recipe for fluid type that feels balanced, because the fixed part keeps small screens readable while the vw part adds growth.

A practical layout

Let’s put it together into a content wrapper you’d genuinely use on a real page — fluid, centered, and capped:

.content {
  width: min(92%, 1100px);        /* fluid, but caps at 1100px */
  margin-inline: auto;            /* centers it */
  padding: clamp(1rem, 4vw, 2.5rem);
}

.content h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
}
<main class="content">
  <h1>Welcome to ACY Partner Indonesia</h1>
  <p>This content stays readable on a phone and elegant on a desktop.</p>
</main>

Look at what you got for almost no code: the wrapper fills the screen on a phone but never sprawls wider than 1100px on a desktop, the padding grows with the viewport but stays within sane bounds, and the heading scales fluidly between a comfortable floor and ceiling. There’s not a single media query in sight, and not one line of JavaScript. That’s the quiet power of CSS math functions.

If you’re still nailing down which units to feed these functions — when to reach for vw, rem, %, or px — it’s worth revisiting CSS units first, since these functions are only as good as the units you mix into them. And once your sizes flex on their own, you’ll lean far less on the breakpoint-heavy approach from responsive design — many things that once needed a media query now just… resize themselves.

Browser support and gotchas

All four functions enjoy excellent support across every modern browser, so you can use them freely today. A few things worth keeping in mind:

  • Spacing in calc() — as covered above, + and - need spaces around them, every time.
  • Division by zerocalc(100% / 0) is invalid and the declaration is dropped. Watch out when a variable could be zero.
  • Unit mismatches — you can’t add a unitless number to a length: calc(10px + 5) is invalid. Every term that needs a unit must have one.
  • Readability — these can get dense. A short comment explaining why a clamp() has the limits it does will thank you later.

Don't bury fixed magic numbers inside calc()

It’s tempting to write things like calc(100vh - 73px) where 73px is your header’s exact height. The problem: the day someone changes the header to 80px, your calc() silently breaks and nothing tells you why. Where you can, store such values in a CSS custom property (a variable) and reference it — calc(100vh - var(--header-height)) — so there’s a single source of truth. It keeps these expressions maintainable as the design evolves.

Wrapping up

CSS math functions let the browser handle arithmetic for you, in real time, as the layout changes. They’re the cleanest path to fluid, responsive design without JavaScript:

  • calc() does arithmetic and, crucially, lets you mix units like % and px. Always space your + and -.
  • min() picks the smallest value — use it to set a maximum (a ceiling your value can’t exceed).
  • max() picks the largest value — use it to set a minimum (a floor your value can’t drop below).
  • clamp(min, preferred, max) combines both into fluid sizing that scales between a floor and a ceiling — perfect for responsive typography and spacing.
  • They compose: nest math expressions inside clamp(), min(), and max() for expressive, self-adjusting values.

Master these four and a whole class of layout problems simply dissolves. You stop writing pixel values and start describing relationships — “this big, but never bigger than that” — and let the browser sort out the rest. Next time you reach for a media query to resize something, pause and ask whether a clamp() could do it in one line instead.

Tags:cssfrontendcalcclampresponsiveintermediate
728 × 90Ad Space AvailablePlace your ad here

Related Articles

See All Articles

You Might Also Like

Frontend best practices overview cover
Frontend / Fundamentals

Frontend Best Practices: An Overview

A friendly map of what good frontend really means — semantic HTML, clean CSS, unobtrusive JavaScript, responsive layouts, performance, and progressive enhancement, with pointers to go deeper.

Sep 20, 20268 min read
A Frontend Developer Roadmap cover with the path HTML to CSS to JavaScript
Frontend / Fundamentals

A Frontend Developer Roadmap: What to Learn, and in What Order

A calm, step-by-step learning path for beginners: HTML, CSS, JavaScript, developer tools, responsive and accessible design, a framework, TypeScript, and deployment, with the reasoning behind each step.

Sep 20, 202611 min read
Title card reading Styling and Interactivity over a dark blue ACY Partner background
Frontend / Fundamentals

How Styling and Interactivity Work

A beginner-friendly look at how CSS turns plain HTML into a designed layout, and how JavaScript adds behavior — the structure, style, behavior mental model for building web pages.

Sep 20, 20269 min read
Three front-end layers combining on one web page
Frontend / Fundamentals

How HTML, CSS, and JavaScript Work Together

A hands-on walkthrough for beginners: build one small button, give it structure with HTML, looks with CSS, and behavior with JavaScript, and watch the three layers cooperate on a real page.

Sep 20, 20268 min read
The Frontend Developer Toolkit cover with editor, browser, and CLI motifs
Frontend / Fundamentals

The Frontend Developer Toolkit

A friendly tour of the everyday tools a frontend developer relies on — code editor, browser and DevTools, terminal, version control, package managers, and a dev server — and what each one is actually for.

Sep 20, 202610 min read
Cover illustration for What Frontend Developers Do
Frontend / Fundamentals

What Frontend Developers Do: A Beginner's Guide to the Role

A clear, beginner-friendly look at what frontend developers actually do every day: turning designs into working interfaces, building reusable UI, and caring about responsiveness, accessibility, and speed.

Sep 20, 202610 min read