Difficulty: Intermediate
CSS Grid provides powerful functions for defining grid templates: repeat() for creating repeating track patterns, minmax() for setting flexible size ranges, and the auto-fill and auto-fit keywords for creating responsive grids that automatically adjust the number of columns based on available space. Together, these enable responsive layouts that adapt to any screen size without media queries.
The repeat() function eliminates repetition when defining grid tracks. Instead of writing grid-template-columns: 1fr 1fr 1fr 1fr, you write grid-template-columns: repeat(4, 1fr). The first argument is the repetition count, and the second is the track size pattern. You can repeat complex patterns too: repeat(3, 1fr 2fr) creates six columns alternating between 1fr and 2fr widths. The repeat function can be mixed with other values: 200px repeat(3, 1fr) 200px creates fixed sidebars with three flexible columns in between.
The minmax() function defines a track size range with a minimum and maximum value. For example, minmax(200px, 1fr) creates a track that is at least 200px wide but can grow to fill available space. This is commonly used with grid-auto-rows: minmax(100px, auto) to ensure rows are at least 100px tall but can expand to fit their content. The min value cannot be fr (since fr is relative and cannot serve as a minimum), but the max value can be.
The auto-fill keyword, used inside repeat(), creates as many tracks as can fit in the container width. The declaration grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)) creates a responsive grid that automatically adjusts the number of columns: on a wide screen, four or more columns appear; as the screen narrows, columns are dropped and items wrap to new rows -- all without media queries. When there are fewer items than available columns, auto-fill creates empty tracks to maintain the grid structure.
auto-fit works like auto-fill but with one key difference: when there are fewer items than available columns, auto-fit collapses the empty tracks to zero width, allowing existing items to stretch and fill the available space. In practice, auto-fit is more commonly used because it prevents empty gaps when there are few items. The difference only matters when there are fewer items than the grid can fit -- with enough items to fill the grid, auto-fill and auto-fit behave identically.
/* Without repeat */
.grid-verbose {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}
/* With repeat */
.grid-concise {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
/* Repeating a pattern */
.grid-pattern {
display: grid;
grid-template-columns: repeat(3, 100px 1fr);
/* Creates: 100px 1fr 100px 1fr 100px 1fr */
}
/* Mixed: fixed + repeated + fixed */
.grid-mixed {
display: grid;
grid-template-columns: 200px repeat(3, 1fr) 200px;
}
repeat() takes a count and a track pattern. It can repeat simple values (1fr), complex patterns (100px 1fr), and be mixed with standalone values. This is essential for grids with many columns.
/* Columns at least 200px, grow to fill space */
.flex-grid {
display: grid;
grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr);
gap: 16px;
}
/* Rows at least 100px, grow to fit content */
.auto-height-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
gap: 16px;
}
/* Sidebar: min 200px, max 300px */
.sidebar-layout {
display: grid;
grid-template-columns: minmax(200px, 300px) 1fr;
gap: 24px;
}
minmax() sets a size range. Common patterns: minmax(200px, 1fr) for flexible columns with a minimum width, minmax(100px, auto) for rows that grow to fit content, and minmax(min, max) for constrained sidebars.
/* Responsive grid: columns are at least 280px */
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
/* auto-fill creates empty tracks when items are few */
/* With 2 items in a 1200px container: */
/* | item | item | empty | empty | */
auto-fill calculates how many columns of at least 280px fit in the container and creates that many tracks. As the container resizes, columns are added or removed automatically. Empty tracks remain when there are fewer items than columns.
/* auto-fill: keeps empty tracks */
.auto-fill-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
/* With 2 items in 1000px container: */
/* | item | item | empty | empty | */
/* auto-fit: collapses empty tracks */
.auto-fit-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
/* With 2 items in 1000px container: */
/* | item | item | */
/* Items stretch to fill all available space */
The difference appears when there are fewer items than available columns. auto-fill keeps empty tracks (items stay at minmax size). auto-fit collapses empty tracks (items stretch to fill the container). auto-fit is usually preferred for card grids.
fr Unit, repeat(), minmax(), auto-fill, auto-fit