10

I'm a js newbie and hope this questions doesn't seem too stupid.

I'm using masonry for my site - works fine. I wanted to let my boxes appear just when masonry finished loading. Searching in the internet I found several posts recommending to use imagesloaded Plugin to solve this issue. It just doesn't change anything. That means: my layout and content boxes keep being messed up until masonry finished loading, just then the boxes suddenly jump to their right positions.

My code:

$(document).ready(function() {

    var $container = $('#post-area');
    $container.imagesLoaded( function() {
        $container.masonry({
            itemSelector : '.box',
            columnwidth: 300,
            gutter: 20,
            isFitWidth: true,
            isAnimated: !Modernizr.csstransitions
        });    
    });
});

I'm also getting this firebug-error:

TypeError: EventEmitter is not a constructor
ImagesLoaded.prototype = new EventEmitter();

I'm loading the imagesloaded js like this at the end of my website (I couldn't find any information if imagesloaded is already included in masonry or not, some wrote that it's not included anymore - confusing):

<script src="http://www.domainname.com/js/imagesloaded.js"></script>

I would be really happy if someone could help me. And tell me if imagesloaded is even the right plugin to solve this issue!

Daedalus
  • 7,518
  • 3
  • 29
  • 56
CaraMar
  • 197
  • 1
  • 3
  • 17

3 Answers3

15

imagesLoaded is not included in Masonry, so you should use separate plugin. I would recommend to use compiled .min version.

Regarding your problem with stacked images: the problem is not in imagesLoaded neither Masonry. In your code imagesLoaded is waiting until all images loaded and then fires masonry. Having all images loaded, Masonry plugin can properly define their sizes and put on grid. Before that, browser loads images as usually and display 'em according to defined CSS, that's why they're messed up.

One of the possible solution is to hide elements by default and then fadein while imagesLoaded confirm, that images loaded:

$(document).ready(function() {

  var $boxes = $('.box');
  $boxes.hide();

  var $container = $('#post-area');
  $container.imagesLoaded( function() {
    $boxes.fadeIn();

    $container.masonry({
        itemSelector : '.box',
        columnwidth: 300,
        gutter: 20,
        isFitWidth: true,
        isAnimated: !Modernizr.csstransitions
    });    
  });
});
Leger
  • 1,184
  • 8
  • 7
  • Thanks Leger. This helped me a lot. I just put the .box by default hidden in css (display:none) and let it appear as you suggested with jquery fadeIn. Otherwise it always appeared for a millisecond before it was hidden again. – CaraMar Feb 13 '14 at 14:10
  • .Packaged (minified) version worked for me: http://imagesloaded.desandro.com/imagesloaded.pkgd.min.js – Volker E. Feb 16 '15 at 09:52
8

Another solution is to initialize Masonry inside $(window).load() instead of $(document).ready(). This will trigger Masonry after all the media on the page has loaded – images, fonts, external scripts and stylesheets, etc.

$(window).load(function(){
    $('#container').masonry({
        // options...
    });
});
user2572094
  • 190
  • 3
  • 10
  • 2
    I'm using infinite-scroll, is there a way for the dynamically appended html to be processed by masonry after all the media on the page load? – Ray Jun 11 '15 at 18:43
  • 1
    This doesn't work for dynamic content. $(window).load will only fire one time. – Triynko Nov 25 '15 at 20:09
0

Install

npm install masonry-layout --save

npm install imagesloaded --save

Then vanilla js options would be

'use strict'

const Masonry = require('masonry-layout')
const imgloaded = require('imagesloaded')
const elem = document.querySelector('.grid')
var imgLoad = imgloaded( elem )
    function onAlways() {
        const msnry = new Masonry( elem, {
            // options
            columnWidth: '.grid-sizer',
            // do not use .grid-sizer in layout
            itemSelector: '.grid-item',
            percentPosition: true,
            gutter: 10
        })
    // console.log('all images are loaded')
}
if (elem) {
    // bind with .on()
    imgLoad.on( 'always', onAlways )
    // unbind with .off()
    // imgLoad.off( 'always', onAlways )
}

Then check the console for all images are loaded.

Frithir.com
  • 225
  • 2
  • 13