I'm using the Masonry jQuery plugin to align a grid of items.
Here's what I have:
Expected behavior:
How can I achieve this effect? I've tried various options but nothing works.
Here's my HTML for each box:
<div class="sa-visual-grid-item" id="sa-visual-grid-item-<?=$id?>">
<div class="sa-selected-box"></div>
<input type="hidden" name="selected[<?=$id?>]" value="1" />
<img class="sa-img" src="<?=$img_url?>" />
<div class="sa-desc">
<div class="sa-name"><?=$name?></div>
<div class="sa-price"><?=$price?></div>
</div>
</div>
And CSS:
.sa-visual-grid {
height: auto;
margin: 0 auto;
text-align: center;
}
.sa-visual-grid-item {
background: white;
float: left;
width: 250px;
padding: 15px;
margin: 10px 15px;
border: 1px solid #bbb;
box-shadow: 0px 5px 15px 0px #efefef;
cursor:pointer;
text-align: center;
}
.sa-selected-box {
display: none;
position:absolute;
z-index:100;
border: 8px solid #00aa00;
width:254px;
padding:15px;
margin-top:-25px;
margin-left:-25px;
}
I'm using the Masonry jQuery plugin to align a grid of items.
Here's what I have:
Expected behavior:
How can I achieve this effect? I've tried various options but nothing works.
Here's my HTML for each box:
<div class="sa-visual-grid-item" id="sa-visual-grid-item-<?=$id?>">
<div class="sa-selected-box"></div>
<input type="hidden" name="selected[<?=$id?>]" value="1" />
<img class="sa-img" src="<?=$img_url?>" />
<div class="sa-desc">
<div class="sa-name"><?=$name?></div>
<div class="sa-price"><?=$price?></div>
</div>
</div>
And CSS:
.sa-visual-grid {
height: auto;
margin: 0 auto;
text-align: center;
}
.sa-visual-grid-item {
background: white;
float: left;
width: 250px;
padding: 15px;
margin: 10px 15px;
border: 1px solid #bbb;
box-shadow: 0px 5px 15px 0px #efefef;
cursor:pointer;
text-align: center;
}
.sa-selected-box {
display: none;
position:absolute;
z-index:100;
border: 8px solid #00aa00;
width:254px;
padding:15px;
margin-top:-25px;
margin-left:-25px;
}
Share
Improve this question
edited Jun 20, 2020 at 9:12
CommunityBot
11 silver badge
asked Apr 25, 2013 at 16:37
casrafcasraf
21.7k10 gold badges60 silver badges93 bronze badges
2
- Not really plausible. You'll have to use absolute/relative positioning to get these to line up exactly as expected. We have no idea what the context of these blocks are either. Are they dynamic? Are there more of them? Do they vary in layout over the site? etc. – dmackerman Commented Apr 25, 2013 at 18:17
- They will eventually add up, and their variation is only the height. Is it really impossible to just make them appear properly from left to right? I struggled to do it with pure CSS. – casraf Commented Apr 26, 2013 at 12:24
3 Answers
Reset to default 3Old post, I know, but this might be helpful for others:
$('.grid').masonry({
horizontalOrder: true
});
After adding this to my JS file, the grid-items were all left justified.
Example:
$('.grid').masonry({
itemSelector: '.grid-item',
columnWidth: 160,
horizontalOrder: true
});
* { box-sizing: border-box; }
body { font-family: sans-serif; }
/* ---- grid ---- */
.grid {
background: #EEE;
max-width: 1200px;
counter-reset: grid-item;
}
/* clearfix */
.grid:after {
content: '';
display: block;
clear: both;
}
/* ---- grid-item ---- */
.grid-item {
width: 160px;
height: 120px;
float: left;
background: #D26;
border: 2px solid #333;
border-color: hsla(0, 0%, 0%, 0.5);
border-radius: 5px;
}
.grid-item--width2 { width: 320px; }
.grid-item--width3 { width: 480px; }
.grid-item--width4 { width: 720px; }
.grid-item--height2 { height: 200px; }
.grid-item--height3 { height: 260px; }
.grid-item--height4 { height: 360px; }
.grid-item:before {
counter-increment: grid-item;
content: counter(grid-item);
display: block;
color: white;
padding-top: 0.2em;
text-align: center;
font-size: 1.4rem;
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg./masonry-layout@4/dist/masonry.pkgd.js"></script>
<h1>Masonry - horizontalOrder</h1>
<div class="grid">
<div class="grid-item grid-item--height2"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
You can't. It's an algorithm to pack bins most efficient. It's not designed to look good. Maybe you can try the wookmark plugin. There is also many others.
I know this is old but I ran into the same problem and came across this post in my googling. I was able to solve this problem by slightly modifying the library. Modify the Masonry.prototype._getItemLayoutPosition function as follows (don't overlook the changes under //position the brick, and //apply setHeight) :
Masonry.prototype._getItemLayoutPosition = function( item, count ) {
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 );
// get the minimum Y value from the columns
var minimumY = Math.min.apply( Math, colGroup );
var shortColIndex;
if (this._getOption('alignLTR') == true)
{
shortColIndex = count - ((Math.floor(count / colGroup.length) * colGroup.length));
}
else {
shortColIndex = colGroup.indexOf(minimumY);
}
// position the brick
var position = {
x: this.columnWidth * shortColIndex,
y: colGroup[shortColIndex]
};
// apply setHeight to necessary columns
var setHeight = colGroup[shortColIndex] + item.size.outerHeight;
var setSpan = this.cols + 1 - colGroup.length;
for ( var i = 0; i < setSpan; i++ ) {
this.colYs[ shortColIndex + i ] = setHeight;
}
return position;
};
You'll also have to modify the loop that calls this function to pass in the count for each item as you loop through them.
proto._layoutItems = function( items, isInstant ) {
this._emitCompleteOnItems( 'layout', items );
if ( !items || !items.length ) {
// no items, emit event with empty array
return;
}
var queue = [];
var itemCount = 0;
items.forEach( function( item, itemCount ) {
// get x/y object from method
var position = this._getItemLayoutPosition( item, itemCount );
itemCount++;
// enqueue
position.item = item;
position.isInstant = isInstant || item.isLayoutInstant;
queue.push( position );
}, this );
this._processLayoutQueue( queue );
};
Finally, you'll have to set your new option 'alignLTR' to true when creating your grid.
var $grid = $('#myGrid').masonry({
isAnimated: true,
itemSelector: '.my-item',
alignLTR: true
});