Stretching the Grid — 6 fun ways to use CSS Grid

I’ve been playing with CSS Grid a lot recently. It is a great new enhancement to CSS and makes creating layouts super easy. There are lots of great tutorials on how to use it and lots of cool examples of layouts created using it. I would recommend the following:

I was interested in how you can stretch the Grid implementation a little to make something unusual and here I’m going to show you examples I came up with.

But first a disclaimer: I’m not a professional coder and you may look at some of the code and think there is better way of doing it. Any comments, positive or negative, are gratefully received and if you see a better way of creating any of these effects I’d love to hear about it.

1. Isometric layout

Create an isometric layout by placing skewed grids on top of each other

Square grids are great but it is easy to skew a grid by 30 degrees using CSS: transform: skewY(-30deg);

And once you have one grid you can place another on top of it skewed 30 degrees in the other direction: transform: skewY(30deg);

And finally place a third grid skewed and rotated: transform: rotatez(-60deg) skewY(30deg);

Once you’ve got your row heights right and ensured they line up you have an isometric grid onto which you can place content as demonstrated in this CodePen:

Once you’ve set up your 3 grids you can place text, images and videos wherever you like to create your isometric layout.

You’ll like it because:

  • Pure CSS, no need for any JavaScript
  • Easy to make responsive.

Watch out for:

  • The z-index of the content will depend on the grid it is placed in so if you are going to overlap content you will only be able to layer it in an order determined by the grids. So choose wisely which grid is displayed on top.
  • The third grid needs to be much larger than the display area, so working out the correct column and row to place content is tricky. I used a process of trial and error and working out the location relatively to already placed content.

I wrote a post explaining all the details of how to set up the isometric grid.

2. Use the grid as a mask

Use grid to place content over a full background image.

It’s very simple to use the grid to create an interesting mask over a background image. I created the example above after seeing this striking poster.

However Jen Simmons, master of grid, had already got there with a layout placing content over a full background image.

Add a background image to your page and then place a grid over it. With Jen’s version you simply need to specify the column and row placement of your content.

If you want a fuller mask, like my example, you are going to need to place content in every grid cell and give it an opaque background. Even for the “holes” I needed to place content with a border or outline in order to maintain filled “rails” between holes. See the below CodePen for the details:

You’ll like it because:

  • Pure CSS, no need for any JavaScript
  • Easy to make responsive.

Watch out for:

  • You’ll need to place content wherever you want the mask to be opaque. This means you will be creating lots of empty content.
  • Make sure the grid extends the full length of your background image even if your content doesn’t.

3. Add some perspective to your content

Use perspective transform on grid content to give an interesting 3D effect.

Once you’ve used a grid to layout your content why not use some CSS transforms to make it more interesting?

Here I added perspective and some Y-rotation to give a 3D effect: transform: perspective(1000px) rotateY(30deg);

With this particular layout it got a bit complicated because I wanted to make it responsive whilst maintaining the order of the content and this meant the styles needed to be applied differently depending on the number of content items in the row. (Specifically whether there was an odd or even number).

In the end I had to resort to some JavaScript to solve this so if anyone has a neater CSS-only solution I’d be excited to see it. The details of my solution are in the CodePen below.

Using just one transformed element within a design:

You’ll like it because:

  • Easy to make responsive.
  • Can be used on dynamically populating grid content without needing to specify style individually to each content piece.

Watch out for:

  • In this example the difficulty arises in the alternating styles for each row. The first item in each row should have the alternate style to the first item in the row above. This gets difficult when the number of items per row varies.
  • You could make a version of this specific layout without JavaScript if you restrict the number of items per row to always be an odd number.

4. Morphing/zooming an image

Playing with the size of the rows and columns of a grid

This one may not have any practical value but it is fun.

I’ve placed each part of an image in a square cell within a grid. Then using JavaScript I change the height/width of the rows/columns on mouseover. The result is an image that morphs as the user moves the mouse, some cells shrink whilst other get larger distorting the image within them.

The first version I made was just a toy to enjoy distorting a face having created 25 individual images for each part of the larger image. You can play with it and see the details of how it was built in this CodePen:

In an attempt to find a use for this functionality I then made a version with a more detailed image. The idea being that the user can zoom into the image by mousing over the part they are interested in. That part will be enlarged (and distorted) whilst other parts of the image shrink.

This version also requires just one image to be created and the correct placement of the image in each cell is done with JavaScript. See the functionality and code in the CodePen below and if you can think of any suggestions for a practical use of this functionality please leave a comment.

You’ll like it because:

  • It’s fun.

Watch out for:

  • The first “face” example uses an image that has been manually chopped into 25 smaller images in my favourite graphics program. The second example is better in that no pre-preparation of the image is required.
  • On mouseover I change the value of “grid-template-rows” and “grid-template-columns” based on the distance of the mouse from the centre of the grid cells original position. The calculation I used gives a reasonable effect but isn’t very consistent. When the mouse is nearer the edge of the image the zoom is greater than when it is in the middle. To make a more consistent zoom functionality I would need to think a bit harder.

5. Masonry style layout

Tiled layout dynamically adjusting to rearrange different size elements.

CSS Grid wasn’t intended to be able to produce a Masonry style layout but inevitably people have asked whether it is possible. The short answer is no, not on it’s own. But if you are happy to add just a little bit of JavaScript (my version is just 25 lines) then you can come up with something pretty good.

CSS Grid already does an excellent job of taking content blocks and organising them into a grid and densely packing them so that there is as little empty space as possible. The problem is that each cell in a row is the same height and the row grows to fit the tallest cell.

The solution is to use a small row height and have each content block span several rows, as many as it needs for all the content to fit. This way all the content blocks are different heights and Grid happily rearranges them to fit together without spaces.

For the solution when all content blocks are the same width check out this CodePen:

Equal width content blocks fit perfectly in a grid.

You can still achieve a pleasing result with varying width blocks but you will have a few gaps in the grid. I’ve written a post detailing the whole approach (which has several examples showing different configurations).

You’ll like it because:

  • Masonry is a pretty popular layout for large numbers of irregularly sized content blocks.
  • The resizing of the blocks is dynamic so you can add more blocks without having to specify CSS values for them individually.
  • CSS Grid handles responsiveness beautifully, a layout which increase the width of each column until there is enough room to add an extra column is very simple to implement.

Watch out for:

  • The JavaScript resizes each block to fit the content within it. I run this on page load and again whenever the page is resized as the column widths may have changed, and in turn the height of the content. I also resize each block when all images within it have loaded using the imagesLoaded.js library.
  • The height of each block can’t be any possible value but instead must fit to the underlying grid. So if you set your row heights to 20 pixels and row gaps to 10 pixels the height of each content block will be 20S+10(S-1) where S is the number of rows the block spans. This means you will get some whitespace at the bottom of your content blocks. Play with the row height and gap values to reach a happy compromise.

6. Opening content

A grid of content, click on one to expand and show further details.

CSS Grid is excellent at taking a lot of content in a variety of sizes and sorting it into a densely packed grid. I did this with all the characters from Game of Thrones but I wanted to enable the user to click on a content block and expand the content show more information.

The expanding of the content is easy. The JavaScript applies a class to the clicked cell that sets the grid-column-end and grid-row-end to new, larger values and hides/unhides parts of the content.The difficulty occurs because of CSS Grids packing algorithm. If you change the size of a cell you may find that Grid decides it should go on a different row or column to maintain perfect packing. In the worse cases this means the content disappears off the bottom of the screen.

My messy solution was to calculate which column and row the unexpanded cell had been designated and explicitly set it there so that it didn’t move before expanding it. Then when it is closed these values are unset and it returns to a place in the grid automatically.

It isn’t very nice code but it works as you can see from the CodePen:

I wrote a post about making this example.

You’ll like it because:

  • The expanding of content in place without needing a pop-up or overlapping other content is visually pleasing.
  • All the other nice aspects of Grid are maintained so your design can be responsive and it can handle as many new content blocks as you add to the end of the grid.

Watch out for:

  • The JavaScript is pretty ugly. I’m trying to work out the current column and row for the cell from its pixel location within the grid and comparing this with the settings for the row and column dimensions and gaps. The more irregular these values are, the harder it will be to do this calculation. If only you could simply return the column and row position of automatically placed cells…
  • When opening a new cell, the previously opened cell doesn’t necessarily return to its original place in the grid. It might jump to a new place where it best fits the packing structure. This would be not so likely to happen if all the closed cells were the same size.

That’s it for now!

Congratulations for making it this far. I’ll add more content if I come up with new unusual ways for using CSS Grid. Please leave me a comment, especially if you see something that could be done more easily than I am doing it here.

I gathered all these experiments plus a few extra examples into this CodePen collection.