On http://pinterest.com/ there are 'pins' ie <div>s of varying height but they all seem to render very well with no 'gaps' or line breaks to interrupt the flow. Is there a good/simple explanation of how they get the CSS to behave and implement that (I am hoping to learn and understand rather than just cargo-cult their CSS file!). Thanks in advance
8 Answers
Check out JQuery Masonry, it will be the simplest way to achieve the layout you want. http://masonry.desandro.com/
I did some reading of Pinterest's javascript a few months ago to figure this out myself. In short, they don't do it with CSS at all. They position all of their boxes/pins dynamically by iterating through them all, calculating the height, and dropping it at the bottom of whichever column that has the shortest height at the moment (adding that box's height to it). Basically, there's no trick to it, it's just Javascript.

- 4,389
- 4
- 23
- 19
-
1**+1** I provided link to this answer for different SO Question/Answer [**HERE**](http://stackoverflow.com/a/11253923/1195891). – arttronics Jun 28 '12 at 23:33
-
Css can't actually do that in the way you want it to. Javascript, like this example, can.
Due to how rows of floated or inline-blocked content behave, css isn't right for the job. You'd have to dynamically generate vertical columns of content and place them side by side, meaning you'd have to fight to get current content at the top. It would be kind of a pain, really. You'd also lose the responsiveness to window width.

- 2,812
- 22
- 29
-
Thank you for the pointer to Masonry! I had not heard about that before, will investigate – bachposer Nov 03 '11 at 18:54
You can now actually do it with css3
.three-col {
-moz-column-count: 3;
-moz-column-gap: 20px;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
}
Complete guide at : http://kmsm.ca/2010/an-almost-complete-guide-to-css3-multi-column-layouts/

- 5,223
- 7
- 43
- 71
-
1the problem with this is that the page will not read left to right, so not three latest items will be on the top of the page. – esp May 03 '13 at 18:46
-
1@esp: EXACTLY! +1. Columns are meant for vertically short content to make it more readable by narrowing text line length. If we have long vertically scrollable content and order of individual elements (as in Pinterest cards) is pseudo-important, then column layout isn't a solution. – Robert Koritnik Jul 04 '13 at 07:38
You can read the Pinterest cofounder's response to an earlier question about this: how to replicate pinterest.com's absolute div stacking layout
Having looked at all options, I ended up implementing the layout similar to Pinterest in this way:
All DIVs are:
div.tile {
display: inline-block;
vertical-align: top;
}
This makes them position in rows better than when they are floated.
Then when the page is loaded, I iterate all DIVs in JavaScript to remove gaps between them. It works acceptably well when:
- DIVs are not very different in height.
- You don't mind some minor violations of ordering (some elements that were below can be pulled up above).
- You don't mind the bottom line being of different height.
The benefit of this approach - your HTMLs make sense for search engines, can work with Javascript disabled/blocked by firewall, the sequence of elements in HTML matches the logical sequence (the newer items before older). You can see it's working at http://SheepOrPig.com/news

- 7,314
- 6
- 49
- 79
Easiest and Simple way i did, this looks armature. But i thought of sharing.....
This is three column layout...
First 3 container will not add height to it.. 4th container will take the height and top position of 1st container(that is prev().prev().prev()
)
counter = counter+1;
if(counter > 3){
var getTop = $(this).prev().prev().prev().offset();
var getLeft = $(this).prev().prev().prev().offset();
var getHeight = $(this).prev().prev().prev().height();
var countTPH = getTop.top + getHeight - 20;
$(this).css({"position":"absolute","top":countTPH+"px","left":getLeft.left+"px"});
}
I have put prev()
just to make reader understand the code simple1

- 7,300
- 6
- 36
- 47

- 11
- 1
Andrews answer is amazing! I was searching for a solution and finally got it... As Andrew wrote by positioning.. Here my JS snippet. Not perfect, but the right direction. Thanks Andrew!
var tilename = 6;
for (var i = 0; i < document.querySelectorAll('#tiles .t').length; i++) {
document.getElementsByClassName("t"+tilename)[0].style.top = document.getElementsByClassName("t"+(tilename-5))[0].offsetHeight + 10;
tilename += 1;
}

- 361
- 4
- 13
Its simple how it works: Here, I wrote my own in a matter of minutes. http://jsfiddle.net/92gxyugb/1/
coffescript
tiles = $('.tiles .t')
container = $('.tiles').width()
width = $('.tiles .t:first').width()
columns_height = {}
columns = Math.floor container / width
space = container % width
space = space / (columns-1)
for tile,i in tiles
column_index = i % columns
columns_height[column_index] ?= 0
sp = switch column_index
when 0 then 0
when columns then 0
else
space * column_index
$(tile).css
top: columns_height[column_index]
left: (column_index * width)+sp
columns_height[column_index] += $(tile).height()+space
max_height = 0
for k,v of columns_height
if v > max_height
max_height = v
$('.tiles').height max_height-space
html
<div class='tiles'>
<div class='t t1'></div>
<div class='t t2'></div>
<div class='t t3'></div>
<div class='t t4'></div>
<div class='t t5'></div>
<div class='t t6'></div>
<div class='t t7'></div>
<div class='t t8'></div>
<div class='t t9'></div>
<div class='t t10'></div>
<div class='t t11'></div>
<div class='t t12'></div>
<div class='t t13'></div>
<div class='t t14'></div>
<div class='t t15'></div>
<div class='t t16'></div>
</div>
css
.tiles {position: relative; width: 500px; background: rgb(140,250,250); }
.t { position: absolute; width: 87px; background: rgb(100,100,100); }
.t1 { height: 100px; }
.t2 { height: 140px; }
.t3 { height: 200px; }
.t4 { height: 180px; }
.t5 { height: 120px; }
.t6 { height: 150px; }
.t7 { height: 180px; }
.t8 { height: 200px; }
.t9 { height: 120px; }
.t10 { height: 160px; }
.t11 { height: 210px; }
.t12 { height: 160px; }
.t13 { height: 150px; }
.t14 { height: 150px; }
.t15 { height: 130px; }
.t16 { height: 170px; }

- 2,240
- 5
- 22
- 24