CSS Grid for Beginners: display:grid, the fr Unit, gap, and Responsive Layouts
CSS Grid lets you build web layouts intuitively in two dimensions, rows and columns. This article explains it from the basics of display:grid through grid-template-columns/rows and the fr unit, spacing with gap, named placement with grid-template-areas, responsive layouts using repeat, minmax, and auto-fit, and how it compares with Flexbox.
When building a web layout, have you ever wanted to "place a sidebar and main area side by side" or "line cards up in a neat three-column grid"? CSS Grid lets you achieve these two-dimensional (row and column) layouts intuitively. Arrangements that once had to be forced with floats or table layouts can now be written in a few lines of CSS, and in a way that rarely breaks. This article walks through what CSS Grid is, the key properties you will use in practice, and how to make layouts responsive.
What Is CSS Grid
CSS Grid Layout is a CSS mechanism for placing elements along a grid made of rows and columns. When you turn a parent element into a "grid container," its direct children (grid items) line up according to the cells you define.
Its biggest feature is that it is a two-dimensional layout that controls both the vertical and horizontal directions at once. Whereas Flexbox (discussed later) is good at a single direction (either rows or columns), Grid can express something like "a table of three columns by two rows" directly. It shines in a wide range of situations, from the overall skeleton of a page to aligning card lists and galleries.
Today almost every modern browser supports CSS Grid, so you can use it confidently in production. Before writing concrete code, try adjusting the number of columns and the spacing with sliders and buttons in the CSS Grid Generator and watch the generated CSS; it gives you a visual sense of which property does what.
display:grid and grid-template-columns/rows
The first step with Grid is to set display: grid on the parent element. That alone turns it into a grid container. Next, you define the column structure with grid-template-columns and the row structure with grid-template-rows.
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
The example above declares "three columns of 200px width." Child elements placed inside the container fill the cells one by one, starting from the top left. Because the number of values becomes the number of columns, 100px 1fr makes two columns, while 100px 100px 100px 100px makes four.
- grid-template-columns: specify the width of each column, separated by spaces. You get as many columns as values listed.
- grid-template-rows: specify the height of each row in the same way. If omitted, row height is determined automatically by the amount of content.
Widths are not limited to px (pixels); you can freely combine % (percent), em, and the fr unit described later. Once you grasp the basic idea that "number of columns equals number of values," you can build the skeleton of a grid exactly as you intend.
Sizing and Spacing with the fr Unit and gap
Deciding column widths with fixed px alone leaves surplus or shortage when the screen width changes. This is where the fr unit comes in. fr stands for "fraction," a unit that shares the available space of the container by ratio.
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
gap: 16px;
}
In this example, the three columns share the width in a 1:2:1 ratio. Whether the screen widens or narrows, they stretch and shrink while keeping this ratio, which is an excellent match for responsive design. Writing 1fr 1fr 1fr produces three equal columns.
To create gaps (gutters) between columns and rows, use the gap property. A single value like gap: 16px applies the same spacing to both rows and columns, while two values like gap: 24px 16px set them separately ("24px between rows, 16px between columns"). You do not have to adjust margins one by one, and no extra space appears at the edges, so card alignment comes out very cleanly. Combining fr and gap makes it easy to build flexible layouts that "keep the spacing while dividing the rest by ratio."
Naming Placement with grid-template-areas
When building a page skeleton (header, sidebar, main, footer, and so on), grid-template-areas is wonderfully intuitive. You give each region a name and express the layout by arranging those names "as if drawing a picture."
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"side main"
"footer footer";
}
Then, assigning a name to each child like grid-area: header; places that element in the specified region. Because the strings themselves form a map of the screen, a big advantage is that you can grasp the whole layout just by reading the code.
- Repeating the same name horizontally makes the region span across columns (like header and footer above).
- Repeating the same name vertically makes it span across rows.
- An empty cell is written with a
.(dot).
Because placement is by name, responsive rework is easy: just swap the areas definition to move the sidebar above or below, for example. When you want to try a complex arrangement, experiment with regions in the CSS Grid Generator and use the generated areas syntax as a reference to learn faster.
Going Responsive with repeat, minmax, and auto-fit
When there are many columns, writing 1fr 1fr 1fr 1fr is tedious. The repeat() function lets you write it concisely as repeat(4, 1fr), meaning "repeat the same specification this many times."
Even more powerful for automatically adjusting the number of columns to the screen width is the combination of minmax() and auto-fit (or auto-fill).
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
This single line is the most widely used responsive-grid staple in practice. Breaking down its meaning:
| Code | Meaning |
|---|---|
| minmax(240px, 1fr) | Each column is at least 240px; at most it shares the remainder by ratio (1fr) |
| auto-fit | Generate as many columns as fit, and collapse any leftover tracks |
| repeat(auto-fit, ...) | Repeat the above automatically to match the screen width |
With just this declaration, many cards line up in one row on wide screens, while on narrow phones it automatically wraps down to one or two columns. The big appeal is that you can achieve responsiveness without writing any media queries. Note that auto-fit collapses empty columns, whereas auto-fill leaves empty tracks, so when you want cards packed to the left, auto-fit is usually the choice.
When to Use Flexbox Instead
Alongside Grid, the other layout staple is Flexbox. Both are powerful, but they excel at different things. Roughly speaking, Grid suits two-dimensional layouts (both rows and columns), while Flexbox suits one-dimensional layouts (either a row or a column).
| CSS Grid | Flexbox | |
|---|---|---|
| Strong direction | Two-dimensional (rows and columns at once) | One-dimensional (row or column) |
| Good for | Whole pages and card lists | Navigation, button rows, centering elements |
| Design starting point | Layout (the frame) first | Content first |
Grid shines when you "decide the frame first and pour content into it," such as a page skeleton or a tidy card grid. Flexbox, on the other hand, is good at "lining items up in a single line and adjusting the spacing," like navigation menu items, a row of buttons, or centering an element. You do not have to use only one: in practice it is common to build the overall page with Grid and arrange the smaller parts inside it with Flexbox.
CSS Grid is the modern standard for building two-dimensional layouts declaratively and in a way that rarely breaks. Start by adjusting the number of columns and rows, the gap, and the fr ratios in the CSS Grid Generator, and compare the generated CSS with how the screen changes. You will understand the properties in a visible form and find it easier to apply them in your own code.
Please note that this article is intended to provide general information. Because CSS specifications and browser support change over time, check the latest official information (such as MDN and the specifications) before making implementation decisions.
FAQ
Should I use CSS Grid or Flexbox?
It depends on the use case. Grid is good at two-dimensional layouts of rows and columns, suiting page skeletons and aligning card lists. Flexbox is good at one-dimensional layouts (a row or column), suiting navigation, rows of buttons, and centering. In practice it is common to use both: Grid for the whole page and Flexbox for the smaller parts inside.
What is the fr unit?
fr stands for "fraction," a unit that shares the available space of the grid container by ratio. For example, grid-template-columns: 1fr 2fr 1fr makes three columns share the width in a 1:2:1 ratio. Because they stretch and shrink while keeping that ratio as the screen width changes, the fr unit pairs well with responsive layouts.
Can I build a responsive grid without media queries?
Yes. Writing grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)) keeps each column at a minimum of 240px, generates as many columns as fit, and wraps automatically on narrow screens. You can achieve a responsive grid whose column count changes with the screen width without writing any media queries.
What makes grid-template-areas convenient?
You can give each region a name and express the layout by arranging those names like a picture. Because the strings form a map of the screen, you grasp the whole arrangement just by reading the code. For responsive rework, you simply swap the areas definition to rearrange things like the sidebar position dramatically.
Is the CSS Grid Generator free, and is my data safe?
WAZA TOOLS' CSS Grid Generator runs entirely in your browser, so the settings you enter are never sent to or stored on a server. It works on smartphones too, and you can generate and copy the CSS code as many times as you like, for free.