Episode 1 — Fundamentals / 1.6 — CSS Core Fundamentals

1.6.f — Modern CSS Functions: clamp(), min(), max()

In one sentence: clamp(), min(), and max() let you define fluid, self-adjusting values in CSS without media queries — replacing breakpoint-based sizing with continuous responsive behavior.

Navigation: ← 1.6.e — Units · 1.6.g — CSS Variables →


1. Why CSS needs math

Traditional responsive design relies on breakpoints — "at 768px, switch from X to Y." This creates discrete jumps. CSS functions enable fluid transitions: font sizes that smoothly scale with the viewport, containers that grow but never exceed a maximum.


2. clamp(min, preferred, max)

Returns the preferred value, constrained between a minimum and maximum:

/* Font size: at least 1rem, prefers 2.5vw, at most 2rem */
h1 {
  font-size: clamp(1rem, 2.5vw, 2rem);
}

/* Container: at least 320px, prefers 90%, at most 1200px */
.container {
  width: clamp(320px, 90%, 1200px);
}

How it works

If preferred < min  →  returns min
If preferred > max  →  returns max
Otherwise           →  returns preferred

Mental model: clamp() = max(min, min(preferred, max)).

Fluid typography pattern

body {
  font-size: clamp(1rem, 0.875rem + 0.5vw, 1.25rem);
}

This creates text that starts at 1rem (16px), grows smoothly with the viewport, and caps at 1.25rem (20px) — no media queries needed.


3. min(a, b, …)

Returns the smallest value from the list:

.card {
  width: min(100%, 400px);
  /* Never wider than 400px, but shrinks on small screens */
}

.section {
  padding: min(5vw, 3rem);
  /* Whichever is smaller — prevents excessive padding on large screens */
}

Use when: you want a value that caps at a maximum — "be this, but never more than that."


4. max(a, b, …)

Returns the largest value from the list:

.sidebar {
  width: max(250px, 25%);
  /* At least 250px, but grows to 25% on large screens */
}

.text {
  font-size: max(1rem, 1.5vw);
  /* At least 1rem — never smaller than the user's base */
}

Use when: you want a value that has a floor — "be this, but never less than that."


5. Mixing units freely

One of the most powerful features: CSS math functions accept mixed units:

.hero {
  height: clamp(300px, 50vh, 700px);
  padding: min(2rem, 5vw);
  font-size: max(1rem, 2vw + 0.5rem);
}

The browser resolves the comparison at compute time. You can mix px, rem, em, vw, vh, %, and calc() expressions.


6. calc() — the foundation

calc() performs arithmetic with mixed units:

.sidebar {
  width: calc(100% - 250px);
}

.content {
  padding: calc(1rem + 0.5vw);
}

clamp(), min(), and max() implicitly support calc() math inside their arguments — you can write clamp(1rem, 0.5rem + 1vw, 2rem) without wrapping in calc().


7. Real-world patterns

Responsive container with constraints

.container {
  width: min(90%, 1200px);
  margin-inline: auto;
}

Replaces the classic max-width: 1200px; width: 90%; pattern with a single declaration.

Fluid spacing

section {
  padding-block: clamp(2rem, 5vw, 5rem);
}

Generous padding on large screens; compact on mobile — no breakpoints.

Safe minimum font size

small {
  font-size: max(0.75rem, 12px);
}

Ensures text never drops below a readable 12px even if rem scales down.


8. Accessibility consideration

When using vw-based fluid typography, ensure the minimum value is in rem (not px) so it still respects user font-size preferences. clamp(1rem, …, 2rem) with rem bounds is accessible; clamp(16px, …, 32px) with px bounds ignores user settings.


9. Key takeaways

  1. clamp(min, preferred, max) = fluid value with bounds — the core of modern responsive design.
  2. min() caps at a maximum; max() enforces a floor.
  3. All three accept mixed units — combine rem, vw, px, % freely.
  4. These functions replace many media queries with smooth, continuous scaling.
  5. Use rem for bounds in fluid typography to respect accessibility preferences.

Explain-It Challenge

Explain without notes:

  1. What clamp(1rem, 3vw, 2rem) means in plain English.
  2. When you would use min() vs max() — give one example of each.
  3. Why fluid typography bounds should use rem instead of px for accessibility.

Navigation: ← 1.6.e — Units · 1.6.g — CSS Variables →