🧮 minmax() in CSS Grid
The minmax(min, max) function sets a range for track size:
➡️ Minimum size (can't shrink below)
➡️ Maximum size (can grow up to)
✅ Syntax:
minmax(MIN, MAX)MIN: Minimum track size (e.g.,150px,0,auto)MAX: Maximum track size (e.g.,1fr,500px,auto)
🧪 Example:
grid-template-columns: minmax(200px, 1fr);👉 This column will never shrink below 200px
👉 It can grow to take available space using 1fr
🔎 Common Use:
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));🎯 When to Use minmax()?
Use Case | Why use |
|---|---|
Responsive grid items | Prevent shrinking too small |
Mix fixed min size + flexible max | Control layout in smaller screens |
🔁 repeat() in CSS Grid
📌 What is repeat()?
The repeat(count, value) function avoids repeating code for grid tracks.
✅ Syntax:
repeat(COUNT, VALUE)COUNT: Number of times to repeatVALUE: Size of each column/row (e.g.,1fr,100px)
🧪 Example 1 – Fixed Repetition:
grid-template-columns: repeat(3, 1fr);➡️ Creates 3 equal columns of 1fr each.
🧪 Example 2 – With minmax():
grid-template-columns: repeat(4, minmax(100px, 1fr));➡️ 4 columns that won’t go below 100px, but can expand.
🧪 Example 3 – With auto-fit or auto-fill:
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));➡️ Responsive layout: as many columns as fit the space.
🎯 When to Use repeat()?
Use Case | Benefit |
|---|---|
Multiple equal columns | Cleaner code |
Dynamic layouts with | Responsive grid without media queries |
🧑💻 Full Example:
The items will be At least 50px or At most 1fr (fraction of available space).
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Grid: auto-fit Emoji Grid</title>
<style>
.infographic-emojifit {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #db2777;
--accent-soft:#fce7f3;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-emojifit[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #f472b6;
--accent-soft:#3a1f30;
--line: #2c313d;
}
.ef-inner { padding: 0.5rem; }
.ef-layout { display: flex; flex-direction: column; gap: 1.5rem; }
.ef-code-wrap {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
overflow: hidden;
}
.ef-filebar {
display: flex;
background: #161616;
border-bottom: 1px solid #2a2a2a;
padding: 0.6rem 1rem;
}
.ef-filename {
color: #ffffff;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.78rem;
font-weight: 700;
}
.ef-code {
padding: 1rem 1.8rem 1rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.8rem;
line-height: 1.85;
overflow-x: auto;
}
.ef-line { display: block; white-space: pre; color: #e5e5e5; padding: 0.05rem 0.4rem; border-radius: 5px; }
.ef-line.ef-hl { background: #1c2333; box-shadow: inset 3px 0 0 #f472b6; color: #ffffff; }
.ef-sel { color: #f472b6; font-weight: 700; }
.ef-prop { color: #c586c0; }
.ef-val { color: #ce9178; }
.ef-browser {
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
background: var(--paper);
}
.ef-browser-bar {
background: var(--paper-alt);
padding: 0.5rem 0.7rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--line);
}
.ef-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.ef-tab {
background: var(--paper);
border: 1px solid var(--line);
border-bottom: none;
border-radius: 6px 6px 0 0;
font-size: 0.72rem;
color: var(--ink-soft);
padding: 0.25rem 0.6rem;
}
.ef-controlrow {
background: var(--paper-alt);
padding: 0.5rem 0.7rem 0.7rem;
display: flex;
align-items: center;
gap: 0.7rem;
}
.ef-control-label {
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
white-space: nowrap;
}
.ef-slider {
flex: 1;
accent-color: var(--accent);
cursor: pointer;
}
.ef-width-readout {
font-size: 0.72rem;
color: var(--ink);
font-weight: 700;
font-family: "SFMono-Regular", Consolas, monospace;
min-width: 46px;
text-align: right;
}
.ef-screen {
background: #ffffff;
padding: 1.2rem 1.4rem 1.4rem;
overflow-x: auto;
}
.ef-out-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(50px, 1fr));
gap: 1rem;
width: 380px;
max-width: 100%;
transition: width 0.15s ease;
box-sizing: border-box;
}
.ef-out-item {
background: #f2b5d4;
padding: 20px;
text-align: center;
border-radius: 6px;
font-size: 1.4rem;
box-sizing: border-box;
}
.ef-readout {
font-size: 0.82rem;
color: var(--ink-soft);
padding: 0 0.2rem;
}
.ef-readout strong { color: var(--ink); }
.ef-readout code {
font-family: "SFMono-Regular", Consolas, monospace;
background: var(--paper-alt);
padding: 0.05rem 0.3rem;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="infographic-emojifit" id="ef-root">
<div class="ef-inner">
<div class="ef-layout">
<div class="ef-code-wrap">
<div class="ef-filebar"><span class="ef-filename">style.css</span></div>
<div class="ef-code">
<span class="ef-line"><span class="ef-sel">.grid</span> {</span>
<span class="ef-line"> <span class="ef-prop">display</span>: <span class="ef-val">grid</span>;</span>
<span class="ef-line ef-hl"> <span class="ef-prop">grid-template-columns</span>: <span class="ef-val">repeat(auto-fit, minmax(50px, 1fr))</span>;</span>
<span class="ef-line"> <span class="ef-prop">gap</span>: <span class="ef-val">1rem</span>;</span>
<span class="ef-line">}</span>
</div>
</div>
<div class="ef-browser">
<div class="ef-browser-bar">
<span class="ef-dot"></span><span class="ef-dot"></span><span class="ef-dot"></span>
<div class="ef-tab">🌐 Emoji Grid</div>
</div>
<div class="ef-controlrow">
<span class="ef-control-label">container width</span>
<input type="range" class="ef-slider" id="ef-slider" min="120" max="700" step="10" value="380">
<span class="ef-width-readout" id="ef-width-readout">380px</span>
</div>
<div class="ef-screen">
<div class="ef-out-grid" id="ef-out-grid">
<div class="ef-out-item">🍕</div>
<div class="ef-out-item">🍔</div>
<div class="ef-out-item">🌮</div>
<div class="ef-out-item">🍣</div>
</div>
</div>
</div>
<div class="ef-readout" id="ef-note">
With a tiny <strong>50px</strong> minimum, all 4 emoji fit on one stretchy row until the container gets quite narrow — then they wrap to a second row instead of shrinking below 50px.
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('ef-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const slider = document.getElementById('ef-slider');
const readout = document.getElementById('ef-width-readout');
const grid = document.getElementById('ef-out-grid');
const note = document.getElementById('ef-note');
const MIN_TRACK = 50;
const GAP = 16;
function render() {
const width = parseInt(slider.value, 10);
readout.textContent = width + 'px';
grid.style.width = width + 'px';
let cols = Math.floor((width + GAP) / (MIN_TRACK + GAP));
if (cols < 1) cols = 1;
const perRow = Math.min(cols, 4);
const rows = Math.ceil(4 / perRow);
if (perRow >= 4) {
note.innerHTML = 'At ' + width + 'px, all <strong>4 items fit in one row</strong> — each stretches wider than its 50px minimum to fill the space evenly.';
} else {
note.innerHTML = 'At ' + width + 'px, only <strong>' + perRow + ' fit per row</strong> — the rest wrap down, giving <strong>' + rows + ' rows</strong> instead of shrinking items past 50px.';
}
}
slider.addEventListener('input', render);
render();
})();
</script>
</body>
</html>🔑 Summary
Function | Description |
|---|---|
| Sets min and max size for grid tracks |
| Reduces repetition when defining columns/rows |
Use them together for clean, responsive grid layouts!