Masonry JS Overlapping Items
Asked Answered
G

8

24

I have a very strange problem in here: [Referral Link Removed]. The first row product items overlapped with the items in the second row.

The masonry items are below the homepage above the footer. As you can see, it looks different with Chrome. In firefox, it looks good.

Here's how it looks in my chrome: http://clip2net.com/s/5LIRko

My jQuery Code is:

jQuery(function($){
var $container = $('.woocommerce ul.products');
    $container.masonry({
          columnWidth:10, 
          gutterWidth: 15,
          itemSelector: '.product-category'
    });
});

Is there any css rule which affects the row output ?

Guthrey answered 17/9, 2013 at 11:59 Comment(4)
Just curious, what are you using masonry for? They all look to be the same size. Nothing "masonry" about it. If I disable Javascript on the page and refresh, the grid layout looks as expected.Aranda
Yes but I'm asking why you even need masonry. I see the error, but I don't see what masonry is solving for you over just floating your elements. See my answer below.Aranda
I used masonry so that it will look good in its responsive part. I just wanna put masonry for the animation feature when resized.Guthrey
Ok, fair enough. Then see my responses below for option #2, namely jQuery(window).on('load'Aranda
A
70

The problem is your images. By the time masonry is called, your images haven't loaded. So it's assuming the height of your elements WITHOUT the height of the image being factored in.

If you refresh your screen after the images are already cached, you'll see that it loads correctly. If you then clear cache and refresh, you'll see they overlap again.

Four Five options:

  • Wait until the images are finished loading (there are plugins that you can wait until all images inside a certain div are loaded, for example)
  • Wait for the load event instead of the ready event. Instead of using jQuery(function($){ use jQuery(window).on('load', function(){ var $ = jQuery; and you'll see the results.
  • Re-apply masonry after the images load (Don't like this one... you'd see flicker)
  • My favorite, don't use masonry here! Disable JS on your page and look at the layout. It's what you want. All the divs are even heights and even widths. There's not really a reason to use masonry here. Just float your elements and let them display in the grid naturally.
  • EDIT: another option. Specify a height of the divs so the height doesn't depend on the images it's loading.
Aranda answered 17/9, 2013 at 12:7 Comment(6)
i think thats the problem. Because there are times, when I reload, it loads successfully.Guthrey
how can will i write it correctly? Im not very good in javascript.Guthrey
I added a fifth option. And how to write it, I already said. Replace jQuery(function($){ that line with jQuery(window).on('load', function($){ that line that wraps around your masonry call (the code you posted in your Q)Aranda
An error appeared when I applied the second option, it says: "Uncaught TypeError: object is not a function."Guthrey
Yea sorry, bad copy paste on my part. I've updated my answer. That first line should be jQuery(window).on('load', function(){ var $ = jQuery;Aranda
terrific! This worked perfectly: "Wait for the load event instead of the ready event. Instead of using jQuery(function($){ use jQuery(window).on('load', function(){ var $ = jQuery; and you'll see the results."Hokanson
C
17

You need to initiate Masonry after all images are loaded. If you are using jQuery try:

var $container = $('#container');
// initialize Masonry after all images have loaded  
$container.imagesLoaded( function() {
  $container.masonry();
});

for other options see Masonry docs - http://masonry.desandro.com/layout.html#imagesloaded

Carryingon answered 16/10, 2014 at 15:54 Comment(0)
C
3

Use the ImagesLoaded library, is made specially to reorganize the blocks when each image is loaded.

You can download it from:

https://github.com/desandro/imagesloaded

Cami answered 28/4, 2016 at 4:36 Comment(1)
can you add more details on how it is used.Firecracker
T
2

I've solved this issue with a settimeout function. By allowing a second or so to pass (depending on the # and file size of the images being downloaded) you can download the images first then apply masonry.

                $(document).ready(function(){                                                                                                                   
                setTimeout(function() { masonry_go();masonry_go2();}, 1000);                                                                    
            });     
            $(window).resize(function() 
            {
                // jQuery
                $('.grid').masonry( 'destroy')
                $('.grid2').masonry( 'destroy')                 
                setTimeout(function() { masonry_go();masonry_go2();}, 1000);                                                                    
            });                 
            function masonry_go(){
                $('.grid').masonry({
                  // options
                  itemSelector: '.grid-item',
                  columnWidth: 300
                });                         
            }       
            function masonry_go2(){
                $('.grid2').masonry({
                  // options
                  itemSelector: '.grid-item2',
                  gutter: 15,
                  columnWidth: 200
                });                         
            }       
Thousandfold answered 6/11, 2015 at 21:12 Comment(2)
Thanks your solution works after replacing document.ready with jQuery(window).on('load', function(){Workingman
masonry('destroy') is an effective solution before loading second time.Wismar
A
2

Add minimum height for images with CSS. That would fix the issue.

.image{ min-height: 250px; }
Asexual answered 10/4, 2019 at 7:33 Comment(0)
R
0

Loading masonry after window load works for me.

jQuery(window).on('load', function(){
    //masonry init and options
    // .. codes
}
Rockery answered 30/7, 2018 at 8:21 Comment(0)
K
0

it's most likely because u're importing the js too soon and it doesn't have a target to be executed on, try to add "defer" to the import, u can do like this:

<script type='text/javascript' src='src/js/mensory-min.js' defer></script>

the key is adding defer at the end of the imprort which will make it load after the entire page has loaded.

P.S. giving a height to the grid-item won't solve anything cuz it is in position absolute

Kenay answered 23/9, 2022 at 9:22 Comment(0)
C
-2

$(window).on('load',function(){ });

$(window).on('load',function(){
//code
});

//use load event instead of document.ready starting of jquery
Courses answered 3/5, 2020 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.