Masonry

Basic masonry grid algorithm

by soulwire

HTML

<div id="container"></div>

CSS

.item {
    background: #222;
    margin: 2px;
    float: left;
    width: 80px;
    color: #fff;
}

JavaScript

var numItems = 50;
var $container = $('#container');

// Create items.
for (var i = 0, $item; i < numItems; i++) {
    $item = $('<div class="item"/>');
    $item.height(50 + Math.round(Math.random() * 50));
    $item.text(i);
    $container.append($item);
}

// Position items.
var $items = $('.item');
var colWidth = $items.width();
var numCols = Math.floor($container.width() / colWidth);
var padX = parseInt($items.css('margin-left'), 10);
var padY = parseInt($items.css('margin-top'), 10);
var cols = [];
var col;

// Pushes an item onto a column.
function pushToCol($item, col) {
    
    // Position item.
    $item.css({
        position: 'absolute',
        left: col.index * (colWidth + padX),
        top: col.height
    });
    
    // Update column height.
    col.height += $item.height() + padY;
    
    // Add the item to this column.
    col.items.push($item);
    
    // Update the column index.
    cols[col.index] = col;
}

// Pops an item from a column.
function popFromCol(col) {
    
    // Pop the last item.
    var $item = col.items.pop();
    
    // Update height.
    col.height -= $item.height() + padY;
    
    return $item;
}

// Loop through items.
$items.each(function(index) {
    
    // Compute current column.
    colIndex = index % numCols;
    
    // Append item to column.
    pushToCol($(this), cols[colIndex] || {
        index: colIndex,
        height: 0,
        items: []
    });
});

function sortOn(arr, key) {
    return arr.sort(function(a, b) {
        return a[key] - b[key];
    });
}

var prevOpp = null;

// Takes from the largest column and gives to the shortest.
function robinHood() {
    
    var prevOpp = [];
    var count = 0;
    
    while (++count < 100) {
        
        var opp = [];
        
        // Sort columns, shortest to hightest
        cols = sortOn(cols, 'height');
        
        // Get the longest column.
        col = cols[cols.length - 1];
        opp[0] = col.index;
        
        // Pop the last...