Creating A Quick Grid System With Flexbox
Tags: css, tutorial, beginners, webdesign
Published: 2021-10-06 01:07:13

Greetings, Earth-things!

Today, I'm going to show you how to create a flexible grid system using Flexbox! Flexbox is pretty well-supported across pretty much **all the browsers** (except for some quirks in IE11, offfff course), so this should work even where `display: grid` does not!

As a bonus, this demo will allow you to add or remove cells from the grid with a click!

## First, let's set up our environment

I'm using two fonts from Google's Font Library, *Open Sans* and *Dosis*. Let's set up their import statement first:

### Code:

```css
@import url('https://fonts.googleapis.com/css2?family=Dosis:wght@200&family=Open+Sans&display=swap');
```

We'll be using two custom properties later, so let's set them up at the top of our CSS code, just below the import above:

### Code:

```css
:root {
  --border: rgba(255, 255, 255, .2);
  --page-color: rgb(235, 235, 235);
}
```

As always, I like to do things with a little style. For the background, I'm going to use a nice gradient, and disable padding and margins on the body.

### Code:

```css
body {
  background-image: linear-gradient(rgb(135, 35, 135), rgb(75, 135, 195), rgb(35, 48, 135));
  background-attachment: fixed;
  background-size: cover;
  color: var(--page-color);
  font-family: 'Open Sans', sans-serif;
  font-size: 18px;
  letter-spacing: .135ch;
  margin: 0;
  padding: 0;
}
```

## Next, let's include a little description of what we're building (Optional)

We'll need a heading (`h1`) and a `section`:

#Code:

```html
<h1>
   flexi-grid demo
</h1>
<section class="description">
   Hi! This is a little demo of a
   simple grid system usingFlexbox!
   You can add a new box to the
   grid by clicking on the "+", or
   remove a cell by clicking on the "-".
</section>
```
And then we'll style them:

### Code:

```css
h1 {
  color: white;
  display: flex;
  font-family: 'Dosis', sans-serif;
  font-variant: small-caps;
  justify-content: center;
  letter-spacing: .235ch;
  margin: 5vw 0 2.5vw 0;
}

.description {
  align-items: center;
  background: rgba(85, 85, 85, .2);
  border-radius: 8px;
  box-shadow: 0 8px 18px rgba(0, 0, 0, .3);
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  line-height: 4ch;
  padding: 3.5vw 7.365vw;
  margin: 0 15vw 5vw 15vw;
  text-align: center;
}
```
You should end up with something like this:
![A screenshot showing the heading and description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60u7282tko5053pye07p.png)

## Now, let's build the container

The container itself is invisible, but it's one of the most critical components of our grid system. It holds the cells and tells them how they should be laid out.

Fortunately, it's pretty easy to set up. First, let's add a `main` element to our HTML:

### Code:
```html
<main class="flexi-grid" id="grid">

</main>
```

You'll notice that I've included a class, `.flexi-grid` and give this element an ID, `grid`. These attributes will be critical to the rest of this tutorial, so make sure to include them.

* The class `flexi-grid` will be used to define our grid system.
* The id `grid`, will be used to target this element via JavaScript.

Let's go ahead and set up the CSS for our grid container:

### Code:
```css
.flexi-grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  padding: 0 .5vw;
  width: 100%;
}
```

### Some things of note:
* Within this declaration block, we've set the `display` property to `flex;` which tells the browser to use the [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) system for this element.
* Next we've set the `flex-flow` property to `row wrap`. This covers two properties in one go: `flex-direction`, and `flex-wrap`. Later on, we will change this property to `column`, for smaller screens.
* Setting the property `justify-content:` to `flex-start;` tells the browser to align our grid cells toward the beginning (left side) of the row.
* I've padded the container to align its contents to the centre. By using the appropriate value in view-width (vw) units, we can have this done automatically.

## Creating the grid cells
With our container in place, we need to actually add some cells to the grid to make it... you know... a grid. To achieve this, we'll create a new class, `flexi-cell-25`\*.

---

**\*** We can add grid cells of other sizes, but for convenience, and the purposes of this tutorial, we're sticking with quarters.

---

### Code:

```css
.flexi-cell-25 {
  border: 1px solid var(--border);
  box-sizing: border-box;
  margin: .5vw .5vw;
  height: 23.5vw;
  width: 23.5vw;
  box-shadow: 0 3px 12px rgba(0, 0, 0, .3);
}
```

### Some things of note:
* We're using the custom property we defined earlier, `--border`.
* `box-sizing: border-box;` ensures that our grid cells are not affected in terms of overall size, by either their borders or their padding (should we choose to add it).
* For the `margin`, I'm using the same value as the padding used by the container. This maintains (proportionally) even spacing regardless of screen dimensions.
* `height:` and `width:` are not set exactly to `25vw`. This is on purpose. For the purposes of this tutorial, I actually want spacing between each cell, but still want each cell to take 1/4th of the screen width, and the same height. If you want to give each cell the same width, but adjustable height, you could replace `height:` with `align-self: stretch;`.

To see how these grid cells look, add the following to `main`:

```html
<div class="flexi-cell-25">

</div>
<div class="flexi-cell-25">

</div>
```

---

At this point, we should have a page that looks like this:

![A screenshot of the demo up to this point](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qwdv9zwuzw1d3u20yeh.png)

---

## Bonus: Add and remove buttons
We've technically completed our grid system, but we're going to extend it a bit by adding `add/remove` buttons.

### Our HTML Code:

Within `main`, we'll put the following, adjusting what we had before:

```html
<div class="flexi-cell-25 flexi-grid-new" onclick="newCell()">

</div>
<div class="flexi-cell-25 flexi-grid-remove" onclick="removeCell()">

</div>
```

### Our embedded JavaScript Code:
At the bottom of the file, we'll add this script:

```html
<script type="text/javascript">
   var grid = document.getElementById("grid")

   function newCell() {
      let cell = document.createElement("div")
      cell.classList.add("flexi-cell-25")
      grid.appendChild(cell)
   }

   function removeCell() {
      grid.removeChild(grid.lastElementChild)
   }
</script>
```

### Some things to note:
* We're pulling from the `id` of the grid container, because using `querySelector()` stops us from being able to use `appendChild()` (it apparently returns a string and causes an error).
* Placing `cell` outside `newCell()` (as a global variable) does not work. Ensure it's within the function.
* You can make `newCell()` more versatile by passing the class to add to new cells as an argument. You can try this on your own.

### Finally, let's style our add/remove buttons:

```css
.flexi-grid-new, .flexi-grid-remove {
  border-style: dashed;
  position: relative;
}

.flexi-grid-new::after {
  content: '+';
}

.flexi-grid-remove::after {
  content: '-';
}

.flexi-grid-new::after,
.flexi-grid-remove::after {
  align-items: center;
  bottom: 0;
  display: flex;
  font-size: 5ch;
  justify-content: center;
  left: 0;
  opacity: .35;
  position: absolute;
  right: 0;
  top: 0;
  transition-duration: .735s;
}

.flexi-grid-new:hover::after,
.flexi-grid-remove:hover::after {
  opacity: 1;
  transform: scale(1.35);
}
```

### Some things to note:
* I've combined definitions wherever possible, to avoid duplication.
* Rather than wrangling with the position of the text, I've simply let the overlays (`::after` pseudo-elements) take up the full space of their parent elements, and used 
Flexbox properties to position them in the centre.

---

##That's it!
That's about all there is to it! You can play around with this tutorial and see what you can come up with. If you do, feel free to share your creations with me!

You can view the source code here: [https://codepen.io/rolandixor/pen/rNwEgPb](https://codepen.io/rolandixor/pen/rNwEgPb)