I have a 2-column grid layout with content inside them. The content can be short or long, now I want to use the available place more usefully. I've created an example:
Currently, the container around the green content stretches to be as high as the red content.
Ideally, I want to use up the free space under the green content with the blue content, but only if the red content is higher than the green one. If the green content is larger than the red one, and therefore there is space under the red one, the blue content should appear there.
Is a grid layout the wrong thing I am using? I looked at the different grid-auto-flow
options unsuccessfully.
Thanks :)
Should the specification for Masonry Layout in CSS Grid be standardized and supported, then that would be the correct choice.
Until then, here are ways to achieve masonry layout:
columns
property (and inline-level container elements).columns
propertyThe columns
property is used to divide the inline flow of an element into columns, like text columns in newspaper articles:
/*Ignore; make containers visible*/
.masonry > * {
border: 1px solid black;
}
<div class="masonry" style="column-count: 2">
<div>
Long text to fill this DIV in hopes that we can see some line-wrapping because otherwise this demo may not be sufficient enough in showing how the CSS columns property works on inline containers that may wrap and may be split onto separate columns one may naively think.
</div>
<div>
Another long text to fill yet another DIV to show containers with varying lengths of content that will demonstrate that the column property properly lays the containers out on multiple columns however uninterrupted so that each container is still whole to not ruin the flow of reading and show a pleasing and robust layout and design.
</div>
<div>
Maybe a third long text with some other content yet again to show the same points as before which really were only one point but worded differently just so that I can fill these containers with text and have differently sized containers that hopefully not look like they can be layed out in a grid just as well as they could be layed out with the columns property.
</div>
<div>
I could very well copy-paste some pre-generated text here or even some of the texts above but I find enjoyment in writing mundane and irrelevant texts that maybe someone will read that serve no actual purpose but to be filler text much like how series on television occasionally feature filler episodes which I find really irritating especially when their content is not featured in the original work the series is based on.
</div>
<div>
While I did mention that someone someday may read these whole passages of text wondering why each block is one coherent sentence I hope that nobody really does read this and waste their time which could be used in a much better and productive way except those who may enjoy reading this just as much as I enjoyed writing it.
</div>
</div>
You can avoid an element to break mid-way with break-inside: avoid-column
, as this answer explains. However, Firefox supports it only as of late.
Alternatively, inline-level containers are also not split mid-way, so we can set the masonry element's children's display
property accordingly for similar behaviour:
:where(.masonry > *) {
break-inside: avoid-column;
}
/*Ignore; make containers visible*/
.masonry > * {
border: 1px solid black;
}
<div class="masonry" style="column-count: 2">
<div>
Long text to fill this DIV in hopes that we can see some line-wrapping because otherwise this demo may not be sufficient enough in showing how the CSS columns property works on inline containers that may wrap and may be split onto separate columns one may naively think.
</div>
<div>
Another long text to fill yet another DIV to show containers with varying lengths of content that will demonstrate that the column property properly lays the containers out on multiple columns however uninterrupted so that each container is still whole to not ruin the flow of reading and show a pleasing and robust layout and design.
</div>
<div>
Maybe a third long text with some other content yet again to show the same points as before which really were only one point but worded differently just so that I can fill these containers with text and have differently sized containers that hopefully not look like they can be layed out in a grid just as well as they could be layed out with the columns property.
</div>
<div>
I could very well copy-paste some pre-generated text here or even some of the texts above but I find enjoyment in writing mundane and irrelevant texts that maybe someone will read that serve no actual purpose but to be filler text much like how series on television occasionally feature filler episodes which I find really irritating especially when their content is not featured in the original work the series is based on.
</div>
<div>
While I did mention that someone someday may read these whole passages of text wondering why each block is one coherent sentence I hope that nobody really does read this and waste their time which could be used in a much better and productive way except those who may enjoy reading this just as much as I enjoyed writing it.
</div>
</div>
An advantage of using the columns
property over Flexbox is that it implicitly finds the required height of the masonry element to lay out all its children properly.
When using CSS Flexbox, we can define the direction of the main-axis to go top-to-bottom with flex-direction: column
.
Unfortunately Flexbox avoids wrapping as much as possible:
.masonry {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
/*Ignore; make containers visible*/
.masonry > * {
border: 1px solid black;
}
<div class="masonry">
<div>
Long text to fill this DIV in hopes that we can see some line-wrapping because otherwise this demo may not be sufficient enough in showing how the CSS columns property works on inline containers that may wrap and may be split onto separate columns one may naively think.
</div>
<div>
Another long text to fill yet another DIV to show containers with varying lengths of content that will demonstrate that the column property properly lays the containers out on multiple columns however uninterrupted so that each container is still whole to not ruin the flow of reading and show a pleasing and robust layout and design.
</div>
<div>
Maybe a third long text with some other content yet again to show the same points as before which really were only one point but worded differently just so that I can fill these containers with text and have differently sized containers that hopefully not look like they can be layed out in a grid just as well as they could be layed out with the columns property.
</div>
<div>
I could very well copy-paste some pre-generated text here or even some of the texts above but I find enjoyment in writing mundane and irrelevant texts that maybe someone will read that serve no actual purpose but to be filler text much like how series on television occasionally feature filler episodes which I find really irritating especially when their content is not featured in the original work the series is based on.
</div>
<div>
While I did mention that someone someday may read these whole passages of text wondering why each block is one coherent sentence I hope that nobody really does read this and waste their time which could be used in a much better and productive way except those who may enjoy reading this just as much as I enjoyed writing it.
</div>
</div>
Therefore the masonry element needs an explicit height (for vertical masonry layout) and its children explicit widths (for horizontal writing; sizes should also account for the gap
property):
.masonry {
height: 24rem;
}
.masonry > * {
width: 50%;
box-sizing: border-box;
}
/*From before:*/
.masonry {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
/*Ignore; make containers visible*/
.masonry > * {
border: 1px solid black;
}
<div class="masonry" style="column-count: 2">
<div>
Long text to fill this DIV in hopes that we can see some line-wrapping because otherwise this demo may not be sufficient enough in showing how the CSS columns property works on inline containers that may wrap and may be split onto separate columns one may naively think.
</div>
<div>
Another long text to fill yet another DIV to show containers with varying lengths of content that will demonstrate that the column property properly lays the containers out on multiple columns however uninterrupted so that each container is still whole to not ruin the flow of reading and show a pleasing and robust layout and design.
</div>
<div>
Maybe a third long text with some other content yet again to show the same points as before which really were only one point but worded differently just so that I can fill these containers with text and have differently sized containers that hopefully not look like they can be layed out in a grid just as well as they could be layed out with the columns property.
</div>
<div>
I could very well copy-paste some pre-generated text here or even some of the texts above but I find enjoyment in writing mundane and irrelevant texts that maybe someone will read that serve no actual purpose but to be filler text much like how series on television occasionally feature filler episodes which I find really irritating especially when their content is not featured in the original work the series is based on.
</div>
<div>
While I did mention that someone someday may read these whole passages of text wondering why each block is one coherent sentence I hope that nobody really does read this and waste their time which could be used in a much better and productive way except those who may enjoy reading this just as much as I enjoyed writing it.
</div>
</div>
Using Flexbox like this is most robust when setting an explicit size on the masonry element under the assumption that the font won't change.
Should the font change (e.g. by zooming, switching font-family, changing font-size) then the Flexbox-based masonry layout may break. This breaking may be apparent by overflowing children and a scrollbar.