Responsive layouts with CSS Grid let you create flexible arrangements that display correctly at different screen sizes. This article covers practical techniques: auto-fill, auto-fit, media queries, and common responsive grid patterns.
auto-fill and auto-fit
Key values for responsive grids without media queries:
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}- auto-fill — creates as many empty tracks as will fit. Empty tracks take up space.
- auto-fit — works similarly, but empty tracks collapse to zero and the remaining tracks expand.
/* auto-fill: пустые колонки остаются */
.grid-fill {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
/* auto-fit: пустые колонки исчезают */
.grid-fit {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}For catalogs and galleries, auto-fill is usually chosen — items do not stretch to the full width when there are only a few.
Choosing minmax
Choosing minmax(min, max) correctly affects how the grid behaves:
| min | max | Behavior |
|---|---|---|
| 200px | 1fr | Minimum of 200px; distributes space evenly when available |
| 150px | 300px | From 150px to 300px |
| 0 | 1fr | Can shrink to 0 (watch out for overflow) |
.cards {
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}At a container width of 900px and gap: 1rem, 3 columns fit (280 * 3 + 2 * 32 = 944, at 900px — 2 columns).
Breakpoints and media queries
For explicit control at different screen sizes:
.grid {
display: grid;
gap: 1rem;
}
@media (min-width: 480px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}Responsive page layout
.page {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-rows: auto 1fr auto auto;
min-height: 100vh;
}
@media (min-width: 768px) {
.page {
grid-template-areas:
"header header"
"main sidebar"
"footer footer";
grid-template-columns: 1fr 300px;
grid-template-rows: auto 1fr auto;
}
}
@media (min-width: 1024px) {
.page {
grid-template-areas:
"header header header"
"nav main sidebar"
"footer footer footer";
grid-template-columns: 200px 1fr 280px;
}
}Responsive gallery
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 200px;
gap: 1rem;
}
.gallery .featured {
grid-column: span 2;
grid-row: span 2;
}
@media (max-width: 500px) {
.gallery .featured {
grid-column: span 1;
grid-row: span 1;
}
}Equal-height cards
Grid automatically aligns the height of items in a row:
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
display: flex;
flex-direction: column;
}
.card .content {
flex: 1;
}Grid with a fixed sidebar
.layout {
display: grid;
grid-template-columns: 1fr;
min-height: 100vh;
}
@media (min-width: 768px) {
.layout {
grid-template-columns: 280px 1fr;
}
}
.sidebar {
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
}Tools
For quick prototyping of responsive grids, use the CSS Grid Generator on rechecker.ru. The tool lets you set track sizes and gap, and see the result immediately.
Container queries (container queries)
With container-type and @container, you can change the layout based on the container size rather than the viewport:
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}Supported in modern browsers. Use media queries as a fallback.
Responsive spacing
Using clamp() for a gradual change in gap:
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: clamp(1rem, 2vw, 2rem);
}Responsive grid-template-areas
Named areas make it easier to switch layouts:
.dashboard {
display: grid;
grid-template-areas:
"a b"
"c d";
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
@media (max-width: 600px) {
.dashboard {
grid-template-areas:
"a"
"b"
"c"
"d";
grid-template-columns: 1fr;
}
}Further reading
See the CSS Grid: complete guide to grids for a detailed guide to CSS Grid. For a comparison of Grid and Flexbox, see Flexbox vs CSS Grid: when to use each.
Grid with a fixed number of columns
When you need exactly N columns regardless of width:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
@media (max-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.grid {
grid-template-columns: 1fr;
}
}Responsive images in a grid
For image galleries, use aspect-ratio and object-fit:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}
.gallery img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}Grid with rows of different heights
grid-auto-rows: minmax(100px, auto) lets rows adjust to their content. For a masonry effect (without column), consider grid-template-rows: masonry (experimental in Firefox) or specialized libraries.
Responsive menu
Grid can be used for navigation that changes its layout on mobile:
.nav {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 0.5rem;
}
@media (max-width: 640px) {
.nav {
grid-template-columns: 1fr;
}
}Form grid
For forms with fields of different widths:
.form {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.form .full-width {
grid-column: 1 / -1;
}
@media (max-width: 600px) {
.form {
grid-template-columns: 1fr;
}
}Support for older browsers
For browsers without Grid support, use @supports:
@supports (display: grid) {
.grid { display: grid; /* ... */ }
}
@supports not (display: grid) {
.grid { display: flex; flex-wrap: wrap; }
.grid > * { flex: 1 1 300px; }
}