Stretching the Grid — 6 fun ways to use CSS Grid

Andy Barefoot
11 min readNov 25, 2017

--

I’ve been playing with CSS Grid a lot recently. It is a great enhancement to CSS and makes creating layouts super easy.

The intention of this article isn’t to teach CSS Grid. There are lots of excellent tutorials and lots of cool examples of layouts created using it. If you haven’t yet seen any CSS Grid examples or want to learn how to get started with it I would strongly recommend the following:

Having used these great resources myself to get going I was also inspired to play with the Grid implementation. The experiments below are the results of this playing and with each example you will find a link to CodePen where you can see the code and experiment with it yourself.

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. Use the grid as a mask

Reveal key parts of the background image with a grid mask: CodePen

I created the example above after seeing this striking poster.

If you place a grid over an image it’s easy to mask parts of the image by placing content in the grid. In the example above I used a full-width grid to obscure a background image exposing parts of it by leaving cells of the grid empty.

However Jen Simmons, master of grid, had already got there with a layout placing content over a full background image. She has since produced a video explaining how she did it.

With Jen’s version you specify the column and row placement of the cells you wish to fill with content.

For a a fuller mask, like my example, its exactly the same only you are going to have to fill more cells, many of which with just an opaque background colour. Even for the “holes” I needed to place content with a border or outline in order to maintain filled “rails” between holes. See the CodePen for the details.

Tips:

  • Easy to make responsive by setting the grid and background image to 100% width
  • To ensure the gaps line up with the background image the same for all screen sizes use vw to size the columns and rows.
  • To add a more random alignment let Grid add more columns as the page gets wider.

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.

2. Add some perspective to your content

Adding some distortion effects to an otherwise standard list: CodePen

Although the Grid produces rectangular cells in aligned rows and columns you can apply transformations to the content of the grid cells to make things more interesting.

Here I added perspective and some Y-rotation to the contents of the cell 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.

Frank, Tommy and Ken all shared the same idea of what a comedian’s head shot should look like: CodePen

In the example above the layout alternates from row to row. As there is no way to support this in grid I instead created groups of 2 profiles with the first above the other. One style was applied to the first of the group and another to the second. This maintains vertically alternating styles even as the responsive layout displays more or less groups of profiles per row.

A straight-forward gallery of images given a 3D cube effect: CodePen

The above example uses transform: skewY(30deg);and transform: skewY(-30deg); alternatively to distort the individual cells in the grid. To ensure there is always an odd number of images per row whilst maintaining a responsive approach of adding more images to the row as width allows I used: grid-template-columns: repeat(auto-fill, minmax(150px,1fr) minmax(150px,1fr)) minmax(150px,1fr);

Using transformations on a sub-grid within a design: CodePen

In the above example the distortion is applied to a sub-grid creating a distorted affect consistently over several cells.

Tips

  • Easy to make responsive using the grid-template-columns: repeat(auto-fill, minmax(150px,1fr)); pattern. See Rachel Andrew’s video for an excellent tutorial.
  • Can be used on dynamically populating grid content without needing to specify style individually to each content piece.

Watch out for:

  • In the first 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.

3. Isometric layout

Content arranged on 3 overlaid grids: CodePen

Its also possible to apply transformations to the entire grid. In the example above I have created three grids aligned on top of each other and applied different skews to each in order to create an isometric gris.

Grid 1: transform: skewY(-30deg);

Grid 2: transform: skewY(30deg);

Grid 3: transform: rotatez(-60deg) skewY(30deg);

I’m basing the grid sizing on vw so that I can be sure they line up as the window is resized.

Using Grid Inspector in Firefox reveals the 3 overlaid grids.

Once you’ve set up your 3 grids you can place text, images and videos wherever you like to create your isometric layout. The text and images will also appear skewed with the grid so there is no need to apply any additional transformations to the individual elements.

Combining the isometric grid approach with the mask technique: CodePen

Tips:

  • By basing the isometric grid on vw makes it easier to make sure everything is aligned even as the window is resized.
  • This does mean the whole content will resize with the browser. Creating a more responsive layout would be a challenge.

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.

4. Morphing/zooming an image

Using the grid to distort an image: CodePen

This one is less about creating an interesting layout and more about a fun effect that’s driven by manipulating the grid parameters.

As the user moves the mouse over an image placed within the grid the image distorts to the mouse position. The best way to understand is to play for yourself with the CodePen:

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.

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. If you can think of any suggestions for a practical use of this functionality please leave a comment.

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

Masonry style layout using grid: CodePen

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.

Grid Inspector in Firefox reveals how each block spans several thin rows.

JavaScript is used to set the row span for each block dynamically so that the solution supports multiple blocks without the need for manually calculating and setting the span for each. The code can be seen in this CodePen.

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).

Tips:

  • 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. Interactive expanding content

Grid elements can be expanded to show more content: CodePen

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.

Tips:

  • 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. If you found this interesting or helpful please applaud and I’ll add more content as I come up with more unusual ways for using CSS Grid.

Also please leave a comment if you’d like more details on any of the demos shown here or how to achieve the effects. And 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.

--

--