Dynamic columnWidth causing stacked images in Masonry

1.3k Views Asked by At

I am trying to recreate the masonry blog view from Unify in Rails 4. http://htmlstream.com/preview/unify-v1.8/blog_masonry_3col.html

I bought the theme and included the latest imagesLoaded and Masonry files within my application (using bower-rails).

  • Masonry PACKAGED v3.3.2
  • imagesLoaded PACKAGED v3.2.0

When using the with the theme supplied js file all images are stacked on top of each other.

screenshot 1 stacked on eachother

$(document).ready(function(){
    var $container = $('.grid-boxes');

    var gutter = 30;
    var min_width = 300;
    $container.imagesLoaded( function(){
        $container.masonry({
            itemSelector : '.grid-boxes-in',
            gutterWidth: gutter,
            isAnimated: true,
              columnWidth: function( containerWidth ) {
                var box_width = (((containerWidth - 2*gutter)/3) | 0) ;

                if (box_width < min_width) {
                    box_width = (((containerWidth - gutter)/2) | 0);
                }

                if (box_width < min_width) {
                    box_width = containerWidth;
                }

                $('.grid-boxes-in').width(box_width);

                return box_width;
              }
        });
    });
});

See this js fiddle: http://jsfiddle.net/sdynfq83/

I noticed following things:

  • Resizing the window or refreshing does not correct the issue so I figured out it is not an images loaded error. This took me a long time to figure this out.
  • My html code seems alright since I have the same problems if I copy the HTML code from the theme itself and include the same JS and CSS files.
  • the ".grid-boxes-quote" boxes don't have the same width as the other grid boxes. Which is strange because they should all be the same since all boxes have the ".grid-boxes-in" class. https://jsfiddle.net/sdynfq83/embedded/result/

When removing the columnWidth code and replacing it by a fixed number (300) + adding width to the grid-boxes-in then it seems to work. This is not what I want since the images sizes are not correct anymore.

css

.blog_masonry_3col .grid-boxes-in {
    padding: 0;
    margin-bottom: 30px;
    border: solid 1px #eee;
    /* added width */
    width: 300px;

}

js

$(document).ready(function(){
    var $container = $('.grid-boxes');

    var gutter = 30;
    var min_width = 300;
    $container.imagesLoaded( function(){
        $container.masonry({
            itemSelector : '.grid-boxes-in',
            gutterWidth: gutter,
            isAnimated: true,
              /*columnWidth: function( containerWidth ) {
                var box_width = (((containerWidth - 2*gutter)/3) | 0) ;

                if (box_width < min_width) {
                    box_width = (((containerWidth - gutter)/2) | 0);
                }

                if (box_width < min_width) {
                    box_width = containerWidth;
                }

                $('.grid-boxes-in').width(box_width);

                return box_width;
              }*/
            columnWidth: 300
        });
    });
});

js fiddle: http://jsfiddle.net/8c0r06a6/2/

The theme itself supplies an older version of masonry. In which the code seems to work. The images do keep overlapping (this can be fixed by resizing or refreshing the window).

Screenshot 2 overlapping images screenshot 3 enter image description here

I however want to update to the latest version of masonry and images loaded so I can keep using bower to easily update those files. I am also hoping that using the latest version of everything fixes the overlapping images in screenshot 2. I have a working JS fiddle below with the old code.

/**
 * jQuery Masonry v2.1.05
 * A dynamic layout plugin for jQuery
 * The flip-side of CSS Floats
 * http://masonry.desandro.com
 *
 * Licensed under the MIT license.

http://jsfiddle.net/ytLf3bue/1/

Summarized I have following questions, please bear in mind that I am a beginning hobby coder and I do not have a lot of JS experience:

  1. Is it a smart idea to always use the latest version of the Masonry and ImagesLoaded code or should I just stick with the supplied files?
  2. If 1. is yes => how do I fix the code so the images are not stacked on eachother anymore?
  3. If 1. is no => how do I fix the code so the overlapping images and background bleed in screenshot 2 and 3 are gone?
2

There are 2 best solutions below

0
Christoph On BEST ANSWER

David Desandro answered me himself.

$(document).ready( function() {
  // init Masonry after all images have loaded
  var $grid = $('.grid').imagesLoaded( function() {
    $grid.masonry({
      itemSelector: '.grid-item',
      percentPosition: true,
      gutter: 20,
      columnWidth: '.grid-sizer'
    });
  });

});

In Masonry v3, columnWidth no longer accepts a function. Instead, use element sizing for responsive layouts.

Here's a demo http://codepen.io/desandro/pen/f3451d70f80c35812b33956785ee152c/

This fixes the issue.

2
Gregg Duncan On

Anytime you are dealing with masonry, instead of using:

$(document).ready(function(){ ... go masonry ... }

use:

$(window).load(function(){ ... go masonry ... }

http://jsfiddle.net/sdynfq83/2/

$(document).ready triggers as soon as the DOM is completely loaded. That does not include loading of resources like images. Masonry calculates the absolute positioning of images based on their widths and heights. If it runs before the actual image is loaded it sees the image tag as an element with zero width and height. There for it only offsets for the gutter between and the images end up stacked.

$(window).load triggers once all page resources have finished loading. This allows Masonry to get the correct dimensions of all objects before it tries to place them.