Question

I am using Packery.js [ http://packery.metafizzy.co/ ] on a site and am having a few layout issues on page load. I have looked at the documentation for Masonry, Isotope, and Packery (all very similar plugins, all developed by David DeSandro) and it discusses addressing issues where the layout should be triggered after all images are loaded as well as any webfonts.

http://packery.metafizzy.co/appendix.html

I have Packery working just fine with imagesLoaded... but am not sure how to tie in the Google Web Font loader with that. Below is my code for loading fonts, followed by the imagesLoaded Packery Layout. If any one could suggest a way to have Packery fire after both Web Fonts and imagesLoaded, I would be eternally grateful.

// before <body>
<script type="text/javascript">
WebFontConfig = {
    google: {
        families: [ 'Bitter:400,700,400italic:latin' ]
    },
    typekit: {
        id: // hidden for obvious reasons
    }
};
(function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
})();
</script>

// after </body>
// jquery and plugins are loaded prior to the following code
jQuery(document).ready(function($) {

    var $container = $('section.home-page main');

    imagesLoaded( $container, function() {

        $container.packery({
            itemSelector: 'article',
            columnWidth: '.grid-sizer',
            gutter: '.gutter-sizer'
        });

    });

});
Was it helpful?

Solution

It is all about creating the best algorithm to solve your problems , and this requires robust analysis of the problem , then finding all possible solutions , and finally apply the best solution.

The problem :

  • Creating a Masonry effect for your page, which depends on the load of different unrelated elements (webfonts, and images), or in other terms which depends on the asynchronous loading of unrelated page elements.

Possible Algorithms :

  • Load an item (webfont, or images first), and on success load of first item , start to load the other

  • Use Flags, and invoke both load functions asynchronously , based upon returned flags, the developer can decide what to do.

First Algorithm is wrong for sure

  • As in a series call if one call fails for any reason, rest of calls will not take place, because it depends on another item load callback.

  • Time taken to load item will be longer cause events are taking place in a series way, not in a parallel way.

Second algorithm seems ok

Solution :

Referring to both docs for webfontloader , imagesLoaded

  1. Create two flag variables

    var imagesAreLoaded = false , fontsAreLoaded = false

  2. Set each flag true on a successful callback for load event

for webfontloader if you want to give highest priority to the font that will be used only in your packery plugin then you should use fontactive, if the plugin depends on more than one family you better use active :

WebFontConfig = {  
  active: function() { // set fontsAreLoaded to true here }, 
  fontactive: function(familyName, fvd) { // set fontsAreLoaded to true here } 
};

WebFontConfig is the object you pass to webfontloader load method.

  1. Do same for imagesLoaded event

    $('#container').imagesLoaded()
    .done( function( instance ) { //set imagesAreLoaded to true here })

please note that imagesLoaded jQuery plugin returns a jQuery Deferred object. This allows you to use .always(), .done(), .fail() and .progress(), similarly to the emitted events.

  1. Usually everything should run fine, and usually fonts will load before the images will, but a good developer should handle all possible scenarios.

    $(document).load(function() {
    // if both flags are true , go ahead and load your masonry. // else if either of flags is false, show a warning, retry loading , or whatever you think is better })

Note : My answer doesn't really provide much coding , because from what i think the documents for both plugins are very clear , but i think the issue was how to handle the problem using correct algorithm.

OTHER TIPS

This works perfectly.

<script>
  function loadIsotope(){
      var $container = $('section.home-page main');

      imagesLoaded( $container, function() {

          $container.packery({
              itemSelector: 'article',
              columnWidth: '.grid-sizer',
              gutter: '.gutter-sizer'
          });
      });
  }

  WebFont.load({
    google: {
      families: ['Bitter']
    },
    active: function() {
        // This event is triggered when the fonts have rendered.
        loadIsotope();
    },
    inactive:function(){
        // This event is triggered when the browser does not support
        // linked fonts or if none of the fonts could be loaded.
        loadIsotope();
    }
  });
</script>

Just like ProllyGeek said, async solution is more reasonable. Code could look something like this (I tested – it works):

<script>
var loadedImages = false;
var loadedFonts = false;

function loadedEverything() {
        return (loadedImages && loadedFonts);
}

function loadMasonry() {
        console.log("Loading masonry");
}

WebFontConfig = {
        google: {
                families: ['Droid Sans']
        },
        active: function() {
                loadedFonts = true;
                if (loadedEverything()) loadMasonry();
        }
};

imagesLoaded( document.querySelector('.container'), function(instance) {
        loadedImages = true;
        if (loadedEverything()) loadMasonry();
});
</script>

Whatever loads slower will fire the event you need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top