最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Always align left in Masonry - Stack Overflow

programmeradmin1浏览0评论

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
Add a ment  | 

3 Answers 3

Reset to default 3

Old 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
        });
发布评论

评论列表(0)

  1. 暂无评论