EduFlow
Modern CSS Mastery
0%

Section 2 · Layout That Holds Up

Intrinsic Sizing: min(), max(), clamp()

17 min3 min readCode playground

Lesson at a glance

Size elements from their content with min-content, max-content and fit-content, and replace breakpoint pairs with min(), max() and clamp().

  1. 1Let the content decide: intrinsic keywords
  2. 2min(), max() and clamp()
  3. 3Units that make math functions useful
  4. 4Your turn

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

Waypoint’s session abstracts had the classic pair of rules: width: 100% plus max-width: 40ch, and then a media query to add side padding on phones, and another for big screens. Three rules and two breakpoints to say one thing: “be as wide as is comfortable to read, but never wider than the space you have”.

CSS can say that directly now. This lesson covers two tools: the intrinsic size keywords, which let content decide how big an element is, and the math functions min(), max() and clamp(), which let you describe a range instead of picking breakpoints.

Let the content decide: intrinsic keywords

Most sizes you write are extrinsic: 300px, 50%, 1fr. The browser can also size an element from its content, and three keywords expose that:

  • min-content: the narrowest the element can be without overflowing, which is usually the width of its longest word.
  • max-content: the width the content would take if it never wrapped.
  • fit-content: max-content, but never wider than the available space. When space runs out, it wraps like a normal block.

fit-content is the one you’ll use most. A block-level badge or button normally stretches to fill its container; width: fit-content makes it hug its label like an inline element while staying a block, so margins and stacking still behave. Add margin-inline: auto and it centers.

In grid tracks, the keywords give you content-driven columns. Waypoint’s agenda uses grid-template-columns: max-content 1fr: the time column is exactly as wide as the longest time (“10:15–11:00”), and the session title takes the rest.

min(), max() and clamp()

The math functions take a list of values, in any mix of units, and resolve to one length at layout time:

sizing.css
.abstract {
  width: min(100%, 40ch);            /* ceiling: never wider than 40ch */
}

.page {
  padding-inline: max(1rem, 4vw);    /* floor: never less than 1rem */
}

.session-card {
  padding: clamp(12px, 4%, 32px);    /* between 12px and 32px, 4% in the middle */
}

.content {
  width: min(100% - 2rem, 60rem);    /* arithmetic works without calc() */
  margin-inline: auto;
}

min() returns the smallest value, which means it sets an upper limit. min(100%, 40ch) is 40ch on a wide card and 100% on a narrow one; it replaces the width plus max-width pair with one declaration. max() returns the largest value, so it sets a lower limit: the page gutter is 4vw on wide screens but never shrinks below 1rem on a phone.

clamp(MIN, PREFERRED, MAX) combines both: it returns the preferred value, but never less than MIN and never more than MAX. It’s exactly max(MIN, min(PREFERRED, MAX)).

A graph of padding against container width. The line is flat at 12 pixels for narrow containers, rises along 4 percent of the width in the middle, and is flat at 32 pixels for wide containers. container width padding 12px (MIN) 4% (PREFERRED) 32px (MAX) 300px 800px
clamp() follows the preferred value between two limits

With clamp(12px, 4%, 32px), a card in a 300px column gets 12px of padding, one in a 500px column gets 20px, and anything wider than 800px tops out at 32px. Padding percentages are relative to the containing block’s inline size, so the card’s spacing follows its container, not the viewport.

Units that make math functions useful

The preferred value in clamp() should be something that scales: a percentage, vw, or the container units you’ll meet in Container Queries. The limits should be stable units like px or rem. Using rem for the limits has a bonus: if a user raises their default font size, the limits scale with it.

This is also the trick behind the guard from the grid lesson: minmax(min(180px, 100%), 1fr). Inside a container narrower than 180px, min() picks 100%, so the track never forces overflow.

Your turn

The exercise has a session card inside a wrapper whose width the checks change. Cap the abstract at 40ch without overflowing narrow cards, make the badge hug its text, and give the card padding that scales between 12px and 32px. Next, you’ll make whole components change layout based on their container’s width, with container queries.

Key takeaways

  • min-content is the narrowest an element can be without overflowing, max-content is its width with no wrapping, and fit-content is max-content capped at the available space.
  • min() picks the smallest value, so it acts as a ceiling: width: min(100%, 40ch) never exceeds 40ch and never overflows its container.
  • max() acts as a floor, and clamp(MIN, PREFERRED, MAX) keeps a fluid value between two limits.
  • Math functions accept mixed units and arithmetic, so min(100% - 2rem, 60rem) works without a nested calc().

Further reading

Check your understanding

4 questions

Question 1 of 4

A session abstract has width: min(100%, 40ch). Its card is 900px wide. How wide is the abstract?

Question 2 of 4

What does padding: clamp(12px, 4%, 32px) give a card in a 500px-wide container?

Question 3 of 4

A “Sold out” badge is display: block inside a card, and it stretches across the whole card. Which declaration makes it hug its text but still wrap if the text is longer than the card?

Question 4 of 4

Why does max(1rem, 4vw) make a good page gutter?

Practice

Code playground

Size the card from its content

The checks resize .wrap between 220px and 1000px. Without media queries:

  1. Make .abstract at most 40ch wide, but never wider than the card’s content box.
  2. Make the block-level .badge hug its text instead of stretching (keep display: block).
  3. Give .session-card padding of 4% of the wrapper’s width, never less than 12px and never more than 32px.
<div class="wrap">
  <article class="session-card">
    <span class="badge">Sold out</span>
    <h3>Intrinsic Sizing in Practice</h3>
    <p class="abstract">Let content decide how big things are: min-content, max-content, fit-content and the math functions that replace half your media queries.</p>
  </article>
</div>Loading the editor…

Ctrl/⌘ + Enter to run · Runs in a sandbox in your browser. Nothing leaves your device.

Preview

Console

(no output)

Checks

  • In a wide card, the abstract is 40ch wide
  • In a narrow card, the abstract doesn’t overflow
  • The badge hugs its text and stays a block
  • Padding never drops below 12px
  • Padding is 4% of the width in between
  • Padding never exceeds 32px