The Problem

Implementing a grid layout can quickly turn into a tricky task. If you have grid items that are always the same height, then you can probably make do with a Flexbox grid or some other CSS grid implementation. However, if you’re dealing with user-generated content, chances are, you don’t have the luxury of equal height components. One longer or shorter component would either stretch the other components in its row, or leave some unpleasant whitespace at the bottom of the row. All of a sudden, our beloved CSS grid has become insufficient.

The Solution

The situation might seem dire, but all hope isn’t lost. We just need a little Javascript assistance. Magic Grid is a JS library that makes it super simple to create grid layouts. I’ll go into excruciating detail about how it works but first, we should remember a few things.

Absolutely positioned elements are taken out of the regular flow of their container.

An element with absolute positioning will be positioned relative to its closest, relatively positioned parent.

We can move an element around by setting a value for the “position” attribute, and manipulating the values of the “top” and “left” attributes.

Using these facts, we will manually position each item in the grid. Let’s get to it then. The first thing we need is a grid class. This class will contain methods that will initialize and manipulate the grid. The following properties are defined for a grid.

containerClass [String]: Class or id of the container

Class or id of the container container [Dom element]: Actual container element

Actual container element items [Dom elements]: The items in the grid

The items in the grid static [Boolean]: Is the grid content static?

Is the grid content static? size [Integer]: number of items in the grid

number of items in the grid gutter[Integer]: Space between elements in px

Space between elements in px maxColumns[Integer]: Maximum number of columns

Maximum number of columns useMin[Boolean]: Append next element to the shortest column?

Append next element to the shortest column? started[Boolean]: Has the grid been initialized?

Let’s have a look at the constructor:

The last line of the constructor calls the init() function, which initializes the container element and its items. Before I show you that function, we need a way to know if every item in the grid is present. For this, we create a “ready” function:

For static content, the grid is always ready because every item is always present in the container. However, if you’re fetching data from an api and rendering with a frontend framework, there might be a slight delay before all the items are present. In that case, the grid is considered ready when the number of items in the container is equal to, or greater than, the expected number passed in through the constructor.

Now we can write the initialization function.

We’ve done a couple of important things here. First, the container must be relatively positioned to make sure that the items stay within the grid. Second, every item in the grid must be positioned absolutely. This places each item in the top-left corner of the container (0, 0).