Suggest an editImprove this articleRefine the answer for “CSS grid layout”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**CSS Grid Layout** is a two-dimensional layout system that divides a container into rows and columns, letting you position elements across both axes at once. ```css .container { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr auto; gap: 1rem; } ``` **Key point:** unlike Flexbox (one axis), Grid controls rows and columns simultaneously, making it the right tool for page-level layouts like header, sidebar, and footer structures.Shown above the full answer for quick recall.Answer (EN)Image**CSS Grid Layout** is a two-dimensional CSS layout system that divides a container into rows and columns, letting you place items precisely across both axes at once. ## Theory ### TL;DR - Think of it like a spreadsheet: define column and row tracks, then drop items into specific cells - Main difference from Flexbox: Grid controls rows and columns simultaneously; Flexbox works one axis at a time - Use Grid for page structure (header, sidebar, content, footer); use Flexbox inside grid cells for component alignment - `fr` unit distributes free space after fixed and `auto` tracks are sized - `grid-template-areas` gives you a visual map of your layout directly in CSS ### Quick example ```css .container { display: grid; grid-template-columns: 1fr 2fr 1fr; /* narrow | wide | narrow */ grid-template-rows: auto 1fr auto; /* content | flex | content */ gap: 1rem; height: 100vh; } ``` Three columns (equal, double, equal), three rows (content-sized, flexible, content-sized). Items fill left to right, top to bottom by default. Add `grid-template-areas` and you get a named layout readable at a glance. ### Grid vs Flexbox Grid creates explicit tracks on the container and places items into those intersections. Flexbox lines items up along one axis and wraps them when needed. Neither replaces the other. Grid is the page skeleton. Flexbox handles the muscles inside each cell. The practical rule: if you need to control rows and columns together (dashboard, magazine layout, overlapping elements), use Grid. If you have a row of buttons or a list of cards that just needs to wrap, Flexbox is simpler. ### When to use - Full-page layout with header, sidebar, content, footer: Grid with `grid-template-areas` - Dashboard with panels spanning multiple columns: Grid with `grid-column: 1 / -1` - Nav bar with links spread horizontally: Flexbox - Card component internals (icon + text aligned): Flexbox - Responsive gallery with unknown item count: `repeat(auto-fill, minmax(250px, 1fr))` - Two elements overlapping without absolute positioning: Grid, same cell area, different `z-index` ### Comparison table | Feature | CSS Grid | Flexbox | |---|---|---| | Dimensions | 2D: rows and columns | 1D: main axis + cross axis | | Item placement | Explicit lines, areas, or auto-flow | Flow order with optional wrapping | | Spanning | Native `grid-column: 1 / 3` | Not available natively | | Named areas | Yes, `grid-template-areas` | No | | Best for | Page layouts, dashboards, overlapping content | Nav bars, card internals, button groups | ### Core properties **Container properties** define the grid structure. `grid-template-columns` and `grid-template-rows` set track sizes. `gap` adds space between tracks only (no outer edges by spec). `grid-template-areas` maps named regions visually. ```css .layout { display: grid; grid-template-areas: "header header header" "sidebar content aside" "footer footer footer"; grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; gap: 1rem; } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .footer { grid-area: footer; } ``` No floats. No clearfix. No `position: absolute`. That whole layout took six lines. **Item properties** control placement and alignment. `grid-column: 1 / 3` spans from line 1 to line 3. `grid-column: 1 / -1` always spans the full row, regardless of column count. `justify-self` and `align-self` align a single item within its cell without touching the rest. ### repeat() and minmax() `repeat(3, 1fr)` is three equal columns. The more useful pattern is `repeat(auto-fill, minmax(250px, 1fr))`. That creates as many columns as fit, each at least 250px wide, distributing remaining space proportionally. Replace `auto-fill` with `auto-fit` and empty trailing tracks collapse, so items stretch to fill the row. The difference matters when you have fewer items than possible columns. `auto-fill` keeps ghost tracks visible. `auto-fit` removes them. I have seen `fr` columns collapse to near zero on small screens more times than I can count. The fix is always the same: use `minmax(200px, 1fr)` instead of plain `1fr`. The `fr` unit only distributes free space; when there is none, tracks shrink to min-content width. ### How the browser handles this `display: grid` triggers a grid formatting context. The browser first resolves fixed track sizes, then `auto`, then distributes `fr` units from what remains. Explicitly placed items are positioned first; the rest auto-flow into open cells. Resize the viewport and the track sizing algorithm runs again. That is why heavy `minmax` and `fr` combinations on large grids can cost more on resize than a simple Flexbox flow. ### Common mistakes **Setting `justify-items: center` to center one item.** `justify-items` centers every item in every cell. For a single item, use `justify-self: center` on that element directly. ```css /* Moves all items - probably not what you want */ .container { justify-items: center; } /* Moves only this one */ .featured { justify-self: center; } ``` **Expecting `gap` to add outer spacing.** `gap` inserts space between tracks only. There is no trailing gap by spec. If you need space around the outside, add `padding` to the container. **Using plain `1fr` on small screens.** `fr` only takes free space. When the container has no free space, tracks can shrink to min-content width. Set a floor with `minmax(200px, 1fr)` instead. ```css /* Fragile on small screens */ grid-template-columns: repeat(3, 1fr); /* Safer */ grid-template-columns: repeat(3, minmax(200px, 1fr)); ``` **Nested grids with no height.** A child with `display: grid` has no height unless the parent cell stretches it. `align-items: stretch` is the default on the parent, but overrides happen. Check that first when a nested grid collapses. **Overlapping items stacking in the wrong order.** Items overlap in DOM order by default. Add explicit `z-index` values to control which one sits on top. Grid items accept `z-index` the same way positioned elements do when they share overlapping areas. ### Real-world usage - Tailwind CSS: `grid grid-cols-12 gap-4` for responsive dashboards - Bootstrap 5: `row g-3` with column wrappers for card grids - Material-UI (MUI): `Grid container spacing={2}` in React apps - Chakra UI: `SimpleGrid columns={4}` for auto-flow galleries - GitHub repo page: file list uses grid for icon, filename, and action column alignment ### Follow-up questions **Q:** What is the difference between `grid-template` and `grid-template-columns`? **A:** `grid-template` is a shorthand that combines `grid-template-columns`, `grid-template-rows`, and `grid-template-areas` in one declaration. Use individual properties when you need to override just one dimension without touching the others. **Q:** How does the implicit grid work? **A:** Items placed beyond the explicit grid create new tracks automatically. `grid-auto-rows` and `grid-auto-columns` control implicit track sizes. `grid-auto-flow: dense` fills gaps by visually reordering items, while DOM order stays unchanged. **Q:** What is subgrid? **A:** Subgrid (CSS Grid Level 2) lets a child grid align its tracks to the parent grid instead of creating independent ones. You set `grid-template-rows: subgrid` or `grid-template-columns: subgrid` on the child. Useful for aligning labels and values across multiple cards. Browser support in modern browsers is solid as of late 2024. **Q:** When does Grid reflow cost more than Flexbox? **A:** Complex `minmax` and `fr` calculations repeat on every resize. A large grid with many `auto`-sized tracks runs a heavier algorithm than a simple Flexbox row. Profile with Chrome DevTools Performance panel before optimizing. **Q:** Can you build a masonry layout with CSS Grid alone? **A:** `grid-template-rows: masonry` is in the spec and was available behind a flag in Firefox. As of 2024, no stable browser ships it. Current fallbacks are CSS `column-count` or JavaScript. Knowing the spec exists and where implementation stands signals senior-level awareness. ## Examples ### Basic responsive page layout ```css .page { display: grid; grid-template-areas: "header" "content" "footer"; grid-template-rows: auto 1fr auto; min-height: 100vh; gap: 1rem; } @media (min-width: 768px) { .page { grid-template-areas: "header header" "sidebar content" "footer footer"; grid-template-columns: 250px 1fr; } } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .footer { grid-area: footer; } ``` Mobile stacks everything vertically. Above 768px, sidebar appears on the left. The entire layout switch is two property changes inside a media query. ### Dashboard with spanning panels ```css .dashboard { display: grid; grid-template-columns: 250px 1fr 300px; grid-template-rows: auto 1fr auto; grid-template-areas: "sidebar header stats" "sidebar content stats" "sidebar footer footer"; gap: 2rem; min-height: 100vh; } .sidebar { grid-area: sidebar; } .header { grid-area: header; } .content { grid-area: content; } .stats { grid-area: stats; } .footer { grid-area: footer; } ``` Sidebar spans all three rows on the left. Stats panel spans two rows on the right. Footer covers the last two columns. This is the structure behind most admin panels built with Next.js and Remix. ### Overlapping items with z-index ```css .canvas { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 100px); gap: 10px; } .card-red { grid-column: 1 / 3; /* top-left 2x2 block */ grid-row: 1 / 3; background: #e55; z-index: 1; } .card-blue { grid-column: 2 / 4; /* overlaps bottom-right corner of red */ grid-row: 2 / 4; background: #55e; z-index: 2; } ``` Blue overlaps the bottom-right corner of red without any clipping. No absolute positioning needed. `z-index` works on grid items the same way it works on positioned elements when they share overlapping areas.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.