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().
- 1Let the content decide: intrinsic keywords
- 2min(), max() and clamp()
- 3Units that make math functions useful
- 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:
.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)).
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-contentis the narrowest an element can be without overflowing,max-contentis its width with no wrapping, andfit-contentis 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, andclamp(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 nestedcalc().