How to add image gallery to shopify blog posts
How to add a gallery to blog posts of shopify v2
For the past few months, I have been working on a Shopify website. Recently, my client has begun investing in content marketing. However, in the last two weeks, they complained that the content manager was unable to add an image gallery to blog posts.
After conducting some research, I was surprised to discover that Shopify does not allow users to add galleries to a blog post. The platform only provides a rich text editor and the ability to add single images.
Some people suggest migrating to a proper blogging solution like WordPress. However, this solution did not work for me as it would require more effort. Therefore, I decided to create a hacky but easy-to-use solution.
Solution
The solution only requires one JavaScript and one CSS file. Once it is set up, you won't need any coding skills to use it. I believe even someone without coding experience can handle the setup.
How to set up
- To add CSS styles for the gallery to your website, create a separate file named "blog-carousell.css" in the assets folder. This file should contain only CSS styles for the gallery and no 3rd party dependencies.
/* Slideshow container */
.slideshow__photo {
max-width: 500px;
position: relative;
margin: auto;
}
.slideshow-container {
margin-bottom: 32px;
}
/* Next & previous buttons */
.slideshow__prev, .slideshow__next {
cursor: pointer !important;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 16px;
color: white !important;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease !important;
border-radius: 0 3px 3px 0 !important;
user-select: none !important;
}
/* Position the "next button" to the right */
.slideshow__next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.slideshow__prev:hover, .slideshow__next:hover {
background-color: rgba(0,0,0,0.8);
}
.slideshow__thumbnails {
display: flex;
justify-content: center;
}
.slideshow__thumbnails img {
max-width: 200px;
max-height: 170px;
margin-left: 3px;
margin-right: 3px;
cursor: pointer;
}
- Add a JavaScript file that will initialize the galleries. More details on how it works will be provided later.
function slideShowChangeImage(e) {
const newUrl = e.src;
const img = e.parentNode.parentNode.getElementsByClassName('slideimg');
img[0].src=newUrl;
}
function slideShowPrev(e) {
changeToNextOrPrevImage(e, -1);
}
function slideShowNext(e) {
changeToNextOrPrevImage(e, 1);
}
function getAllGalleryImages(parent) {
const images = parent.getElementsByClassName('gallery-thumbnail');
let allUrls = [];
for (let i = 0; i < images.length; ++i) {
allUrls.push(images[i].src);
}
return allUrls;
}
function changeToNextOrPrevImage(e, change){
// get all available images
// try to find the next one
let allUrls = getAllGalleryImages(e.parentNode.parentNode);
const img = e.parentNode.getElementsByClassName('slideimg');
const currentUrl = img[0].src;
const pos = allUrls.findIndex(v => currentUrl === v);
let nextSlide = pos + change;
if (nextSlide < 0) {
nextSlide = allUrls.length - 1;
} else {
nextSlide = nextSlide % allUrls.length;
}
img[0].src = allUrls[nextSlide];
}
function initImageGalleries() {
for (let i = 0; i <= 15; ++i) {
createGallery(i.toString().padStart(2, '0'));
}
}
function createGallery(id) {
// get galleries grouped by number
let allImages = document.querySelectorAll(`img[alt*="gallery ${id}"]`);
let imgInCurrentGallery = [];
let parent;
let galleryStartNode = null;
// delete the old images
for(let i = 0; i < allImages.length; ++i) {
const img = allImages[i];
imgInCurrentGallery.push(allImages[i].cloneNode(true));
parent = img.parentNode.parentNode;
if (!galleryStartNode) {
galleryStartNode = img.parentNode.nextSibling;
console.log(galleryStartNode);
}
img.parentNode.remove();
}
if (allImages.length > 0) {
buildGalleryHtml(parent, galleryStartNode, imgInCurrentGallery);
}
return allImages.length > 0;
}
function buildGalleryHtml(parent, insertBefore, imgs) {
// class="slideshow-container"
const container = document.createElement('div');
container.className = 'slideshow-container';
// init controls
const controlsHtml = ` <div class="slideshow__photo">
<div class="mySlides">
<img class="slideimg" src="" style="width:100%">
</div>
<a class="slideshow__prev" onclick="slideShowPrev(this)">❮</a>
<a class="slideshow__next" onclick="slideShowNext(this)">❯</a>
<br>
</div>`;
container.innerHTML = controlsHtml;
// init thumbnails
const thumbNailsSection = document.createElement('div');
thumbNailsSection.className = 'slideshow__thumbnails';
container.append(thumbNailsSection);
for(let i = 0; i < imgs.length; ++i) {
const img = document.createElement('img');
img.className = 'gallery-thumbnail';
img.src = imgs[i].src;
img.addEventListener('click', () => slideShowChangeImage(img));
thumbNailsSection.appendChild(img);
}
// set image to the first
const img = container.getElementsByClassName('slideimg');
img[0].src = imgs[0].src;
parent.insertBefore(container, insertBefore);
}
document.addEventListener('DOMContentLoaded', () => initImageGalleries());
- Next, you need to add these two files to your website. I suggest adding them only to your blog pages…
{{ 'blog-carousell.css' | asset_url | stylesheet_tag }}
<script src="{{ 'blog-carousell.js' | asset_url }}" defer="defer"></script>
- If you would like to add a gallery to your blog post, you will need to add an 'alt' attribute to the images. The alt attribute should end with 'gallery {id}', where the id is a number between 01 and 15 (leading zeros are required).
For example, I have multiple galleries within the same post. The images in the first gallery have alt texts such as "First Beef image, gallery 01" and "Another Beef image, gallery 01". The images in another gallery have alt texts like "Pork, gallery 02" and "Pork, gallery 02".
How it works
The JavaScript file attempts to group all images presented on the page based on their "alt" attributes. It then creates the required DOM elements and attaches event handlers.
Demo
The demo could be found here Wine bars in Singapore