@Ricky et al,
I’d welcome a native robust image gallery as well! In the meantime, I’ve cobbled together a masonry gallery with lightbox to suit a current project of mine.
I have an Airtable attachment field containing my desired photos, and on my details page, I pull this field in via a normal image gallery field, using a javascript to hide it and its parent.
Note that it’s the second n gallery, as my details page has a primary photo gallery as its header.
Then, I have a script that rips all the network resources from the hidden, full gallery of photos, and loads them into a lightbox/masonry gallery as such via a custom code block that contains the div below. Note that the script ignores the first resource (to avoid a redundant image load that’s already in the header).
<div class="gallery">
<div class="gallery-sizer"></div>
</div>
<script>
window.addEventListener('load', () => {
let attempt = 0;
const maxAttempts = 10;
const intervalTime = 300;
// Function to hide the second occurrence of .gallery-container and its parent container
const hideSecondGalleryContainer = () => {
const galleryContainers = document.querySelectorAll('.gallery-container');
if (galleryContainers.length > 1) {
const secondGalleryContainer = galleryContainers[1];
const parentContainer = secondGalleryContainer.parentElement;
parentContainer.style.display = 'none';
console.log('Second .gallery-container and its parent hidden.');
} else {
console.log(`Attempt ${attempt + 1}: .gallery-container not found.`);
attempt++;
if (attempt < maxAttempts) {
setTimeout(hideSecondGalleryContainer, intervalTime);
} else {
console.log('Max attempts reached. .gallery-container not found.');
}
}
};
// Initial call to the function
hideSecondGalleryContainer();
});
</script>
<!-- Lightbox2 CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.3/css/lightbox.min.css" rel="stylesheet" />
<!-- Lightbox2 JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.3/js/lightbox.min.js"></script>
<!-- Masonry JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js"></script>
<script>
window.addEventListener('load', () => {
let imageUrls = [];
// Function to extract images from the document
const extractImages = () => {
const initialImgs = document.querySelectorAll('img');
initialImgs.forEach((img) => {
if (img.src.startsWith('https://v5.airtableusercontent.com')) {
imageUrls.push(img.src); // Add image URL to the array
}
});
};
// Create a MutationObserver to watch for changes in the network requests
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) { // Check if the node is an element
// Look for img elements
const imgElements = node.querySelectorAll('img');
imgElements.forEach((img) => {
if (img.src.startsWith('https://v5.airtableusercontent.com')) {
imageUrls.push(img.src); // Add image URL to the array
}
});
}
});
}
});
});
// Observe changes in the body of the document
observer.observe(document.body, {
childList: true,
subtree: true,
});
// Initial extraction in case images are already present
extractImages();
// Wait for a short duration to ensure all images are captured
setTimeout(() => {
imageUrls.shift(); // Remove the first image URL
const galleryContainer = document.querySelector('.gallery');
imageUrls.forEach((url, index) => {
const galleryItem = document.createElement('div');
galleryItem.classList.add('gallery-item');
const link = document.createElement('a');
link.href = url;
link.setAttribute('data-lightbox', 'gallery'); // Lightbox attribute
link.setAttribute('data-title', `Image ${index + 1}`); // Optional: Add title
const img = document.createElement('img');
img.src = url;
link.appendChild(img);
galleryItem.appendChild(link);
galleryContainer.appendChild(galleryItem);
});
// Initialize Masonry after images are added
new Masonry(galleryContainer, {
itemSelector: '.gallery-item',
columnWidth: '.gallery-sizer', // Ensure the column width is set properly
percentPosition: true,
gutter: 20 // Add vertical gaps
});
}, 2000); // Adjust the delay as needed
});
</script>
<style>
.gallery {
width: 100%;
margin: 0 auto;
}
.gallery-sizer,
.gallery-item {
width: calc(25% - 20px); /* Adjusted for the gap */
box-sizing: border-box;
}
.gallery-item {
margin-bottom: 20px; /* Vertical gap */
}
.gallery-item img {
width: 100%;
display: block;
}
@media (max-width: 993px) {
.gallery-sizer,
.gallery-item {
width: calc(50% - 20px);
}
}
@media (max-width: 600px) {
.gallery-sizer,
.gallery-item {
width: calc(100% - 20px);
}
}
.lb-caption {
display: none !important;
}
</style>
While it’s not the typical slider gallery you are requesting, it hopefully helps demonstrate the power of custom blocks and custom headers/footers.
Cheers!