CSS Columns and Drop Shadow
How to fix Chromes bug on showing shadows in a column (masonry) layout
As of today, there is no true Masonry Layout technique in web development that can be implemented exclusively with CSS and is not based on JavaScript. True in the meaning, that the reading direction should be from left to right and not in the form of columns from top to bottom. For the latter, also called Fake Masonry, there are even two implementation options in CSS: Columns or Flex, whereas the Columns variant is the much simpler one.
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:
1 | <div class="wrapper"> |
By applying column-count
and 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:
1 | :root { |
See the pen for the complete HTML and CSS:
Drop Shadow and the Chromium Bug
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:
1 | :root { |
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.
Workaround
Step 1
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 ìtem-inner
:
1 | <div class="item"> |
Step 2
Next, we move the width
, 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.
1 | :root { |
Step 3
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 left
, 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 item:first-child
.
1 | :root { |
Here is the complete solution as a pen:
Conclusion
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.
More Info
- 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)
You can interact with this article (applause, criticism, whatever) by mention it in one of your posts, which will be shown here as a Webmention, or by leaving a good old comment with your GitHub account.
Webmentions
No Webmentions yet...
In case your blog software can't send Webmentions, you can use this form to submit me a mention of this article...
Comments