javascriptjquerycssjquery-masonry

MasonryJS image gallery aligns left on page refresh


So I have this image gallery which I displayed as Pinterest-style Masonry by using MasonryJS. Everything works fine but the problem is when I refresh the page. That is, when I refresh the page, all the images align to the left at first then comes to the actual place. It's like for a couple of milliseconds it goes to that position and comes back to life.

Here's a gif which shows the actual problem:

enter image description here

How can I not have it left-aligned in page refresh? I just wish it to stay in the middle no matter how much I refresh the page.

Here's the code:

jQuery(window).on('load', function(){ 
    $('.modal-grid').masonry({
        itemSelector: '.modal-grid-item',
        gutter: 10,
        isFitWidth: true
    });
});
.modal-grid{
    margin: 0 auto;
    margin-top: 30px;
}

.modal-grid-item { 
    width: 300px; margin-bottom: 10px; 
}

.modal-grid-item img { 
    width: 100%; height: auto; 
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>


<div class="modal-grid">

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/m7M9EPX.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/NzD7YF9.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/8zvUjul.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/WNmP9VL.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/0nwzhDV.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/ypdixv8.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/1oHOvK1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/kpjtht1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/QAQ0dk6.jpg" />
  </div>

    <div class="modal-grid-item">
    <img src="https://i.imgur.com/m7M9EPX.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/NzD7YF9.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/8zvUjul.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/WNmP9VL.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/0nwzhDV.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/ypdixv8.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/1oHOvK1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/kpjtht1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/QAQ0dk6.jpg" />
  </div>
  
    <div class="modal-grid-item">
    <img src="https://i.imgur.com/m7M9EPX.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/NzD7YF9.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/8zvUjul.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/WNmP9VL.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/0nwzhDV.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/ypdixv8.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/1oHOvK1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/kpjtht1.jpg" />
  </div>

  <div class="modal-grid-item">
    <img src="https://i.imgur.com/QAQ0dk6.jpg" />
  </div>

</div>


Solution

  • Masonry has events we can take advantage of, like layoutComplete. I used that to get masonry to load the images while hidden. Once the ready event fires, we trigger Masonry's own layoutComplete event to recalculate the elements. Then we run a callback once to reveal Masonry.

    .modal-grid {
        opacity: 0; /* jQuery will remove this later */
        transition: opacity; /* optional */
    }
    
    jQuery(window).on('load', function() { 
        /* Init your grid like normal but save it to a variable */
        const $grid = $('.modal-grid').masonry({
                itemSelector: '.modal-grid-item',
                gutter: 10,
                isFitWidth: true
            });
        /*
          Add a one time eventListener to just run on our hand-made "onLoad" event
        */
        $grid.one('layoutComplete', function() {
            /* and fade it in */
            $grid.css('opacity', '1');
    
            /*
            If it is still happening, you can
            add a setTimeout to delay the fade effect
            */
            /**
            let timeoutHandle;
            timeoutHandle = setTimeout(function() {
                $grid.css('opacity', '1')
                // clear the timeout to make explicitly
                // sure no extra timers are running
                clearTimeout(timeoutHandle); 
            }, 1000);
            */
        });
        
        $(document).ready(function() {
            // trigger the event when the document elements
            // are ready
            $grid.trigger('layoutComplete');
        });
    });
    

    If you wanna play around with it, you can check out the CodePen here.