jquerycss-floatjquery-masonry

jQuery masonry leaving gap


I'm attempting to use jQuery Masonry in a project and it's not working properly: there's a gap in the top-right corner of the grid. I've tried adjusting the grid width and margins, which results in either one block per row or all blocks being run together (but still with a gap topright.)

It doesn't actually look like the blocks are being rearranged at all, though Masonry is applying its class and assigning absolute positioning to the elements as expected.

I was convinced that I was doing something wrong, but now I'm not so sure. I've taken a working fiddle from a similar question on Stack (http://stackoverflow.com/questions/11695574/jquery-masonry-almost-always-empty-spaces) and carefully modified it to use the dimensions I'm working with, and it just seems to be incapable of handling this selection of elements.

Fiddle: http://jsfiddle.net/dVPA9/4/


Solution

  • As apparently this is an indelible issue with Masonry and similar solutions, I decided I'd need to roll my own here. I also decided this would be better handled in PHP, as the default, floated DIVs will have large gaps in a lot of circumstances.

    Here's the algorithm I used, with comments to explain the fine points. This could have been done in jQuery trivially as well, but on the downside it'd look nasty for users without JavaScript.

    $LeftPos = 0; //Tracks where we are on the grid. Our item grid is three wide, but some items may use up to three units of space.
      $j = 0; //Using a second counter to track total iterations. This is to prevent infinite loops, either because of future concerns I can't predict or because of someone setting a content block to be wider than the containing grid.
    
      for ($i = 0; $i < sizeOf($Items); $i++){
        if ($LeftPos == 3){ $LeftPos = 0; } //If we filled the third column on the last iteration, we loop back round.
        if ($Items[$i]['Placed'] !== true){ //If we've already put this object into the new array, skip it.
          if ($Items[$i]['SpanWidth'] + $LeftPos <= 3  || $j > (sizeOf($Items) * 3)){ //If inserting this would push us past the third column, save it for when we have more room. But if we've looped over the entire array three times, chances are we're stuck for some reason so just vomit everything out so the user can look at SOMETHING, even if it's an ugly page.
            $Placed++; //Increment the counter for placed objects.
            $Items[$i]['Placed'] = true; //Set this item as placed, too.
            $NewProducts[$i] = $Items[$i]; //Add the current item to the new array.
            $LeftPos = $LeftPos+ $Items[$i]['SpanWidth']; //And calculate our new position on the grid.
          }
        }
    
        if (($i+1 == sizeOf($Items) && $Placed < sizeOf($Items))) {$i = 0;} //If we reach the end and we have placed less items than we have total, loop through again.
      }