CSS grid is used by frontend developers and designers to build ALL kinds of modern web layouts and interfaces — in fact, it’s the layout structure for apps like Slack and the Webflow Style panel itself. But it can be used to create anything form basic structures to entire websites.
We’ll cover grid-based layouts in 6 parts: we’ll show how to create and configure grids, we’ll talk about the magical div block, we’ll use grid AUTO position to create an image grid layout, we’ll use MANUAL position and OVERLAPPING to create a four-quadrant hero section, we’ll go into reusable layouts using grid template areas, and then we’ll cover making grid layouts responsive to work on DIFFERENT devices.
Now. Before we begin — let’s clear up something. Grids are GUIDES. It’s no different than arranging apps and widgets on iOS. (You can push things around, but the things INSIDE the grid will be GUIDED by columns...and rows.)
And this is the DEFAULT behavior for CSS Grid (things are AUTOMATICALLY positioned...and they wrap to the next row when they run out of columns). But that’s just the BEGINNING. Because you can do SO much more.
So with that in mind, let’s start with the basics. ANYTHING can be a grid. Almost anything. Here’s a section. Click grid? Now you have a grid. Here’s a div block. Click grid? Now you have a grid. On the Add panel? There’s a grid you can just drag right in. Collection list filled with dynamic content from the CMS? Set its display setting to Grid? Now you have a grid. Working on a late-night project and accidentally spill coffee, causing your other hand to lean in just the perfect way on your macOS-compatible keyboard to press both the Command and E keys at the same time? Start typing Grid, press Enter. Now you have a grid.
Now. That’s on Mac. It’s different on Windows. Grimur?
Grimur: I’m working on a late-night project and accidentally spilled coffee, causing my other hand to lean in just the perfect way on my Windows-compatible keyboard to press both the CONTROL and E keys at the same time.
McGuire: Start typing Grid, press Enter. Now he has a grid.
And how do we use a grid? Well, we just put stuff inside. By default, things take up the available cells, and wrap to the next line automatically. In fact, new rows will be automatically created.
And at any time, to edit a grid...press edit grid. Now you’re editing the grid. When you’re editing, you can add columns or rows to your grid. And notice how the contents automatically wrap to fill up the space inside. Once we’re done editing the grid, let’s close out.
And here’s the first thing that might seem odd: if we want to drag an element to the bottom right cell? It just...doesn’t work. But that’s expected. That’s because elements added to a grid, by default, are AUTOMATICALLY positioned. If we want to manually position this? Just set it to manual. And we can now drag it wherever.
We’ll cover this later on when we talk about Manual position in more detail, but there’s one, really important point to make here.
This is a website we built in CSS grid. Except it’s not. It’s Microsoft Excel. And in spreadsheets or tables, deleting a row or column usually DESTROYS the content inside.
Grids on the web are different. BECAUSE they’re guides, deleting a column or row might push things around, but it’s not deleting actual content.
And that’s the main idea: there is NO wrong move you can make when creating a grid. Grids are non-destructive in that they’re just GUIDES for the content we’ll put inside.
Let’s edit our grid further. Lots of options here. And we can just click and drag so we can adjust that space (you can adjust the GAPS between the rows and columns).
But it gets better. Want to adjust the columns themselves? You can do this, too; you can adjust sizing on a column by clicking and dragging — you can do this right on the canvas when you’re editing a grid.
By the way, FRs (the FR unit on these columns)? These are fractional units. Because before grid came out, we’d manually calculate things like percentages, pixel values (and YOU can still use these)...but FRs replace everyone having to manage their own Cartesian coordinate systems in favor of something far more straightforward. And it goes like this:
Three columns? Each set to 1 FR? That means each will take up 1/3rd of the width. Four columns? 1 FR each? Now each takes up 1/4th. And the math is done FOR us, so if we want this column to be TWICE the width of the others, we just set it to 2 FR. Notice how everything else scales automatically. And one more thing to note here: we mentioned the GAPS between each cell. You can change these gaps and FRs will STILL compensate for that.
Are FRs magic? No; they’re science. And also magic.
When you’re DONE editing a grid, remember you can ALWAYS come back and change things, but for now, we can just PRESS Escape, or, press the button that says “done.”
So. Grids. We can make a grid, set some rows and columns, and start putting things inside. They’re automatically going to position themselves, but we can deviate from that by setting one or more elements to MANUAL positioning. (We can then move it wherever we want inside a grid.)
Let’s move to the magical Div block. Because if you haven’t noticed yet, there’s something odd going on. There aren’t many practical layouts that look like THIS. And we get the question a lot, “yeah, grid, but how do we USE it?” Syntax aside, there’s an important point there. Grid-based layouts often require NESTING things (headings, paragraphs, buttons, images — whatever) — grid layouts often require putting MULTIPLE things inside single cells.
So. Do we just set things to manual position and drag them into the same cell? Well...no. Now they’re all stacked on top of one another in a mess.
Enter: the magical div block. It’s a div block. But we’re calling it magical. And the idea is this: we can just drag in a div block that TAKES UP a cell...we can place it wherever...and now we can put stuff INSIDE the div block.
So if this is our grid, and we want these things inside, we put a DIV block in the cell. And we position the things we want...inside the div block. The most PRECISE way to make sure we’re placing our elements is to use the Navigator (but we’ll cover a shortcut for doing this on the canvas in just a bit).
But that’s the SECOND big idea (we covered how grids are guides for our content)...but the SECOND takeaway here is that grid CELLS aren’t actual containers (they’re NOT div blocks, and by default, they only hold one thing at a time).
So div blocks give us the power to put MULTIPLE elements inside a grid cell.
Those are our two takeaways: grids GUIDE our content, and div blocks let us NEST multiple things inside any CELL in our grid.
But let’s make this REAL and put all of it into REAL layouts. And to do that, let’s do auto position FIRST...by building this image grid.
And this one’s straightforward. For us, we have a blank section and a blank container...and we’re going to use a Grid (just dragging in a GRID from the Add panel and we’re placing it in the Container — this way we keep the grid and our images contained towards the center of our design).
But for now, let’s add our images. As we know, to add stuff to our grid? We just click and drag it in. (WE’RE using images, but this could be headings or links or div blocks or videos...).
Let’s edit our grid before we continue — let’s make it a 4x4 (remember: we can ALWAYS change this). When we’re done? Let’s stop editing.
And let’s CONTINUE dragging images inside. But notice how, like we covered earlier, no matter WHERE we let go, content is automatically placed. The children of the grid (the IMAGES inside) are just wrapping around and filling up the available cells inside our GRID. (It’s doing this automatically.)
In fact, if we go in and edit again? We can CHANGE, for instance, the number of columns. And again, in Excel or Numbers or Google Sheets or with ice cube trays — removing a column is HIGHLY destructive and destroys the stuff inside. But HERE...our images are fine. They’re now just taking up fewer columns (they WRAP automatically). Once we’re done, let’s head back out.
And something to note here about SIZE... is that these rows (the height of EACH row in our grid) — this is automatically sized. And since the Grid (and the Container and the Section) — since none of these have a height set to them, ONE option is to just set a height on our Grid. Let’s choose something like 800 pixels, but we can ALWAYS change this later.
But right now it’s a LITTLE inconsistent — these images have different aspect ratios; they’re all aligned to the top-left of each cell... let’s start to CONTROL that. With our GRID selected, let’s look at our options here. We can ALIGN... or justify any of the CHILDREN elements inside the Grid.
Now. With IMAGES specifically, sometimes designers want images like these to fit more consistently (to have the SAME row heights, and same aspect ratios).
And a great way to do that is fit (object fit). It’s 100% magic. And it WORKS (most of the time).
Now. Before filming, we pre-applied the same class to each of these images. You can TELL... because it literally says “Class we pre-applied” on each of the images. If we hadn’t done that, we could always add a class later. But we DID.
So. To fit the images EVENLY? We only have to do TWO things: (1) we set the dimensions (we set 100% width...and 100% height). And (2) we USE object-fit. (We’re doing all of this on the CLASS that’s been applied to the images). We’ll set our FIT... to Cover.
And just like that, all the objects FIT inside their cells. And notice how the row heights are perfectly even.
Now. HOW is this grid NOW being sized? Well let’s go back a moment, because we set the height to 800 pixels a minute ago. What happens if we REMOVE that height on the GRID? Does it go to zero?
Almost. In fact, if you look closely, it still has the GAP (the space between the rows). But because we DEFINED the height of EACH image as 100%, they’re only going to be as tall as the ROWS themselves. Which don’t have a height. Which is why this whole thing has collapsed. So. If we put back a number? (If we give the grid a height?) It sizes accordingly.
Of course, the blue property labels TURNED blue because we’ve changed something on this class. And, as we know, the AMBER property labels show that a value on this class is coming from somewhere ELSE. But what about PINK labels?
Let’s just pick ONE of these images and SPAN it (we’re grabbing the corner...clicking and dragging...to span). So instead of ONE cell in our grid, it spans MULTIPLE cells. And we can see it in the Style panel: we see HOW many columns and how many rows it spans. And THAT information is stored in the ELEMENT. That’s what pink labels mean — this does NOT apply to the whole class we pre-applied earlier called “class we pre-applied” — it JUST affects the SELECTED element.
That’s automatic positioning using an image grid. What about manual positioning and OVERLAP? To go over THAT, let’s build this hero section. But to GET there, let’s first make our hero section a side-by-side (we’ll talk about WHY in a moment).
For this, we’re just going to drag in a Section element (dragging it right into the page body). And we’ll set a height (let’s set the minimum height to 70vh — this way it’s 70% the height of the viewport).
And all we have to do to make it side-by-side? Just set the Section...to GRID. (Two columns...now we can build our side-by-side.)
So let’s start by putting an image on the left. Let’s go to the Assets panel and drag in the image we want on the left side (dropping it right into our Grid section). And by default (as we know), it goes in the FIRST available cell (top-left). And we want our image to take up the full space available.
Well, fortunately, we just brushed up on object FIT. And like we did before, we do TWO things to make this work perfectly. We can (1) add our dimensions (set both width and height of our image to 100%)...and (2) we can set our FIT to Cover. (And now our IMAGE...is COVERING the first cell.)
But that’s not what we said we’d build.
With our image selected, let’s span it. (We want to click and drag to SPAN this element across both cells in our left column.) That’s it. Again, spanning is THAT simple. Want to span the TOP two cells? Click and drag...and it’s spanned. Want to put it back? Span it back.
Span. The word sounds weirder the more you say it.
That’s our left side of the side-by-side. What about the right one? Well here’s where we go back to our magical Div block. We’ll drag a div block right into the grid, and it can be placed in the next available cell. To span it? We’ll just span it. And that’s the side-by-side.
If we want to put a heading inside? Let’s demonstrate the WRONG way to do this. Drag the heading...over to the right here? Let go? This...is NOT what we wanted. Remember: dragging something into a Grid is DIFFERENT than dragging something into a Div block INSIDE a grid.
So to make sure we get it right, let’s undo...and try that again, but this time let’s hold down Command on macOS or Control on Windows...and just drag the heading into the Div block. We can verify this in the Navigator. (The heading is in the div block...which is in the grid.)
Let’s do the same with a paragraph — this time we can drag the paragraph RIGHT into the Navigator ITSELF (right under the heading).
And finally, let’s add some buttons. This time (and because we’ve developed a habit of showing DIFFERENT ways to add things)...with our Paragraph still selected, we can add something RIGHT after it. We’ll use Quick Find.
Which we can do by pressing Command + E (or Control + E on Windows) and starting to type button. And it's not just elements (it's even other layouts we've designed and saved). Once we select it? It's placed right after the paragraph.
NOW. How do we vertically center this stuff? A couple ways. We can select the grid ITSELF. And if we want the children to align to the CENTER...we just...align to the center.
Or, if we want to undo that, we could use flexbox (we could apply flexbox to the Div block itself, and just make sure it’s set to Vertical, and we can mess with our alignment or justification controls to make it work how we want it to work).
And if we select our Grid again, and we go to EDIT? We can adjust or even REMOVE the gap (just set the gap there to ZERO) — so now it’s truly a 50/50 split with the image. And for our content on the right? We can USE our Div block (by the way, let’s name this something like “Hero content” to keep things organized).
But wait a moment. This section is called MANUAL position. And so far...everything uses AUTO positioning. (We’ve COVERED spans, but we haven’t used MANUAL position on this layout). So. What is our GOAL? Our goal... is to have our hero content on the bottom-right cell. How do we do that?
Well...we just set our image on the left to manual position...and we set our div block on the RIGHT to manual position. And now? We can select and SPAN our image to take up all FOUR cells. And if we want our magical flexbox Div block to position on the bottom right? We span it DOWN so it takes up the bottom right cell. So now we have a BASIC overlap.
Is it stunning? Not yet. A couple things here: (1) we need to make the background more not terrible. So in our Div block (the Hero content block), we can add a background color. But (2), we should go in and figure out what’s going on with the row height. Because you might notice that the HEIGHT of the second row is no longer HALF — because we have the height of the CONTENT added to the bottom row, too. Could we set each of the rows to 1 FR? Can we use fraction units on both? Well, yes. In fact, that’s going to still respect the content inside, but give us more even rows. But we could also make the BOTTOM row Auto. That’ll mean the SIZE of the bottom row is determined ONLY by the content inside. And when we do that, we can now add breathing room by adding PADDING (just add some padding to the Hero content block).
But that’s MANUAL positioning and overlapping. What about reusable layouts? This part goes pretty quick. Because, here’s a section. Let’s give it a height (let’s say 750 pixels). And let’s turn it into a grid. But THIS time, let’s set up our layout INSIDE a Grid. And no matter how we CONFIGURE our grid... we can define Grid areas (we just click the little plus to start defining a grid area). And this lets us define REGIONS of our grid that can hold content (in other words, we’re defining the individual PARTS of a layout). But the REASON this is important is because we can REUSE these entire layouts in other parts of our project.
But here’s the big thing. This layout? It’s part of the CLASS. In fact, we can rename this class “Example layout” (there are more clever options)...and we can apply it to ANOTHER element. So let’s add ANOTHER section underneath this one (of course, you could add this to ANY page in the project). And what do we notice? Well, nothing yet. We have to apply the Example layout class.
But NOW what do we notice? Its layout isn’t just following the same RULES, but also...it’s blank. So what if we add OTHER stuff to this layout? (These are ALL just div blocks with some stuff inside — again, we’re using plain old div blocks we sometimes call “magical” to serve as little CONTAINERS — containers that we put inside grid cells.) And what happens if we edit our grid? Is it unique? No. BECAUSE this is a reusable layout, we can define our areas and even REDEFINE our areas after the fact. And the layout throughout the project changes.
Put more practically? We can use AREAS to define entire layouts. That means a change on ANY ONE AREA will affect ALL Grids that are using that class. But THAT’S grid template areas.
Let’s finish up talking about responsive design. Grids are responsive by DEFAULT. BECAUSE the width of each column is usually sized with FRs, it’ll generally respect those proportions and the content inside. And as the browser gets narrower, everything will scale accordingly.
But if you want to change something in another view? Want to design for different devices? We can make that change. Even if we change the number of columns, and grid children set to auto? (If the children of a grid are automatically positioned?) They’ll wrap responsively just like you’d expect. Come back to desktop? Everything’s as it was.
That’s because changes cascade down FROM the base breakpoint, meaning when you change stuff on desktop, that affects tablet and mobile views. And things you add or change on tablet affect mobile. (There’s a pattern here.) Mobile landscape changes affect mobile portrait. And as we go down the different views, changes only affect smaller devices.
You will notice, though, that if you have something MANUAL? (If something’s set to manual position?) It can get stuck that way if you don’t TELL it what you want it to do on, for example, a smaller breakpoint. Even if you remove a column, if something was placed there manually, you have to either MANUALLY place it in a new column, or set its position to auto.
Now. One thing to note about manual position: if you’re repositioning an element VISUALLY on the canvas (if you’re moving it around in the Grid)? It has NO effect on the actual document order. Why is that important? Well, if you’re tabbing through or using a screen reader like VoiceOver, by default, it’s going to follow the order you see in the NAVIGATOR (the document order). With THIS element selected, notice how its position in the Navigator DOESN’T change, even though we’re moving it around using Manual position (by the way, this can apply to Grid Areas, too). And this is CRITICAL to keep in mind as you’re ORGANIZING content in a grid: make sure the ORDER (the way you want someone to INTERPRET your content) — make sure that’s set in the Navigator, THEN make visual adjustments as needed. Not only is this LOGICAL, and correct, and efficient, but it’s a step in the right direction for developing more accessible websites.
But that’s an overview of responsively designing with CSS grid.
So. Our two big takeaways: (1) grids serve as GUIDES (deleting a row or column doesn’t delete the stuff inside. And (2) grid cells usually only hold ONE thing at a time. So putting a DIV BLOCK inside a cell unlocks SUPERPOWERS...and lets us put other stuff inside that Div block.
So. Let’s do a quick recap of Grid. We can add a grid just like any other element. We can drop things in a grid and they’re automatically placed. They’ll fill up empty space... unless, of course, you set something to manual, in which case you can get that child to do anything you want. Like parenting. Except not at all.
We can span things and overlap things...we can create reusable layouts which, when we APPLY that class to other stuff, that layout carries OVER. And we can design responsively (taking a grid layout that might work GREAT on desktop, but maybe removing some columns on smaller views).
Now. We cover a lot more of this...like auto-fit, the dense setting in grids, designing for LARGER breakpoints, when to use flexbox versus when to use GRID — all of this is on Webflow University. So check that out if you haven’t already.
But that’s an overview of grid...in Webflow.