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-columnsandgrid-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;
}
CardOne
CardTwo
CardThree
CardFour
CardFive
CardSix
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-NameThis 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.
Practical Layout: Header + Flexible Middle + Footer
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.
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 (likefont-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 shrinkmin-width: 0on 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(notminmax())
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.
