I'm trying to organize div
s into two columns, but not force them into rows. I'm also trying to keep the vertical spacing between the div
s a constant.
You can see the following demo, which would be correct if there wasn't huge amounts of vertical whitespace between the divs in each column.
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
I thought that I could just float them to the left with a static width, but apparently that didn't work.
Any ideas?
First things first: you won’t be able to acheive a columnar wrapping layout with floats: as other commenters have pointed out, that’s just not how floats work. Nor is there an "automatic masonry-layout" module in CSS, which I suspect is what you’re really after. I also assume that placing each item individually is out of the question.
The closest thing you’ll get is Grid Layout—we’ll get to that towards the end. Spoiler: it’s really cool, but it’ll be a little while before browser support is really good.
So, TL;DR: there is no cross-browser method for doing a smart, row-by-row, masonry-like layout in CSS. But Grid Layout comes damn near. If you can't wait, use JS or switch the design to something that works with wrapping columns, for example.
If you choose the JS route, you could use the Grid Layout JS polyfill! That way, you can write grid layout syntax today, and remove the polyfill when it’s no longer needed, at some point in the future.
Judging from other answers and comments, a columnar wrapping layout is not what you want though. Just in case you still decide to go that route, you can do it with Multi Column layout. Support is pretty good: everything except IE<10, pretty much.
A quick example, just in case you want to change your layout to go in the multicol direction: here’s a JSBin with 2-column multicol layout. Note that you do not need to set both column-count
and column-width
: set a column-count
(and column-gap
) and the rest will sort itself out.
Oh, and if you get buggy rendering with margins (e.g. margins wrapping onto new columns, creating uneven layouts), the usual fix is to set display: inline-block; width: 100%;
on the .module
. Your milage may vary: for something that’s been around a long time, multicol sure is buggy.
Sticking with columnar layout for just a little bit longer, you can also use flexbox. (I see one other answer bringing up Flexbox, but sadly a completely outdated syntax which will not work in modern browsers).
The difference between wrapping into columns in multi-col vs flexbox is that flexbox does not balance the items into columns for you (it’s not really made for that type of layout), so you need to set a specific height in order to force the columns to wrap. If you have a container element (.container
) and the .module
items inside it, the following is the basic approach:
.container {
display: flex;
flex-flow: column wrap;
height: 1000px; /* or whatever works for you */
}
.module {
/* whatever props you want for modules */
}
...not counting prefixes and syntax variations for IE10, which uses a slightly older variation of the spec. (There’s also the old-old flexbox, which doesn’t support flex wrapping, so we’ll forget about that). Simple JSBin wrapping flexbox example here.
Finally, we get to Grid Layout. This new spec has some really cool features, that allow us to do something close to a "Masonry" layout.
Heads up: you need to check these examples in Chrome Canary, WebKit Nightly or Firefox Developer edition. There is an old implementation of Grid Layout in IE10+ (and Edge as well), but it doesn’t contain all the new hotness properties we need.
First the markup: we’ll use a wrapper element + the .module
items inside (the wrapper is not strictly necessary—we could have put the modules directly into body
, but I just find it clearer this way):
<div class="container">
<div class="module"></div>
<div class="module"></div>
<!-- and so on -->
</div>
Next, we tell the container to be a grid container:
.container {
display: grid;
}
Then we set it to have a "template" for columns of 2 equal width columns (1 "fractional unit"), and gaps between columns as well as rows of 20px:
.container {
display: grid;
/* 2 columns, equally wide: */
grid-template-columns: 1fr 1fr;
/* gaps between each column and row. */
grid-column-gap: 20px;
grid-row-gap: 20px;
/* ...can also be shortened to grid-gap: 20px; */
}
We have not yet given it a template for rows, but we only need to allow it to automatically create them as needed. For this, we set the grid-auto-rows
property, to add as many 50px
tall rows as needed:
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
/* automatically create rows, 50px tall each: */
grid-auto-rows: 50px;
}
At this point, we have not placed any items inside the container yet, at least not explicitly. With grid, you can specify exactly which area of the grid an item shoud belong in. The thing is, you don’t have to! The grid will place them automatically in the first available slot, starting at the top left and going row by row by default, unless you tell it otherwise.
Instead, we need to tell it that some items are bigger than others. We don’t use sizes for this, but instead tell odd items to span 2 rows, and every 3rd item to span 4 rows.
.module {
background: yellow;
}
.module:nth-child(odd) {
grid-row: span 2;
background: green;
}
.module:nth-child(3n) {
grid-row: span 4;
background: orange;
}
Finally, we need to tell the grid to use the "dense" algorithm, meaning it will make one placement pass per item, trying to avoid making "holes" in the auto placement.
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 20px;
grid-row-gap: 20px;
grid-auto-rows: 50px;
/* use the "dense" algorithm: */
grid-auto-flow: row dense;
}
This gives us something very close to a "masonry" layout, as can be seen in this JSBin example of a dense grid layout — Again, note that you will need nightly/dev versions of Chrome/WebKit or Firefox to see how it works.
Here’s an image of the result, as viewed in Chrome Canary:
Some things to note:
row dense
packing algorithm doesn’t really make a difference here, as the items happen to stack up in a pattern that leaves no holes, but I put it in there for completeness.Thanks to J.Albert Bowden for the fiddle
HTML
<div id="box">
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
</div>
CSS
#box{
-moz-column-count:3;
-moz-column-gap: 3%;
-moz-column-width: 30%;
-webkit-column-count:3;
-webkit-column-gap: 3%;
-webkit-column-width: 30%;
column-count: 3;
column-gap: 3%;
column-width: 30%;
}
.module{
margin-bottom: 20px;
}
Try this.. http://jsfiddle.net/rymfev8c/1/
HTML
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
<div class="module"></div>
CSS
body {
padding: 40px;
}
.module {
height: 50px;
width: 45%;
margin-right: 3%;
margin-bottom: 60px;
background: yellow;
float: left;
}
.module:nth-child(odd) {
height: 100px;
background: green;
margin-bottom: 5px;
}
.module:nth-child(3n) {
height: 200px;
background: orange;
margin-bottom: 5px;
}
omg its 3 years old..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With