What Is minmax() in CSS

minmax() is a sizing function used in CSS Grid. You give it two sizes: a minimum and a maximum. The browser picks a value in that range based on available space and content.

  • Where you’ll use it most: grid-template-columns and grid-template-rows.
  • What it sizes: grid tracks (columns/rows), not arbitrary element properties like height.
  • Why it’s useful: it helps you say “never smaller than X, never larger than Y.”

Are you instead looking for min(), max() or clamp()? Learn about them in the CSS Min() Max() Clamp() Interactive Tutorial.

Basic Syntax

The syntax is: minmax(min, max). Both values can be lengths (px, rem), percentages, content sizes (min-content, max-content), or flexible units like fr (usually used as the max).

.grid {
  grid-template-columns: minmax(160px, 1fr) minmax(160px, 1fr) minmax(160px, 1fr);
}
    


.grid {
grid-template-columns: minmax(220px, 1fr) minmax(220px, 1fr) minmax(220px, 1fr);
} 


.grid {
  grid-template-columns: minmax(320px, 1fr) minmax(70px, 1fr) minmax(70px, 1fr);
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.card {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
min-height: 74px;
display: grid;
align-content: center;
}

.kicker {
font-size: 13px;
opacity: 0.8;
margin: 0 0 4px;
}

.title {
margin: 0;
font-weight: 700;
} 


Track

minmax() column

Track

minmax() column

Track

minmax() column

In each snippet, the columns are allowed to grow (up to 1fr), but they refuse to shrink below the minimum. That “refuse to shrink” part is often the difference between a layout that feels stable and one that collapses into chaos.

CSS Grid minmax() for Responsive Columns

The most common “wow, that’s handy” pattern is combining repeat(), auto-fit/auto-fill, and minmax() to create responsive grids that wrap automatically.

Auto-Wrapping Columns with auto-fit

This pattern means: “Create as many columns as fit, each at least this wide, otherwise share remaining space.”

.grid {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
    


.grid {
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
} 


.grid {
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.tile {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
display: grid;
gap: 6px;
}

.badge {
display: inline-block;
width: fit-content;
border: 2px solid #111;
border-radius: 999px;
padding: 2px 10px;
font-size: 12px;
background: #fff;
}

.tile p {
margin: 0;
} 


Card

One

Card

Two

Card

Three

Card

Four

Card

Five

Card

Six

Change the minimum (the first value). If it’s larger, fewer columns fit before wrapping. If it’s smaller, more columns squeeze in.

Quick Note: auto-fit vs auto-fill

auto-fit collapses “empty tracks” so your items stretch nicely. auto-fill keeps those tracks reserved, which can leave empty columns. When in doubt for card grids, auto-fill keeps the layout more predictable.

.grid {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
    


.grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.tile {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
}

.tile p {
margin: 0;
} 


One

Using minmax() with fr Without “Oops, Overflow”

A classic Grid gotcha: items can overflow their tracks because grid items have a default minimum size. Sometimes you’ll set minmax(0, 1fr) not because you want a literal 0px minimum, but because you want tracks to be allowed to shrink below the content’s “ideal” width.

The minmax(0, 1fr) Pattern

If you have long text (URLs, unbroken strings), minmax(0, 1fr) often prevents unexpected overflow.

.grid {
  grid-template-columns: 1fr 1fr;
}
    


.grid {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.panel {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
}

.label {
font-size: 12px;
opacity: 0.8;
margin: 0 0 6px;
}

.codey {
font-family: ui-monospace, SFMono-Regular, monospace;
font-size: 14px;
line-height: 1.3;
}

.codey p {
margin: 0;
} 


Normal 1fr

https://thisisareallylongurlwithnobreaks.example

Normal 1fr

Some normal text is fine, but the URL is the troublemaker.

If you still see overflow, pair it with min-width: 0 on the grid item. The important lesson: minmax() sizes tracks, but content can still fight you.

Content-Aware Tracks: min-content, max-content, and auto

minmax() becomes extra fun when one side is a content keyword. This lets your grid react to what’s inside it.

Using minmax(min-content, max-content)

Think of: min-content as “smallest it can be without overflow (breaking where allowed)” and max-content as “as wide as the content wants to be.”

.grid {
  grid-template-columns: minmax(min-content, max-content) 1fr;
}
    


.grid {
grid-template-columns: minmax(30ch, max-content) 1fr;
} 


.grid {
grid-template-columns: minmax(120px, max-content) 1fr;
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
align-items: start;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.box {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
}

.tag {
display: inline-block;
border: 2px solid #111;
border-radius: 999px;
padding: 2px 10px;
font-size: 12px;
}

.small {
font-size: 13px;
opacity: 0.85;
margin: 8px 0 0;
line-height: 1.35;
} 


Super-Extra-Long-Tag-Name

This left column tries to fit tag content (within limits).

The right column is 1fr, so it absorbs leftover space. Resize the preview and watch the left column behave.

Using minmax() with fit-content()

fit-content() is like saying: “Size to the content… but don’t exceed this cap.” When paired with minmax(), you can create tracks that have a minimum, then grow naturally, but stop growing after a certain point.

A Practical “Label + Content” Layout

A common UI pattern: a label column that shouldn’t get too tiny, but also shouldn’t hog the whole row.

.grid {
  grid-template-columns: minmax(140px, fit-content(260px)) 1fr;
}
    


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.cell {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
}

.label {
font-weight: 700;
margin: 0 0 6px;
}

.help {
margin: 0;
font-size: 13px;
opacity: 0.85;
line-height: 1.35;
} 


Billing address

This label column grows, but is capped by fit-content().

The content column stays flexible. This is great for forms, settings pages, or “term + definition” UIs.

CSS “Minmax Height”: What You Can (and Can’t) Do

Here’s the important beginner truth: minmax() does not work as height: minmax(...). minmax() sizes grid tracks, so it applies to grid-template-rows (and columns), not an element’s height.

Use minmax() for Row Height in Grid

If you want a row that is at least a certain height, but can grow with content, grid rows are a perfect place.

.grid {
  grid-template-rows: minmax(120px, auto) auto;
}
    


.grid {
grid-template-rows: minmax(180px, auto) auto;
} 


.grid {
grid-template-rows: minmax(70px, auto) auto;
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.hero,
.body {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
padding: 14px;
}

.hero p,
.body p {
margin: 0;
line-height: 1.4;
}

.hero .big {
font-weight: 800;
font-size: 18px;
margin: 0 0 8px;
}

.hero .small {
font-size: 13px;
opacity: 0.85;
} 


Row 1 uses minmax()

It will never be shorter than the minimum, but it can grow if the content needs more space. Add more text here in your head. The row will expand.

Row 2 is just auto, so it’s content-sized.

If You Mean “Min and Max Height,” Use min-height and max-height

For normal elements (not grid tracks), you typically want: min-height and max-height. That gives you a “range” for height, similar in spirit to minmax(), but using the right tools.

.panel {
  min-height: 120px;
  max-height: 220px;
  overflow: auto;
}
    
.panel {
min-height: 120px;
max-height: 160px;
overflow: auto;
} 
*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.panel {
border: 3px solid #111;
background: #fff;
border-radius: 14px;
padding: 14px;
}

.panel p {
margin: 0 0 10px;
line-height: 1.4;
}

.panel p:last-child {
margin-bottom: 0;
}

.note {
margin: 12px 0 0;
font-size: 13px;
opacity: 0.85;
} 


Scrollable panel

This box has a minimum and maximum height. When content exceeds the maximum, it scrolls. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer a nibh vel mauris. Curabitur commodo, nulla non feugiat dapibus, neque lorem volutpat turpis, in viverra.

This is not minmax(), but it solves the “minmax height” idea for normal elements.

This is one of the cleanest “real life” uses of grid-template-rows: auto minmax(0, 1fr) auto;. The middle section stretches to fill remaining space but is allowed to shrink properly.

.page {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
}
    
*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.page {
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
overflow: hidden;
}

.header,
.main,
.footer {
padding: 14px;
background: #fff;
}

.header,
.footer {
border-bottom: 2px solid #111;
}

.footer {
border-top: 2px solid #111;
border-bottom: 0;
}

.header p,
.footer p {
margin: 0;
font-weight: 700;
}

.main p {
margin: 0 0 10px;
line-height: 1.4;
}

.main p:last-child {
margin-bottom: 0;
}

.muted {
font-size: 13px;
opacity: 0.85;
} 


Header

Main (this area flexes)

With minmax(0, 1fr), the middle track can shrink properly. Add more content and it grows; reduce space and it compresses without breaking the grid.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at nibh non velit. Donec at nisi vitae arcu facilisis ultricies. Sed consequat, urna quis gravida.

More content. More content. More content. More content. More content. More content. More content. More content. More content. More content.

Footer

Minmax vs Clamp: Same Vibe, Different Job

minmax() and clamp() both sound like “a value constrained between a minimum and maximum.” But they live in different worlds.

  • minmax(): sizes grid tracks (columns/rows). Think layout structure.
  • clamp(): computes a single property value (like font-size, padding, width). Think component sizing that adapts to viewport.

Side-by-Side Demo: Grid Track vs Element Size

In this playground: the grid uses minmax() to decide column width, while the card uses clamp() to decide padding.

.grid {
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.card {
padding: clamp(12px, 3vw, 26px);
} 


.grid {
grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}

.card {
padding: clamp(12px, 3vw, 26px);
} 


.grid {
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.card {
padding: clamp(8px, 2vw, 18px);
} 


*,
::before,
::after {
box-sizing: border-box;
}

.wrap {
padding: 18px;
max-width: 980px;
font-family: ui-sans-serif, system-ui, sans-serif;
}

.grid {
display: grid;
gap: 12px;
padding: 12px;
border: 3px solid #111;
background: #f6f6f6;
border-radius: 14px;
}

.card {
border: 2px solid #111;
background: #fff;
border-radius: 12px;
}

.card p {
margin: 0;
line-height: 1.4;
}

.small {
font-size: 13px;
opacity: 0.85;
margin-top: 8px;
} 


Grid: minmax()

Controls column sizing and wrapping behavior.

Card: clamp()

Controls padding (a normal property value).

Both: responsive

But they solve different problems.

Learn more about clamp() in the CSS Clamp Interactive Tutorial.

Common Mistakes (and Easy Fixes)

Mistake: Trying height: minmax(...)

Not valid. Use min-height + max-height, or use minmax() on grid rows with grid-template-rows.

Mistake: “My grid item overflows even with minmax()”

Long content can force overflow. Try one (or both):

  • minmax(0, 1fr) for tracks that must be allowed to shrink
  • min-width: 0 on the grid items that contain the overflowing content

Mistake: Minimum is too large

If you set minmax(360px, 1fr), your grid will wrap very early on smaller screens. That might be fine, but if your layout suddenly becomes one-column “too soon,” reduce the minimum.

Minmax() Cheat Sheet

  • Responsive card grid: repeat(auto-fill, minmax(180px, 1fr))
  • Prevent overflow in flexible tracks: minmax(0, 1fr)
  • Label + content layout: minmax(140px, fit-content(260px)) 1fr
  • Min row height but allow growth: grid-template-rows: minmax(120px, auto)
  • Min/max height for elements: min-height + max-height (not minmax())

CSS minmax() Conclusion

minmax() is a powerful tool for creating flexible, responsive grid layouts. It lets you set minimum and maximum sizes for grid tracks, giving you control over how your grid adapts to content and screen size.