Stacking divs with variable height in 2 columns like Facebook Timeline

After checking the Facebook CSS and HTML, I found they achieve this using a list and alternating the float on the li elements between left and right (ie, every even element is floated right)

For example:

HTML

<ul>
    <li>...</li>
    <li>...</li>
    <li>...</li>
</ul>

CSS

li {
    clear: left;
    float: left;
    display: block;
    height: 100px;
    width: 200px;
    margin-bottom: 10px;
}

li:nth-child(2n) {
    clear: right;
    float: right;
}

Working example: http://jsfiddle.net/gBVPj/

This approach only works if an element on one side does not exceed the height of two elements on the other side. For example, in your diagram, should box 2 have a height larger than that of box 1 and 3 combined, then box 5 will be displaced and positioned inline with box 4.

Like this: http://jsfiddle.net/gBVPj/1/

I have not found an example of this problem on Facebook (one element never exceeds the height of two) so I believe that they have taken this into account. They could possibly be achieving this by using JavaScript - if you check the elements, they have a property data-height which matches the height of the element.


I worked on this last night and found a rather simple way to do.

Compare the bottom position of the left column and the right column, append the new li element to the side with smaller value, which can be done by th e following way:

var last_left_post = $('.left:last');
var last_right_post = $('.right:last');
var left_position = 0;
var right_position = 0;

left_position = last_left_post.height() + last_left_post.offset().top;
right_position = last_right_post.height() + last_right_post.offset().top;

if(left_position<=right_position){
    $('#timeline').append('<li class="left"></li>');
}else{
    $('#timeline').append('<li class="right"></li>');
}

.left and .right using the same css as you do.

Tags:

Html

Css