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:
- Rachel Andrew’s site contains video tutorials and layout examples.
- Jen Simmons created the Layout Land video series and also has gathered together everything you need to learn CSS Grid.
- Stacy Kvernmo has a collection of pens using CSS Grid.
- Jules Forrest has some beautiful responsive layouts on CodePen.
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
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.
- 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
vwto 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
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 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.
The above example uses
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);
In the above example the distortion is applied to a sub-grid creating a distorted affect consistently over several cells.
- 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.
3. Isometric layout
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.
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.
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.
- 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
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:
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.
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
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.
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).
- 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 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
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.
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.
- 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:
- 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.
Masonry style layout with CSS Grid
D3 and CSS Grid with expanding content
Combining D3 and CSS to create a flexible content grid with expandable content and sorting. Spoiler alert: Completed…