WooCommerce Custom Theme: Enqueuing PhotoSwipe for Awesome Product Galleries (The Easy Way!)
So, you’re building a fantastic WooCommerce store with your very own custom theme? Awesome! But maybe you’ve noticed your product image galleries are a bit… basic. You want that smooth, swipeable, zoomed-in goodness that modern shoppers expect. That’s where PhotoSwipe comes in!
This article will guide you through easily enqueuing PhotoSwipe in your WooCommerce custom theme. No complicated coding jargon – just clear, practical steps. We’ll turn your bland product galleries into eye-catching, engaging experiences.
Why PhotoSwipe?
Imagine you’re selling high-end watches online. A potential customer wants to admire the intricate details of the watch face. Without PhotoSwipe, they might see a small, static image. With PhotoSwipe, they can zoom in, swipe through multiple angles, and feel like they’re holding the watch in their hands.
PhotoSwipe is a free, responsive, and modular JavaScript image gallery that’s perfect for WooCommerce. It offers:
- Mobile-Friendly Design: Works flawlessly on phones and tablets.
- Touch Support: Swiping, pinching to zoom – the natural gestures your customers expect.
- Customization: Easily tweak the look and feel to match your brand.
- Performance: Optimized for fast loading speeds.
- `photoswipe.css`
- `photoswipe.min.js`
- `photoswipe-ui-default.min.js`
- `default-skin.png` (and other image files from the `default-skin` subfolder inside `dist/default-skin`)
Step 1: Download PhotoSwipe Files
First things first, we need the PhotoSwipe files. You can download them from the official website: [https://photoswipe.com/](https://photoswipe.com/). Grab the “PhotoSwipe Core” version.
Unzip the downloaded file. Inside, you’ll find folders like `dist` and `src`. We’ll primarily need the contents of the `dist` folder.
Step 2: Organize Your Theme Files
Create a folder named `photoswipe` within your theme’s directory. This is a common practice for organizing external libraries. Copy the following files from the `dist` folder into your theme’s `photoswipe` folder:
Your theme’s file structure should now look something like this:
your-theme/
├── photoswipe/
│ ├── photoswipe.css
│ ├── photoswipe.min.js
│ ├── photoswipe-ui-default.min.js
│ ├── default-skin.png
│ └── … (other image files)
├── style.css
├── functions.php
└── …
Step 3: Enqueue PhotoSwipe CSS and JavaScript
This is the most important step. We need to tell WordPress to load the PhotoSwipe files. Open your theme’s `functions.php` file. We’ll use the `wp_enqueue_scripts` action to do this.
Add the following code snippet to your `functions.php` file:
<?php
function my_theme_enqueue_photoswipe() {
// Check if we’re on a single product page. No need to load PhotoSwipe otherwise!
if ( is_product() ) {
// Enqueue PhotoSwipe CSS
wp_enqueue_style( ‘photoswipe-css’, get_stylesheet_directory_uri() . ‘/photoswipe/photoswipe.css’ );
// Enqueue PhotoSwipe Default Skin CSS
wp_enqueue_style( ‘photoswipe-default-skin-css’, get_stylesheet_directory_uri() . ‘/photoswipe/default-skin/default-skin.css’ ); // Or photoswipe-ui-default.css if you prefer
// Enqueue PhotoSwipe JavaScript
wp_enqueue_script( ‘photoswipe-js’, get_stylesheet_directory_uri() . ‘/photoswipe/photoswipe.min.js’, array( ‘jquery’ ), false, true ); // Dependencies: jQuery, load in footer
// Enqueue PhotoSwipe UI Default JavaScript
wp_enqueue_script( ‘photoswipe-ui-default-js’, get_stylesheet_directory_uri() . ‘/photoswipe/photoswipe-ui-default.min.js’, array( ‘photoswipe-js’ ), false, true ); // Dependencies: photoswipe-js, load in footer
// Enqueue your custom JavaScript to initialize PhotoSwipe (see Step 4)
wp_enqueue_script( ‘my-theme-photoswipe-init’, get_stylesheet_directory_uri() . ‘/js/photoswipe-init.js’, array( ‘photoswipe-js’, ‘photoswipe-ui-default-js’ ), false, true ); //Load after PhotoSwipe script
}
}
add_action( ‘wp_enqueue_scripts’, ‘my_theme_enqueue_photoswipe’ );
?>
Explanation of the code:
- `my_theme_enqueue_photoswipe()`: This is the function we’re creating to enqueue the PhotoSwipe files. You can name it whatever you like, but keep it descriptive.
- `is_product()`: This crucially important conditional tag ensures that PhotoSwipe is only loaded on single product pages. This prevents unnecessary files from loading on other pages, improving your website’s performance.
- `wp_enqueue_style()`: This function tells WordPress to load the CSS files.
- The first argument is a unique handle for the stylesheet (e.g., ‘photoswipe-css’).
- The second argument is the URL to the stylesheet file. We use `get_stylesheet_directory_uri()` to get the URL of your theme’s directory and then append the path to the PhotoSwipe CSS file.
- `wp_enqueue_script()`: This function tells WordPress to load the JavaScript files.
- The first argument is a unique handle for the script (e.g., ‘photoswipe-js’).
- The second argument is the URL to the JavaScript file. Again, we use `get_stylesheet_directory_uri()` to construct the URL.
- The third argument is an array of dependencies. This tells WordPress which scripts need to be loaded *before* this script. For example, `photoswipe-ui-default.min.js` depends on `photoswipe.min.js`, so we include `’photoswipe-js’` in its dependencies.
- `false`: Specifying the version number for the js files.
- `true`: This tells WordPress to load the script in the footer of the page. This is generally a good practice for JavaScript files, as it allows the page content to load first, improving perceived performance.
- `add_action( ‘wp_enqueue_scripts’, ‘my_theme_enqueue_photoswipe’ )`: This line hooks our `my_theme_enqueue_photoswipe()` function into the `wp_enqueue_scripts` action. This tells WordPress to run our function whenever it’s enqueueing scripts (which happens on every page load).
Step 4: Initialize PhotoSwipe with JavaScript (photoswipe-init.js)
Now for the final piece of the puzzle! We need to write some JavaScript code to initialize PhotoSwipe when the product images are clicked. This code will find the product gallery images and tell PhotoSwipe to display them.
1. Create a `js` folder: Inside your theme directory, create a folder named `js` (if you don’t already have one).
2. Create `photoswipe-init.js`: Inside the `js` folder, create a file named `photoswipe-init.js`.
3. Add the Initialization Code: Add the following code to your `photoswipe-init.js` file. This code might need adjustments depending on the structure of your WooCommerce product image gallery. We’re assuming a common scenario where the gallery images are wrapped in `` tags within the `.woocommerce-product-gallery__wrapper` class.
(function($) {
$(document).ready(function() {
// Function to initialize PhotoSwipe
function initPhotoSwipeFromDOM(gallerySelector) {
// parse slide data (url, title, size …) from DOM elements
var parseThumbnailElements = function(el) {
var thumbElements = el.childNodes,
numNodes = thumbElements.length,
items = [],
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i]; //
// include only element nodes
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0]; // element
size = linkEl.getAttribute(‘data-size’).split(‘x’);
// create slide object
item = {
src: linkEl.getAttribute(‘href’),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
// find nearest parent element
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
// triggers when user clicks on thumbnail
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === ‘FIGURE’);
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define index via data- attribute
var clickedGallery = clickedListItem.parentNode,
childNodes = clickedGallery.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
// parse picture index and gallery options from URL
var photoswipeParseHash = function() {
var hash = window.location.hash.substring(1),
params = {};
if(hash.length < 5) {
return params;
}
var vars = hash.split(‘&’);
for (var i = 0; i < vars.length; i++) {
if(!vars[i]) {
continue;
}
var pair = vars[i].split(‘=’);
if(pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
if(params.gid) {
params.gid = parseInt(params.gid, 10);
}
return params;
};
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
var pswpElement = document.querySelectorAll(‘.pswp’)[0],
gallery,
options,
items;
items = parseThumbnailElements(galleryElement);
// define options (if needed)
options = {
// define gallery index (for URL)
galleryUID: galleryElement.getAttribute(‘data-pswp-uid’),
getThumbBoundsFn: function(index) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el.getElementsByTagName(‘img’)[0], // find thumbnail
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
},
showAnimationDuration: disableAnimation ? 0 : 333,
hideAnimationDuration: disableAnimation ? 0 : 333
};
if(fromURL) {
if(options.galleryPIDs) {
// parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
options.index = j;
break;
}
}
} else {
// in URL indexes start from 1
options.index = parseInt(index, 10) – 1;
}
} else {
options.index = parseInt(index, 10);
}
// exit if index not found
if( isNaN(options.index) ) {
return;
}
if(pswpElement){
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
}
};
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll( gallerySelector );
for(var i = 0, l = galleryElements.length; i < l; i++) {
galleryElements[i].setAttribute(‘data-pswp-uid’, i+1);
galleryElements[i].onclick = onThumbnailsClick;
}
// Parse URL and open gallery if it contains #&pid=3&gid=1
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid – 1 ], true, true );
}
};
// execute above function
initPhotoSwipeFromDOM(‘.woocommerce-product-gallery__wrapper’); // replace ‘.woocommerce-product-gallery__wrapper’ with the correct selector for your gallery
});
})(jQuery);
Important Considerations:
- CSS Selectors: The code uses `.woocommerce-product-gallery__wrapper` to find the gallery container and `figure` to find each individual image. This is the most likely place you’ll need to adapt the code. Inspect your WooCommerce product page’s HTML source code to identify the correct CSS selectors for your theme. You’ll need to adjust this if your gallery is structured differently.
- `data-size` Attribute: The JavaScript expects the `` tags around your images to have a `data-size` attribute in the format `widthxheight` (e.g., `data-size=”800×600″`). WooCommerce usually doesn’t automatically add this. You’ll need to add code (either in your theme’s template files or using a plugin) to add this attribute to your image links. A simple way to add it through PHP, assuming you’re looping through `$attachment_ids` array (image attachment IDs) in your product gallery template:
<?php foreach ( $attachment_ids as $attachment_id ) { $image_size = wp_get_attachment_image_src( $attachment_id, 'full' ); // Get the full-size image
// Get the image URL
$image_link = wp_get_attachment_url( $attachment_id ); // Assuming this is your image link
if ( $image_size ) {
$image_width = $image_size[1]; // Width
$image_height = $image_size[2]; // Height
$data_size_attribute = $image_width . ‘x’ . $image_height;
} else {
$data_size_attribute = ‘800×600’; // Provide a default size if the image is not available.
}
echo ‘
echo ‘‘;
echo wp_get_attachment_image( $attachment_id, ‘thumbnail’ ); // Use thumbnail or appropriate size here
echo ‘‘;
echo ‘
‘;
}
?>
- PhotoSwipe HTML Markup: The `photoswipe-init.js` file will use the `photoswipe` library to open images in a fullscreen overlay, you need to add some markup to the end of your theme’s `body` tag or `wp_footer()` action in the theme’s `functions.php` file. The markup should follow PhotoSwipe’s [documentation](https://photoswipe.com/documentation/getting-started.html).
function my_theme_photoswipe_markup() { echo ''; } add_action( 'wp_footer', 'my_theme_photoswipe_markup' );
Step 5: Test and Adjust!
That’s it! Save all your files, clear your browser cache, and visit a product page on your WooCommerce store. Click on a product image. You should now see PhotoSwipe in action!
Troubleshooting:
- PhotoSwipe doesn’t load: Double-check that you’ve enqueued the CSS and JavaScript files correctly in your `functions.php`. Make sure the paths to the files are correct.
- Images don’t show up correctly: Inspect your product page’s HTML source code and adjust the CSS selectors in `photoswipe-init.js` to match your theme’s structure. Verify the existence of `data-size` attributes.
- JavaScript errors: Open your browser’s developer console (usually by pressing F12) and look for any JavaScript errors. This can help you identify problems in your `photoswipe-init.js` code.
Conclusion
Enqueuing PhotoSwipe in your WooCommerce custom theme might seem daunting at first, but by following these steps and carefully adapting the code to your theme’s structure, you can significantly enhance your product image galleries and provide a better shopping experience for your customers. Remember to inspect your theme’s HTML, use the browser’s developer console to debug, and don’t be afraid to experiment! Good luck!