Lets say you have a list of boxes you want to show in a grid-like list, but the height of every box is defined by its content, which results in different heights. Here is an example with a base64 encoded 1px image with an individually defined height:
column-gap to the wrapper and a
margin-bottom with the same value as the gap to each item, you will achieve this:
The order of the boxes is from top to bottom and then from left to right … Fake Masonry, but is works as expected. Here is the most important CSS:
See the pen for the complete HTML and CSS:
To make the list visually a little bit more interesting, we now add a shadow, which is half as thick as the gap, to the boxes:
In case you work with a Chromium based browser (Version 97.x as of today), you will be confronted with a bug. The “break” from one column to the next doesn’t respect the full 10px high shadow of the next item. It breaks too late. You will get something like this:
I added a red shadow on hover, to make the bug more obvious. See following pen to inspect the CSS. In case you use Firefox (Version 96.x as of today), you won’t see the bug, because Mozilla did it right.
In order to achieve a proper result, we have to hack the HTML and the CSS a bit. First of all we have to wrap the content of an item with a new element called
Next, we move the
border and the
box-shadow from the item itself to the new inner element. Important here is, to set the background of the
item element to
transparent in order to prevent interfering with the shadow.
Now we have to set the
wrapper‘s gap to 0, because we will implement the spacing of the items by applying different paddings to the
item element: half of the gap to be reached, to the
right and the
bottom padding and the full gap to the
top. The latter, to achieve pushing the previous element far enough away so as not to see anything of the shadow.
But because this would mean that the horizontal gap would be too large by half, we have to use a negative margin to pull the element up by that amount.
This in turn would mean, that the first
item element in the list would be too high by the now defined negative top margin, which we correct again by using
Here is the complete solution as a pen:
Maybe the Chromium team will fix the bug as soon as possible, to no longer have to rely on this hack, but the really best solution would be, to finish the work already started on the true grid masonry, which currently only Firefox offers behind a flag.
- caniuse.com: Can I Use: CSS property: grid-template-rows
- Ryan (dev.to): Creating A Responsive Masonry Layout Using The CSS column-count Property
- MDN WebDocs: Masonry Layout
- Rachel Andrew (Smashing Magazine): Native CSS Masonry Layout In CSS Grid
- Syed Umar Anis: Create Masonry Layout with CSS
- Chris Coyier (CSS-Tricks): Approaches for a CSS Masonry Layout
- Jonas (Kulturbanause): Responsive Masonry Layouts mit CSS erstellen (German)