How to Build React Grid Layouts With Custom Column Numbers
Having a column-based grid system to lay our elements out on is very useful, which is why Bootstrap and other CSS frameworks are built on that model. In this lesson, you will learn how to build the Columns primitive and its helper the Column to build your custom column layout.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Composing Layouts in React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Composing Layouts in React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:13] What's up guys Travis here with another lesson in composing layouts in React. In this lesson we are going to learn about the columns and column primitives.
[00:14 - 00:23] Bootstrap and other CSS frameworks were revolutionary. They perfected the X-Colon grid systems to create layouts just by doing a little math.
[00:24 - 00:39] Although we are fortunately no longer dependent on these X-Colon grid systems as our universal layout, it is still a helpful way to layout items. However with the column primitive, we are no longer bound by 12 or 24 column systems.
[00:40 - 00:53] Instead we can set 5 columns or 13 columns or any other number we need. In this lesson we are going to build out the form part of the previous widget.
[00:54 - 01:08] Now similar to the split and stack components we need consistent gutters, this time we need to apply them between both the column tracks and the row tracks. In addition to this we need to layout the input fields across multiple column layouts.
[01:09 - 01:19] Ok so let's start with some basic markup. And as always, you follow along with the code sandbox starter that I have linked in the notes below.
[01:20 - 01:37] So we are going to want to import React from React. And in this case we have this component called formgroup.
[01:38 - 01:59] And that is in a file over here called formgroup. You don't really kind of be on what we are trying to focus on in this course but it is more to know it is just basically a div with a label and it allows you to put any input you want and set to it.
[02:00 - 02:11] So with the power of copy and paste let's go ahead and pull that in here. And this is exactly where we left off in the last lesson.
[02:12 - 02:42] So in the last lesson we take two. Ok guys, so let's start off with some basic markup.
[02:43 - 02:51] Once again we are using the starter with the link in the notes below if you want to follow along. And this is pretty much where we left off.
[02:52 - 02:59] We had this form component that was being used by the app. Now we are going to actually go ahead and build this component out.
[03:00 - 03:11] And we are going to import React from React. We are going to import a component called formgroup.
[03:12 - 03:23] That is this version where we have actually pulled this formgroup component out into its own file. It is really not important as it is implemented but you can go look at it if you would like.
[03:24 - 03:37] And that is in the formgroup file. Now let's go ahead and copy and paste for my notes here.
[03:38 - 03:44] And this is where we left off in the last lesson. Now so far we started with the stack component.
[03:45 - 03:52] We just did display grid and we set some gap. Then we added some columns with a split.
[03:53 - 04:01] So let's kind of get that, let's get it to where we were with the split a little bit. So we are going to import styled from styled components.
[04:02 - 04:19] And we are going to create a component called columns equals styled.div. Before we add it let's just go ahead and preemptively put that around our component.
[04:20 - 04:39] So yeah when we built the split we did display grid and we did a gap. In this case we did props.
[04:40 - 05:01] We need our spacing map. Then props.gutter otherwise it would default to spacing map.lg.
[05:02 - 05:09] We need to bring that in. So let's import that in.
[05:10 - 05:30] That's good. And then with the split we'd say grid template columns.
[05:31 - 05:43] And we just did 1FR to do a ratio of 50/50 split. Let's go ahead and put that semi colon.
[05:44 - 05:49] Everybody misses a semi colon sometimes. And yeah that creates a two column split.
[05:50 - 06:09] Now as we learned when we were making the split if we want to make 3, 4, 18 columns that would get pretty ridiculous if we had to get 1FR, 1FR over and over and over again. So luckily there is a function that we can use called repeat.
[06:10 - 06:18] And it helps to spell it right. I don't know why I did that.
[06:19 - 06:27] And in here we can say I want 6 columns of 1FR. And this will give us 6 equal columns.
[06:28 - 06:40] Now whatever we put in here, let's say we only wanted 3 columns as we give us 3 equal columns. But what it does is it repeats 3 times whatever we put in here.
[06:41 - 06:55] We can pass multiple values. So if we wanted to alternate every other column to be 100 pixels to 200 pixels and we want to do that 3 times, this is what we do.
[06:56 - 07:08] And you can see we have 6 columns in all but 3 times it repeats this 100, 200, 100, 100, 200 pattern. So that's pretty cool.
[07:09 - 07:21] But in this case the layout we're looking for has 6 columns. Now the other thing we need to do is we need to span multiple columns.
[07:22 - 07:44] And that's where we're going to create a complementary primitive called the column component. And this column component, see there's a property in grid that we can put on the children itself.
[07:45 - 07:58] That let's us say, hey, I know I want to change my defaults. Instead of me being spanning 3 columns, I want to span.
[07:59 - 08:10] Sorry, instead of me spanning 1 column, I want to span 3 columns. And once again, this is doing it like this is going to break the properties of encapsulated CSS.
[08:11 - 08:24] Okay, we're going to expose this via props, which doesn't break encapsulation. So we have this columns, it's taken up 6 that creates 6 column tracks.
[08:25 - 08:32] And then we want to let's just set it for 3 columns like this for now. And once again, let's copy and paste.
[08:33 - 08:45] I'm just going to redo this. And what we've done here is we've wrapped each of these form groups in a column .
[08:46 - 08:59] And what this, because we set it to 3, this is going to create kind of that split effect again, because we have created 6 individual columns. But we're telling each form group to span 3 columns.
[09:00 - 09:16] Now obviously this doesn't work well if we're going to hard code these values. So let's go ahead and let's create a prop, let's use a prop called columns, where we can set the number of columns.
[09:17 - 09:28] And in fact, what I'm going to do here is I'm just going to take that value columns, we're going to destructured off of props. Oops.
[09:29 - 09:41] And we're going to give it a default value of 1. And we can just return that, because we know that this will have the right amount of columns.
[09:42 - 09:51] So what this says is, hey, grab the columns prop, give it a default value of 1 if nothing's provided, and then just return it. And that's the value that we'll be using repeat.
[09:52 - 10:02] And then we can come in here and go columns equals 6. And now we fix that issue.
[10:03 - 10:14] The other one we want to do is that same thing for the span function. So I want to do pretty much do this.
[10:15 - 10:27] Now instead of the columns prop, we probably want-- we would maybe want to do something like span, right? And not span, span.
[10:28 - 10:34] And that would make a lot of sense. The only problem is span is an HTML attribute.
[10:35 - 10:49] And if we're not using it, this gets-- basically the span will get sent all the way down to that div, and it can cause layout problems. So what we're going to do is we're going to use a dollar sign.
[10:50 - 10:57] Oops. This dollar sign is a convention used in static components, but it's also just a good convention period.
[10:58 - 11:19] And it says, hey, this is a property that I want to use when creating my CSS, but I don't want it to flow all the way down to the HTML element itself. So once again, let's recreate this entire thing.
[11:20 - 11:29] Let's add all those spans in. Now these ones we did want to split, so we're going to set those explicitly as three columns.
[11:30 - 11:46] The email group, though, we wanted it to go a little bit longer, so that's four columns. The street address, we want to take up an entire row, so that's six columns, and then two columns for the final three input groups.
[11:47 - 11:56] And this is the layout we want to achieve. And we could stop here, but there is one problem, you probably didn't even recognize it.
[11:57 - 12:16] But what happens if we define, if we're trying to span more columns, then we actually have set in our columns track, we start getting some weird layout. Like you start seeing things that start looking off and it doesn't look right.
[12:17 - 12:38] Because the reason is because we're trying to tell this form group to span three columns, but there's only two column tracks. So what we need is a way to span three columns, if we can, but don't span more than the amount of columns that are up here.
[12:39 - 12:55] And so to do that, what we're going to do is we're going to do just a little refactoring here. We're going to take this out, and we're going to put this in a CSS custom property called columns.
[12:56 - 13:20] Now, if you never use CSS custom properties, sometimes called CSS variables, is basically a property like display, get, grid that you can set, you can give it a value, and then pull that value out whenever you need it. So only like limitation is all your properties have to start with that double dash.
[13:21 - 13:47] And then if you want to pull the value out, you just use the var function and pass in the name of the column, sorry, the name of the custom property you want. So now we've re-factored to pull this repeat value, gets it from columns, and the columns is set using our string interpolation function that we pass into style components.
[13:48 - 14:02] Oops. Now, the reason why we do this is because now that we've set it as a custom property, this property is available to this or any of the children technically.
[14:03 - 14:15] So now we're going to then take advantage of a function in CSS called min, where it does it. Oops, not min block size, just min.
[14:16 - 14:28] And min will give you back whichever value ends up being less. What's really cool is you can do something like 50% and 500 pixels.
[14:29 - 14:40] And this will return back whichever is smaller, so if 50% happens to be 502 pixels, it will still give you 500 pixels. But if it gives if it is less, then it'll give you 50%.
[14:41 - 15:00] I'll just need to do some cool logic on variable with or things that that may change on you. So what we're going to do is instead of just straight up using the span, we're going to wrap in a min, which is cool.
[15:01 - 15:12] So now we have the span in the first value that we're going to give. But then the second value, we're going to use the Varky word and passing columns.
[15:13 - 15:34] And this will give us this value up here. So if we pass in a span of three right here, but the columns is set to two, then the amount of columns that it spans will only be two because two is less than the amount we passed in.
[15:35 - 15:43] And as you can see here, that's what's going on here. Everything that we passed in was either two or two or more.
[15:44 - 15:55] So everything is taking up the entire row. Now if we were to go to four columns, for example, I have to save that.
[15:56 - 16:01] I'm refresh. Sometimes the hot reloading gets stuck.
[16:02 - 16:05] Here we go. You can see the, we've set this to four columns.
[16:06 - 16:11] This is spanning three. So there's an extra column left, but the email was already set to four.
[16:12 - 16:21] So it takes up the entire amount. The street address was set to six, but because it's not going to max out more than four, it just takes up the entire width, just like email.
[16:22 - 16:33] So that's, that's just a good safe way to, that this column prop will not do unexpected things if we use it wrong. And there we go.
[16:34 - 16:37] We could end it right there. It'd be totally perfectly fine.
[16:38 - 16:46] Now the, and in fact the, there's a link to this code sandbox. Well with the final code at the end of this lesson.
[16:47 - 16:53] Now there's also a link to another code sandbox that I have out there. And it addresses the issue of responsive design.
[16:54 - 16:59] Because the question is, what do we do when we get to like really small screens ? What do we do to adjust?
[17:00 - 17:21] And there's some different strategies you could follow. There is one strategy that I've built directly into the layout primitives at Bedrockle layout that allows it to switch when the actual width, not the viewport, the width of the element, the, the parent container changes to be below the threshold that I give it.
[17:22 - 17:26] And it'll switch to a stack layout at that point. It's really kind of cool.
[17:27 - 17:36] It's implemented using resizer, resize observer. And if you want to see how it's implemented, you can go over to code, sorry, to GitHub.
[17:37 - 17:44] And look under packages. And there is the split and well as the columns components.
[17:45 - 17:56] And you can see how those are implemented. So that we've learned how to make the columns primitive today, which is excellent for setting the number of column tracks.
[17:57 - 18:05] And we also learned about setting the column primitive. Now sometimes we have a layout where we don't know in events how many columns we want.
[18:06 - 18:19] We just want to use as many columns as possible without going below a minimum width for each of our items. And to do that, that's when the grid primitive really shines.
[18:20 - 18:22] And we're going to learn how to build the grid primitive in the next lesson.