Top shelf web developer training.

Guided Paths

Follow our crafted routes to reach your goals.

Video Courses

Premium videos to build real apps.

Written Tutorials

Code to follow and learn from.

Find Your
Opportunity HIRED
Dismiss
Up

Build a Flexbox Grid with Less

Build a Flexbox Grid with Less

Related Course

Get Started with JavaScript for Web Development

JavaScript is the language on fire. Build an app for any platform you want including website, server, mobile, and desktop.

Today we are going to build a grid with flexbox, and you are either going to fall in love with flexbox or simply love it a little bit more once you see how easy it is to create and use a grid using flexbox.

Today I am going to use Less to create this grid just so we have a little more flexibility and also of course for the loops we will use to create to columns.

What we will be building

The grid we will be building here today will have the following specifications:

  1. Multiple breakpoints to be completely responsive and flexible in a variety of screen sizes.
  2. The ability to set each row as a column or a row by using flex-direction.
  3. A flexible number of columns, by default we will be creating a 12 column grid but you can change that at any time in the Less files.
  4. Responsive offset classes in order to allow anyone who uses this grid to add them depending on the breakpoint the browser is currently in.
  5. Hidden classes for each of these breakpoints.
  6. Configurable gutters and container width.
  7. Helper classes to help with various things like alignment.

By these points, you can see that we will create a grid that anyone can use and change for all their projects. That's mainly why I started coding Flexy, to have something to use everywhere even though the designs and spacing weren't always the same. What I will try to accomplish with this grid is something for every project, big or small, and at least in the Less community, I feel like it's something that's lacking. So if you thing this an awesome idea like I do let's get started.

Requirements

In this article, we will use Less to create our grid and because of that, you will need to install Node and Less.

To install Node you can either head over to their download page or if you have brew installed you can just open the terminal and install it with brew:

brew install node

After installing node you can install Less with npm (the package manager that comes with node). To install Less head over to the terminal and type:

npm install -g less

That's all we need to get started building our grid.

Why use Less?

You may be wondering why I am using Less over sass to create this grid. Well, Less has some great looping functionality that we will get into that makes it perfect to create grid system and any functionality that requires looping actually. I also feel like Less doesn't really get the love it deserves from many people so I'm attempting to change that and create a more advanced look at it so you can see all the functionality it has under the hood and maybe you'll start loving it too.

Starting our grid

In this tutorial, we will have the following folder structure:

We will also have a dist folder where we will compile our Less into one CSS file. For that task, I am using gulp and in order to install gulp and gulp-less please run:

npm install --save-dev gulp gulp-less

After this has installed you will need to create a Gulpfile (gulpfile.js) and create a Less task, like this:

var gulp = require('gulp');
var less = require('gulp-less');
var path = require('path');

gulp.task('less', function () {
  return gulp.src('./src/flexy.less')
    .pipe(less({
      paths: [ path.join(__dirname, 'less', 'includes') ]
    }))
    .pipe(gulp.dest('./dist'));
});

This will run our Gulp task to compile Less files to CSS. For more info on Gulp:

Using Gulp as a Build System Automate Your Tasks Easily with Gulp.js

Moving to the flexy.less file all I am doing in it is load all the other Less files:

// flexy.less

@import "_vars.less";
@import "_loops.less";
@import "_grid.less";

As soon as you create these files you can simply run:

gulp less

And our files will be compiled, of course for now it simply creates an empty file because we are loading empty files but soon we will be generating flexbox goodness in this flexy.css file. Now that all the setup is done we can start creating our grid and actually start writing some flexbox goodness.

The grid naming

One thing we still have to decide is what to call our classes in the grid and off course you can change this in your own grid but I decided to go in the simplest way possible:

<!-- index.html -->

<!doctype html>

<html lang="en">
<head>
     <meta charset="utf-8">
     <title>Flexy</title>
     <meta name="description" content="Flexy">
     <meta name="author" content="Scotch.io">
     <link rel="stylesheet" href="dist/flexy.css">
</head>
<body>
  <section class="container">
    <div class="row">
        <div class="col-6 col-l-4 col-m-5 col-s-12">
            <ul>
                <li>This Div will fill 6 columns when the screen is bigger than 1024px.</li>
                <li>Then untill the screen is bigger than 768px it will only fill 4 columns</li>
                <li>In screen sizes between 767px and 480px it will fill 5 columns</li>
                <li>For really small phones it will ocupy 12 columns</li>
            </ul>
        </div>
        <div class="col-6 col-l-8 col-m-7 col-s-hidden">
            <ul>
                <li>This Div will fill 6 columns when the screen is bigger than 1024px.</li>
                <li>Then untill the screen is bigger than 768px it will fill 8 columns</li>
                <li>In screen sizes between 767px and 480px it will fill 7 columns</li>
                <li>For really small phones this div will not appear</li>
            </ul>
        </div>
    </div>
    <div class="row">
      <div class="col-offset-4 col-4">
        <p>This element has an offset of four columns</p>
      </div>
      <div class="col-4">
        <p>This element has 4 columns</p>
      </div>
    </div>
  </section>
</body>
</html>

These two rows will give us a lot of room to play with our grid and test all the different behaviors it can have.

The first we are going to do is create our container and row classes and let's not forget that this row can also be a column so we need to take both these possibilities, so with that in mind we write:

//_grid.less

.container {
    width: @container-width; // Set the width to the one we will set in the variables
    display: block; // Reset the display
    margin: auto; // Always align it to the center

    // Set the directions for the row, columns and reverse versions of them using flex-direction
    .row {
        flex-direction: row; 

        &.reverse {
            flex-direction: row-reverse;
        }
    }

    .column {
        flex-direction: column;

        &.reverse {
            flex-direction: column-reverse;
        }
    }

    .row,
    .column {
        box-sizing: border-box; // Set to border-box for padding and borders to count as width
        display: flex;
        flex: 0 1 auto; // In here we set the flex-shrink so that our columns are never smaller then what we set
        // Then we are setting flex-grow to one to have them grow if needed and setting our basis to auto so it fills the space it has.
        flex-wrap: wrap; // Wrap the elements so that it doesn't overflow the container
        margin-right: @gutter; // Here we place the gutters that the user can customize
        margin-left: @gutter;
    }
}

As you can see we already have two variables in here that we want the person using this grid to customize themselves so let's start by creating the default variables in our _vars.less:

//_vars.less

@gutter: 20px;
@container-width: 100%;

Assuming from this idea the user can now control the width of their container that will always be aligned to the center because of the margin setting and he can also set the gutter size depending on how much he wants these gutters to take on the grid.

Creating our loops

Now we are going to start with the fun part of our grid, let's start creating the loops that will dynamically create our classes.

Let's start simple and create the first loop, this one will create the main columns, by main I mean these will be the columns that will work no matter the screen size.

For that, we need a loop that takes one argument that we will call counter and this counter will be the number of columns our grid will have. What this will do is loop through the code we pass him when it's called. What I mean by this is if we have a 12 column layout this code will run 12 times and what it will do is create the class names we need and set their width.

The code needed for this is:

//_loops.less

// Call this loop when the counter is bigger than 0
.generateCols(@counter) when (@counter > 0) {
    // In here we define the width 
    // and this will be the number of the column we are in divided by the number of columns we have.
    // Imagine this is column 6 and this will give us 0.5 and if multiply it by 100 we will get 50%
    @width: (@counter / @cols ) * 100;
    // Prepend the number of the column with col- to get our class
    .col-@{counter} {
        // Set flex-basis and max width to that value
        flex-basis: ~"@{width}%";
        max-width: ~"@{width}%";
    }
    // Decrease the counter by one so we don't have an infinite loop
    .generateCols((@counter - 1));
}

The loop is done but we still have to call it in order for the classes to be created and for that let's first add another variable to our _vars.less file:

//_vars.less

@cols: 12;
@gutter: 20px;
@container-width: 100%;

All that's left to have to do in order to have our main columns is to actually call this loop with our default column number:

    // _grid.less

    [class^="col-"] {
        box-sizing: border-box; // Se to border-box for padding and borders to count as width
        // Set flex-grow and shrink to 0 so that these columns always have the size we tell them in the loop
        flex-grow: 0;
        flex-shrink: 0;
        padding-right: @gutter / 2; // Set paddings to half the gutter for a little spacing
        padding-left: @gutter / 2;
    }

    // Call our loop
    .generateCols(@cols);

Let's look at this code, shall we?

The first thing I did is select all the elements that have a class that starts with col- and add the default styles that will apply to every column. After that, I called the generateCols loop and pass it the @cols that in this case will be 12 and this will generate all our 12 classes.

If you have been coding along you will see that our columns work and in the browser, you will see something like this:

We have our column classes done and now for this main loop we still need to generate our offset classes so let's just add these lines:

// _loops.less

// Loop for normal cols
.generateCols(@counter) when (@counter > 0) {
    @width: (@counter / @cols ) * 100;
    .col-@{counter} {
        flex-basis: ~"@{width}%";
        max-width: ~"@{width}%";
      }

      // After our main columns
      // add this to create our offset columns
      .col-offset-@{counter} {
        margin-left: ~"@{width}%";
      }
 .generateCols((@counter - 1));
}

Now if you compile the code by running gulp less and open up our index.html you will see something like this:

So now all our main classes are done and so are our offset classes.

Our grid is functional now but if you try to resize the page you can see that we don't quite get the responsive classes working only the main ones and we will get into creating those classes and some other helper ones in the next part of this article.

Conclusion

In this part, we already got a look at some of the looping functionality that Less offers to aid in the creation of grid systems and when we come back to create the rest of our grid you will see just how much we can do with these loops and with Less in general. Stay tuned for the second part.

Sara Vieira

Sara Vieira is a Front-End Developer for Mindera in Portugal with a passion for everything front end related. She is also a drummer and a big time TV Show addict.