-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgallery-masonry.js
More file actions
108 lines (94 loc) · 3.49 KB
/
Copy pathgallery-masonry.js
File metadata and controls
108 lines (94 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* Gallery Masonry Layout Script (gallery-masonry.js)
*
* Purpose:
* Provides masonry-style layout fallback for browsers that don't yet support
* CSS Grid masonry. Calculates optimal row spans for each image based on its
* height to pack images tightly without gaps.
*
* How it works:
* 1. Checks if browser supports CSS Grid masonry (currently only Firefox)
* 2. If not supported, waits for all images to load
* 3. Calculates row span for each image based on its height
* 4. Applies grid-row-end style to position images correctly
* 5. Recalculates on window resize (debounced for performance)
*
* Browser support:
* - Native masonry: Firefox with layout.css.grid-template-masonry-value.enabled
* - Fallback: All browsers with CSS Grid support (Chrome, Safari, Edge, etc.)
*
* Dependencies:
* - _sass/_gallery.scss: defines grid-auto-rows: 5px for precise calculations
* - gallerylay.html: includes this script
*/
(function() {
'use strict';
/**
* Calculate and set row span for a single gallery item
* @param {HTMLElement} item - Gallery card element containing an image
*/
function resizeGridItem(item) {
const grid = document.querySelector('.gallery-container');
if (!grid) return;
const rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows'));
const rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('gap'));
const img = item.querySelector('.gallery-img');
if (!img) return;
const contentHeight = img.getBoundingClientRect().height;
const rowSpan = Math.ceil((contentHeight + rowGap) / (rowHeight + rowGap));
item.style.gridRowEnd = 'span ' + rowSpan;
}
/**
* Recalculate row spans for all gallery items
* Called on window resize events
*/
function resizeAllGridItems() {
const allItems = document.querySelectorAll('.gallery-card');
allItems.forEach(item => resizeGridItem(item));
}
/**
* Initialize masonry layout
* Detects browser support and applies fallback if needed
*/
function initMasonry() {
// Check if browser supports CSS Grid masonry
if (CSS.supports && CSS.supports('grid-template-rows', 'masonry')) {
// Native masonry support, no JavaScript needed
return;
}
// Fallback: calculate row spans with JavaScript
const images = document.querySelectorAll('.gallery-img');
let loadedCount = 0;
const totalImages = images.length;
if (totalImages === 0) return;
// Wait for each image to load before calculating its row span
images.forEach(img => {
const checkLoaded = () => {
loadedCount++;
resizeGridItem(img.closest('.gallery-card'));
// Once all images loaded, do final adjustment
if (loadedCount === totalImages) {
setTimeout(resizeAllGridItems, 100);
}
};
if (img.complete) {
checkLoaded();
} else {
img.addEventListener('load', checkLoaded);
img.addEventListener('error', checkLoaded); // Handle failed loads
}
});
// Recalculate on window resize (debounced to avoid performance issues)
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(resizeAllGridItems, 250);
});
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initMasonry);
} else {
initMasonry();
}
})();