Christoph
Christoph

Reputation: 1377

Dynamic columnWidth causing stacked images in Masonry

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).

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:

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?

Upvotes: 1

Views: 1510

Answers (2)

Christoph
Christoph

Reputation: 1377

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.

Upvotes: 1

Gregg Duncan
Gregg Duncan

Reputation: 2725

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.

Upvotes: 1

Related Questions