container – for the div that contains the items to be laid out
item – for items in the container
The important lines are the highlighted ones which set up the grid system.
Here is the output:
The grid system has fixed sized rows and each item should be placed in a specific row and column (though they may span multiple columns or rows). Therefore, CSS Grid cannot provide us with a masonry look, let’s try something us.
Multiple Items in a cell: I thought of having a grid with multiple columns and only 1 row, and then place multiple items in the same cell. Hoping that items would flow vertically one after the other but in grid items placed in the same cell overlap (see specs). z-index property can be used to control the ordering of overlapping items.
Use Case: – When all items are of the same size. – When item size is a multiple of a specific size. Items, then, can be spanned to multiple rows and columns based on their size.
2nd Attempt: Using Flex
Flex is a one-dimensional layout system with the ability to wrap items. This is in contrast to Grid which is two-dimensional.
Here is the CSS to create the desired layout using flex:
It is perfect now but unfortunately, it only works in Firefox.
Two tricks which make it work (albeit only in Firefox) are the following:
order – In flex, irrespective of the order in which items appear in the HTML, they are laid out based on their order property. We are using nth-child CSS selector to set the right ordering for 3 column grid.
break-before – This is the property which forces flex to break into the next column after certain number of items. break-before is only supported in Firefox.
4th Attempt: Using column-count
column-count is a CSS property which specifies how many columns an item should be divided into. It is commonly used to layout text in multiple columns (along with column-width). Let’s try to create a masonry layout with it.
display: inline-block property is important. Without it, the item may break and not display completely in one column.
Here is the output:
It looks perfect but has the same problem we had earlier with flex. The ordering of items doesn’t look right. Users expect the items to flow from left to right and then to the next row.
It is an improvement on flex through as we don’t have to set the height of the container and it uses all the available columns first, rather than filling up the first column.
Use Case: When the ordering of items is not important.
We came quite close to creating a Masonry layout with pure CSS. All these layouts will work for some scenarios, but none of them ticks all the boxes. The one (3rd attempt) which does tick all the boxes is only supported on Firefox (as of now).