On the surface it seems fairly easy to create a masonry layout with flexbox; all you need to do is set
column wrap and voilà, you have a masonry layout. Sort of. The problem with this approach is that it produces a grid with a seemingly shuffled and obscure order. Items will be (unbeknownst to the user) rendered from top to bottom and someone parsing the grid from left to right will read the boxes in a somewhat arbitrary order, for example 1, 3, 6, 2, 4, 7, 8, 5, and so on so forth.
- Masonry Grid Css Style
- Css Masonry Layout
- Masonry Grid Css Download
- Masonry Grid Css W3schools
- Masonry Blocks Css
- Css Flex Masonry
Flexbox has no easy way of rendering items with a
column layout while using a
:nth-child() and the
order property. In a gist, here’s the trick to create a
row order while using
flex-direction: column, given that you’re rendering three columns:
This will create a masonry layout with items rendered as columns but ordered as rows (the gray vertical lines represent the pseudo elements that force line breaks:
True HTML CSS Masonry with grid layout. This model is presumably the most unpredictable and the. 1,199 Followers, 291 Following, 11 Posts - See Instagram photos and videos from abdou now online (@abdoualittlebit).
Let’s break down the implementation (or jump to the solution, or see the codepen collection).
Pick your poison: a shuffled order, or weird gaps
Flexbox is not really built for masonry—if you set a fixed height on a flex container (so that items can wrap when they overflow) and
column wrap, you’ll achieve something like this:
Items are rendered in columns from top to bottom, producing an arbitrary order when read from left to right. This is of course the expected outcome and desirable in many scenarios, but not when we’re trying to create a masonry layout, and it becomes increasingly disorienting as a page grows taller.
If we instead change the
row and have elements of varying heights we’ll achieve the correct order but with weird and unexpected gaps all over our grid:
So it seems impossible to get the best of both worlds: items rendered as columns but ordered as rows. You might decide to use
flex-direction: column and just move around the elements in your HTML to achieve the right visual order, but this can be cumbersome, it’s unnecessarily complex, and it will mess up the tab order of the elements.
Re-ordering elements with
order property affects the order of items contained in a CSS flexbox or grid, and we can use it to re-order items for our soon-to-be masonry layout. The
order property is pretty straight-forward to use: if you have two elements and one has
order: 1 and the other one has
order: 2 the element with
order: 1 will be rendered before the other element, independent of their HTML source code order.
The CSS masonry solution depends on a detail of the
order specification: what happens if two or more elements have the same
order value? Which comes first? Flexbox falls back on the source code order: the element that appears first in the source code will be rendered before other elements with the same order value. This fact gives us the possibility to easily re-group items in our grid so that we can change the ordering from columns to rows, while still rendering those rows as columns, using
Look at the table below. To achieve a sensible order using
flex-direction: row we’d just have to render elements in the default order:
1, 2, 3, 4, 5, 6 , etc.
|Column 1||Column 2||Column 3|
If we want to achieve the same order while using
flex-direction: column we need to change the order of the elements to match the order of each column in the table (rather than each row):
Masonry Grid Css Style
|Column 1||Column 2||Column 3|
I.e. the first elements in our flexbox layout have to be
1, 4, 7, 10. These items will fill up the first column, followed by
2, 5, 8, 11 for the 2nd column and
3, 6, 9, 12 for the 3rd and last column. This is where the
nth-child() selector comes in. We can use it to select every third element (3n), starting with the first element (3n+1), and set all those elements to have the same
This selector sets
order: 1 for element
1, 4, 7, 10 in our container, i.e. the entire first column. In other words we’re using a combination of
order to re-order items depending on their original order. To create the 2nd and 3rd column we just change the offset:
Here we’re producing three sets:
1, 4, 7, 10 (3n+1) with
2, 5, 8, 11 (3n+2) with
order: 2, and
3, 6, 9, 12 (3n) with
order: 3. All together the order becomes
1, 4, 7, 10, 2, 5, 8, 11, 3, 6, 9, 12.
If we make sure to render each of those groups as one column (and no more), it’ll create the illusion that the items have returned to their original order when you read from left to right. If we visually parse the grid as rows the first row will contain the first element from every group (
1, 2, 3), the second row will contain the second element from every group (
4, 5, 6), and so on so forth. With this technique we can create a masonry layout with items rendered as columns but ordered as rows.
How is the tab order affected by shuffling around elements like this? Luckily, not at all.
order only changes the visual representation of objects, not the tab order, so tabbing through the grid will work as intended.
Preventing columns from merging
If you have many items in a masonry layout this technique will fairly certainly break down at some point. We’re counting on that every “group” that we’ve created will be rendered as exactly one column but in reality items can have different heights and columns can easily start to merge. The first column could be longer than the other two, for example, which could make the third column start at the end of the second column:
Css Masonry Layout
The highlighted box here (3) has to be rendered at the start of the third column or the ordering algorithm will break, but if there’s space for another element at the end of the 2nd column it will naturally be rendered there.
We can fix this wrapping issue by forcing columns to restart at certain points. There’s no easy way of saying “this element should line break” with flexbox, but we can achieve this effect by adding invisible elements that take up 100% of the container’s height. As they require 100% of the parent’s height to be rendered they won’t fit in a column together with any other element, so they’ll essentially force line breaks by creating collapsed columns.
We have to insert these line break elements into our grid and array of elements, so what we’re looking for is to create this sequence of elements:
1, 4, 7, 10, <break>, 2, 5, 8, 11, <break>, 3, 6, 9, 12. We can use pseudo-elements on the container to add these, and we can set the
2 on both of them. Adding a pseudo-element with
:before will make it the first child of the container and adding a pseudo-element with
:after will make it the last child of the container, so if we set
order: 2 on both of them they will become the first and the last element of the
order: 2 “group” (as they appear before and after the other elements):
:before, 2, 5, 8, 11, :after.
I’ve highlighted the pseudo-elements below to show their effect. Notice that despite that box 3 would fit in the 2nd column it’s rendered as the first element in the last column:
As a final step, you need to make sure that your flex container has a set height that makes it taller than your tallest column (so that all columns will fit). Put together, this will produce a CSS masonry layout with three columns (also available as a codepen):
Your HTML should look like this, with one
<div /> for every item in your grid:
Working with more than three columns
Masonry Grid Css Download
To create a masonry layout with more than three columns we need to do a few things: adapt our sorting algorithm, update the width of the items, and insert line break elements manually (instead of using pseudo-elements). For quick access to the final result I’ve compiled a list of codepens showcasing flexbox masonry with 3, 4, 5 and 6 columns.
Since we’re limited to creating just two pseudo-elements with
:after we need to resort to manually adding break elements into our container (you need one less break element than the number of columns in your layout). You can just append them to the end of your container, they’ll be sorted into their respective columns:
We’re inserting column breaks as
spans in order to sort them independently from the content items. We need a way to “restart” the counting once we reach the break elements, or an uneven number of content items could make the first break element start after the 3rd column, for example. The
:nth-of-type selector targets elements of different types independently, so we can decouple the order of the content items and the column breaks like so:
The break elements, like previously, take up the full height of the container:
This will create a masonry layout with four columns (view codepen):
Masonry Grid Css W3schools
Here’s the full solution for a CSS masonry layout with four columns:
For help with more common CSS flexbox patterns, I’ve compiled a list of flexbox examples that you can copy and paste into your projects and written in-depth about the line-breaking flexbox item technique.
- October, 2020: the CSS Working Group has now published a draft specification for masonry layouts, as part of CSS grid
- CSS masonry can also be implemented with Houdini (requires flag)
Masonry layout support has been added to the CSS grid specification! 🎉
A Level 3 of the CSS Grid specification has been published as an Editor’s Draft, this level describes a way to do Masonry layout in CSS.
Masonry Blocks Css
A masonry layout is one where items are laid out one after the other in the inline direction. When they move onto the next line, items will move up into any gaps left by shorter items in the first line. It’s similar to a grid layout with auto-placement, but without sticking to a strict grid for the rows.
To create a masonry layout in CSS, use the new
grid-template-rows: masonry property.
The masonry layout was popularized by Pinterest (they call it a “Collage” in their design system). It’s a useful tool to display text and images without truncating or expanding blocks to a fixed size.
I use a masonry layout or my recipes site. It’s a CSS-only implementation with CSS columns. The problem is that the content is ordered from top to bottom, then left to right. Since I don’t often browse the recipes (I use the search input), this was a tradeoff I could live with.
Masonry with CSS grid currently only works in Firefox, but I hope other browsers will follow soon. I’m not a CSS grid power user. Old habits die hard and I often use flexbox unless I need a grid-specific feature. Time to head back to Grid Garden to flex those muscles!
Css Flex Masonry
You can read all about the new masonry features in Rachel Andrew’s article on Smashing Magazine.