Using Masonry on a catalog site. By default, the items displayed sort by date, then by part number. My images are varying height. The problem is, and correct me if I'm wrong, Masonry sets row 2, item 1 below the shortest item in row 1 rather than on the left of the page. So in other words, when my database returns a certain order, Masonry places those items ordered top to bottom (when varying heights), rather than left to right.
I don't find anything in documentation to control this. Is there a way to force Masonry to keep items in order left to right and just float vertically based on height?
I attempted to post an illustration, but apparently I'm not qualified to do so. Here's a link to the illustration:
inspired by Billy's answer (and therefor by skobaljic's answer :) ) I just changed the initialisation of shortColIndex and minimumY to achieve this behaviour. Might be a little easier plus - using the colGroup's size - responsive layouts with different column counts still work.
Here is the complete code for v3.3.2:
Masonry.prototype._getItemLayoutPosition = function( item ) {
item.getSize();
// how many columns does this brick span
var remainder = item.size.outerWidth % this.columnWidth;
var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
// round if off by 1 pixel, otherwise use ceil
var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
colSpan = Math.min( colSpan, this.cols );
var colGroup = this._getColGroup( colSpan );
// ### HACK: sort by natural order, not by min col height
// get the minimum Y value from the columns
// var minimumY = Math.min.apply( Math, colGroup );
// var shortColIndex = utils.indexOf( colGroup, minimumY );
var shortColIndex = jQuery(item.element).index() % colGroup.length;
var minimumY = colGroup[shortColIndex];
// position the brick
var position = {
x: this.columnWidth * shortColIndex,
y: minimumY
};
// apply setHeight to necessary columns
var setHeight = minimumY + item.size.outerHeight;
var setSpan = this.cols + 1 - colGroup.length;
for ( var i = 0; i < setSpan; i++ ) {
this.colYs[ shortColIndex + i ] = setHeight;
}
return position;
};
There is no option in Masonry to sort items, because it is a simple plugin that places bricks one by one. Choosing new brick position is simple: place it higher as you can.
But what one can do in this case is to change the script by adding one two lines that define sorting, assuming all bricks are same width (for example, always 5 in row).
To demonstrate this, I used jQuery Masonry (was compressed) and you can check it out in this Fiddle.
JS
$.Mason.prototype._placeBrick = function(e) {
var n = $(e),
r, i, s, o, u;
r = Math.ceil(n.outerWidth(!0) / this.columnWidth), r = Math.min(r, this.cols);
if (r === 1) s = this.colYs;
else {
i = this.cols + 1 - r, s = [];
for (u = 0; u < i; u++) o = this.colYs.slice(u, u + r), s[u] = Math.max.apply(Math, o)
}
var a = Math.min.apply(Math, s),
f = 0;
for (var l = 0, c = s.length; l < c; l++)
if (s[l] === a) {
f = l;
break
}
/* Add new calculation, what column next brick is in: */
f = $(e).index() % this.cols; /* Get col index f: Just divide with element's index */
a = s[f]; /* This is current height for f-th column */
/* END of customizing */
var h = {
top: a + this.offset.y
};
h[this.horizontalDirection] = this.columnWidth * f + this.offset.x, this.styleQueue.push({
$el: n,
style: h
});
var p = a + n.outerHeight(!0),
d = this.cols + 1 - c;
for (l = 0; l < d; l++) this.colYs[f + l] = p;
};
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