Writing a grid of twelve equal columns by hand, one by one, or a card grid where each card must stay between 200 and 300 pixels wide no matter how many cards are on screen, quickly becomes tedious without a way to generate that pattern automatically. repeat() and minmax() exist for exactly that: the first avoids repeating a value, the second gives a range of sizes instead of a fixed one.
Combined together, and often with auto-fit and auto-fill, these two functions let you build responsive grids without writing a single Media query, which makes them some of the most used tools in Grid on a daily basis.
Definition
repeat() repeats a pattern of columns or rows a set number of times inside grid-template-columns, so you do not have to type it out by hand. minmax() sets a minimum and a maximum size for a column or row, which then varies freely between those two limits depending on available space. Used alone or together, they shrink a declaration that could span a full line of repeated values into a short, readable syntax.
repeat() on its own
.grid {
grid-template-columns: repeat(4, 1fr);
}repeat(4, 1fr) is exactly equivalent to writing 1fr four times in a row. The first argument sets the number of repetitions, the second the pattern to repeat, which can itself contain several values: repeat(2, 100px 1fr) repeats the pair 100px 1fr twice, giving four columns in total.
minmax() on its own
.grid {
grid-template-columns: minmax(200px, 1fr) 1fr 1fr;
}Here, the first column never drops below 200 pixels, even if the container becomes very narrow, but it can still grow like any other fr unit column when there is room. It is a simple way to stop a column holding a logo or a button from becoming too narrow to read.
The combination that builds a responsive grid
.grid {
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
}| Piece | Role |
|---|---|
auto-fit | Automatically works out how many columns fit |
minmax(220px, 1fr) | Each column is at least 220px, and shares the rest beyond that |
repeat(...) | Applies this pattern as many times as needed |
This single line creates a card grid that adds or removes columns on its own depending on screen width, with no media query needed to go from four columns on a wide screen down to one on mobile.
Choosing between auto-fit and auto-fill inside repeat() changes what happens to empty columns once the maximum column count is reached, a nuance covered in detail in the entry dedicated to those two keywords. A related trap involves minmax(0, 1fr): replacing the minimum with 0 stops content like an image from forcing the column to grow beyond what the grid had planned, a useful setting when a card grid contains images that should never make their column wider than the others.
The trap of a second argument that is too rigid
minmax() only behaves as expected in a responsive grid if its second argument stays flexible, in fr or a percentage. A minmax(220px, 300px) always locks the column between two fixed values, which stops the grid from actually stretching to fill the remaining space.
auto-fit grid does not seem to stretch properly and leaves a gap on the right, check the second argument of minmax(). A flexible 1fr is almost always the right choice; a fixed pixel value blocks the stretching the grid is supposed to provide.Frequently asked questions
repeat() inside minmax()?No, it is the other way around: minmax() goes as an argument inside repeat(), never the reverse. repeat() describes how many times to repeat a pattern, and minmax() can be part of that pattern, as in repeat(3, minmax(100px, 1fr)).
minmax() are inconsistent, for example a minimum bigger than the maximum?The browser treats the minimum as the priority and ignores the maximum in that specific case, to avoid a column ending up with an impossible size to honor. This case is rare in practice and almost always signals a value that needs fixing rather than a behavior worth relying on.
repeat() also work for grid-template-rows?Yes, repeat() and minmax() work exactly the same way for rows as for columns. You will find them for example in grid-template-rows: repeat(3, minmax(100px, auto)) for three rows that never drop below 100 pixels while still being able to grow with their content.