Roland Taylor
Posted on October 6, 2021
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:
@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:
: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:
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:
<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:
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:
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:
<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:
.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 toflex;
which tells the browser to use the Flexbox system for this element. - Next we've set the
flex-flow
property torow wrap
. This covers two properties in one go:flex-direction
, andflex-wrap
. Later on, we will change this property tocolumn
, for smaller screens. - Setting the property
justify-content:
toflex-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:
.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:
andwidth:
are not set exactly to25vw
. 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 replaceheight:
withalign-self: stretch;
.
To see how these grid cells look, add the following to main
:
<div class="flexi-cell-25">
</div>
<div class="flexi-cell-25">
</div>
At this point, we should have a page that looks like this:
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:
<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:
<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 usingquerySelector()
stops us from being able to useappendChild()
(it apparently returns a string and causes an error). - Placing
cell
outsidenewCell()
(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:
.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
Posted on October 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.