this is my first post, I’ve been stuck with this issue for about a year now, not getting anywhere.
I’m trying to create a personal portfolio page using the ‘Masonry gallery cards responsive’ component by Diego Meg. I’m not using the CSS only approach because I want to have newer items in the top row.
After encountering the classic image overlap issue (the layout is calculated before the image sizes are known, when initially loading) I found out about imagesloaded.js and tried to integrate it.
I can’t get it to work.
The script seems to get executed (it writes the log messages) but “$grid.masonry(‘layout’);” doesn’t seem to recalculate the layout. Only reloading or resizing fixes the layout.
Is it maybe a problem that I’m using carousels instead of images in my cards?
I’d appreciate a heads-up,
thanks!
Here’s what I put in the custom code area in BSS:
<!-- Include jQuery -->
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Include imagesLoaded script -->
<script src="https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.min.js"></script>
<!-- Include Masonry script -->
<script src="https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous" sync></script>
<script>
$(document).ready(function() {
console.log('Document is ready');
// Initialize Masonry
var $grid = $('.grid');
console.log('Grid:', $grid);
$grid.masonry({
itemSelector: '.grid-item',
percentPosition: true,
columnWidth: '.grid-sizer'
});
console.log('Masonry initialized');
// Ensure Masonry layout is triggered after each image loads
$grid.imagesLoaded().progress(function() {
console.log('Image loaded');
$grid.masonry('layout');
$grid.masonry();
console.log('Masonry layout triggered');
});
// Safari still has overlaps, can I trigger after some time?
setTimeout(function() {
$grid.masonry('layout');
console.log('Masonry layout triggered after 2sec');
}, 2000);
setTimeout(function() {
$grid.masonry('layout');
console.log('Masonry layout triggered after 4sec');
}, 4000);
setTimeout(function() {
$grid.masonry('layout');
console.log('Masonry layout triggered after 6sec');
}, 6000);
setTimeout(function() {
$grid.masonry('layout');
console.log('Masonry layout triggered after 8sec');
}, 8000);
setTimeout(function() {
$grid.masonry('layout');
$grid.masonry();
console.log('Masonry layout triggered after 12sec');
}, 12000);
});
</script>
Thank you for your efforts, @kuligaposten ,
I played around with your file and had some insights,
but I would have had to restructure everything.
The CSS approach doesn’t have the item sorting ability of the javascript masonry.
So after researching for some more hours,
I found out that I was just calling the wrong elements in my existing script.
And I have to init the masonry before the imagesLoaded function.
<script>
// init Masonry first?
$('.row').masonry();
// layout Masonry after each image loads
$('#projects-section').imagesLoaded().progress( function() {
$('.row').masonry('layout');
});
</script>
Most solutions I found tried to call the masonry via “$grid.masonry({…”
which doesn’t seem to work the way it is set up in this particular BSS component.
In your project section, you initialize Masonry both with a data attribute and with JavaScript. Masonry and imagesLoaded do not depend on jQuery; only your inline script relies on jQuery. It should be easy to convert this to vanilla JavaScript and eliminate the need for jQuery.
You are loading imagesLoaded twice: once in a JavaScript file and again in your inline script. Additionally, you have images that are 1.5 MB in size. You could optimize these images and set a proper size for the webpage.
You have two Masonry grids on your page, which means there should normally be two global listeners from masonry.js. However, the way you set it up, you have 18 global listeners from masonry.js.