Displaying before-and-after images in an interactive way is a powerful tool for showing transformations. It can let your audience visually compare changes or differences. Just drag between the images then they can see a more dynamic comparison.
Let’s see how we can have it with MB Views from Meta Box.
Video Version
Before Getting Started
To start, let's outline the concept:
- The before and after images, along with their extra content, will be stored in the custom fields created with Meta Box.
- Then, we’ll display them using the MB Views extension from Meta Box as well.
- For the before-after effect with dragging interaction, we’ll use a little bit of JavaScript.
Using custom fields allows you to set up and update images and content easily without needing to redesign your layout.
So, we need the Meta Box core plugin to have a framework to create custom fields and set up a template for displaying images. You can download it directly from wordpress.org.
Also, you may need some advanced features from extensions of Meta Box. So you can install them separately, or use Meta Box AlO to get everything bundled together.
These are the extensions you may want to activate:
- MB Views: to create a template for displaying before and after images;
- Meta Box Builder: to have a UI on the back end to create custom fields to save images and related content visually.
Notice that if you are adding before and after images for posts in a custom post type, you should enable the MB Custom Post Type extension to have the post type as well.
Now, let’s go step by step.
Create Custom Fields to Store the Images
I’ll add before-after images for my blog posts, so I’ll create the fields without any further steps.
As I mentioned, you can add the images for posts in a custom post type. Then, you should create the post type first. After that, let’s create custom fields to store the images and related content.
For illustration purposes of this practice only, I’ll set up fields to upload the before and after images, also with a Text field to add extra information to the images like this:
You absolutely can add additional fields for any related details as you want.
Now, go to Meta Box > Custom Fields and create a new field group.
Just add fields one by one corresponding to the kind of content.
For the before image, as well as the after image later, choose the Single Image field type.
After creating all the fields, move to the Settings tab, set the Location as Post to apply the fields to it.
Now, in any post editor, you will see the custom fields displayed.
Just input content there.
Display the Images
In this step, we’ll create a template to just display the before and after images along with their related content within a single post. For styling beautifully and adding interactive functions like sliders or overlays for a clear comparison, we’ll cover that in the next part.
Now, head over to Meta Box > Views, and create a new template specifically for this purpose.
With MB Views, you can add some lines of code to the Template tab, or insert fields into it by clicking the Insert Field button, and choose any fields on the right sidebar to get data from them. It will automatically generate code to the template.
With the images, you can select a suitable image size to display, as well as the output.
After inserting all the fields into the template, move to the Settings section to set the location where we want to display this template. In this case, the concept is that any post which has the before-after images will have them on the post content. So, I set the type of the view as Singular, and the location as Post.
And, choose a place in the post.
Now, on the frontend, you’ll see the before and after images along with their related information. They will be listed one by one.
Turn the Images to Slidable
Styling the before and after images is the key to making the comparison stand out. So, I’ll guide you on how to implement an interactive slider, allowing users to drag between the images for a more dynamic and engaging comparison.
Back to the created template with MB Views, include some div tags, classes, also HTML ID for each element to make the styling process easier.
You can notice that these IDs will be used in JavaScript later to make the images interactive.
Still in the Template tab, add the following code to have a middle bar and the arrows.
<div id="resizer"> <div class="mb-icon"> <div id="triangle-left"></div> <div id="triangle-right"></div> </div> </div>
Next to the CSS tab, add these lines of code to beautify the display of before and after images, as well as the content that goes along with them.
#triangle-right { width: 0; height: 0; border-top: 8px solid transparent; border-left: 8px solid #fff; border-bottom: 8px solid transparent; } #triangle-left { margin-right: 5px; width: 0; height: 0; border-top: 8px solid transparent; border-right: 8px solid #fff; border-bottom: 8px solid transparent; } .mb-icon { cursor: pointer; background: linear-gradient(62deg, #c93072 5%, #3365c0); font-family: "Font Awesome 5 Free"; font-weight: 900; display: flex; justify-content: center; align-items: center; color: white; position: absolute; margin: 0 0 0 -18px; width: 40px; height: 40px; border-radius: 50%; border: 3px solid white; } .text-before { width: max-content; position: absolute; bottom: 10px; left: 10px; color: #fff; background: #0c0202; padding: 3px 7px; } .text-after { width: max-content; position: absolute; bottom: 5px; right: 5px; color: #fff; background: #0c0202; padding: 3px 5px; } .mb-container img { max-width: none; width: 100%; display: block; } #before-after-slider { width: 100%; position: relative; overflow: hidden; border: 3px solid white; } #after-image { display: block } #before-image { position: absolute; height: 100%; width: 50%; top: 0; left: 0; overflow: hidden; z-index: 2; } #resizer { position: absolute; display: flex; align-items: center; z-index: 5; top: 0; left: 50%; height: 100%; width: 4px; background: white; -ms-touch-action: pan-y; touch-action: pan-y; }
Run the Slider
Now, include some script to the JavaScript tab for the advanced effect of sliders. These are the whole code I use for JavaScript.
const slider = document.getElementById('before-after-slider'); const before = document.getElementById('before-image'); const beforeImage = before.getElementsByTagName('img')[0]; const resizer = document.getElementById('resizer'); let active = false; document.addEventListener("DOMContentLoaded", function () { let width = slider.offsetWidth; console.log(width); beforeImage.style.width = width + 'px'; }); window.addEventListener('resize', function () { let width = slider.offsetWidth; console.log(width); beforeImage.style.width = width + 'px'; }) resizer.addEventListener('mousedown', function () { active = true; resizer.classList.add('resize'); }); document.body.addEventListener('mouseup', function () { active = false; resizer.classList.remove('resize'); }); document.body.addEventListener('mouseleave', function () { active = false; resizer.classList.remove('resize'); }); document.body.addEventListener('mousemove', function (e) { if (!active) return; let x = e.pageX; x -= slider.getBoundingClientRect().left; slideIt(x); pauseEvent(e); }); function slideIt(x) { let transform = Math.max(0, (Math.min(x, slider.offsetWidth))); before.style.width = transform + "px"; resizer.style.left = transform - 0 + "px"; } function pauseEvent(e) { if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); e.cancelBubble = true; e.returnValue = false; return false; }
Let’s break down one by one part:
Get Elements and Create Variables
const slider = document.getElementById('before-after-slider'); const before = document.getElementById('before-image'); const beforeImage = before.getElementsByTagName('img')[0]; const resizer = document.getElementById('resizer');
These are to get one by one specific elements with the corresponding HTML IDs we added previously.
let active = false;
This is to keep track of whether the user is currently dragging or not.
Manage Middle Bar and Drag Action
Displaying the images based on the slide action actually means redefining the size of one of the images. So, the images will be stacked, and the middle bar also is the limit of one image to display.
We do this code below to adjust the width of the before image to match the width of the cover frame, which also means the frame covers the after image.
document.addEventListener("DOMContentLoaded", function () { let width = slider.offsetWidth; console.log(width); beforeImage.style.width = width + 'px'; });
When the middle bar is moving, the width of the before image should change following.
window.addEventListener('resize', function () { let width = slider.offsetWidth; console.log(width); beforeImage.style.width = width + 'px'; })
This following class will be added or removed automatically and conditionally based on the mouse action on the middle bar.
resizer.addEventListener('mousedown', function () { active = true; resizer.classList.add('resize'); }); document.body.addEventListener('mouseup', function () { active = false; resizer.classList.remove('resize'); });
In there: resizer
is the ID we added to the bar previously.
Based on this action, the resize
class indicates the current position of the middle bar. It also indicates the width of the image should be at the moment.
Next, we should limit the area of action that can be triggered.
document.body.addEventListener('mouseleave', function () { active = false; resizer.classList.remove('resize'); });
This one is to stop the dragging if the mouse moves outside the frame area, preventing the dragging action from continuing unintentionally.
document.body.addEventListener('mousemove', function (e) { if (!active) return; let x = e.pageX; x -= slider.getBoundingClientRect().left; slideIt(x); pauseEvent(e); })
This captures the mouse movement event so that the icon and the middle slider move only when the icon is clicked.
Then, alter the width of the before image and the position of the middle bar with the new one based on the calculated distance. So that, when you click the icon and move the mouse, the slider and the width of the before image adjust accordingly.
function slideIt(x) { let transform = Math.max(0, (Math.min(x, slider.offsetWidth))); before.style.width = transform + "px"; resizer.style.left = transform - 0 + "px"; }
Prevent Default Actions
We use this final part to prevent the default actions of the browser that can be confused with the action on the middle bar. It makes sure that the middle bar moves only when the reader really clicks on it and drags it. Also, the dragging does not affect any other part of the page.
function pauseEvent(e) { if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); e.cancelBubble = true; e.returnValue = false; return false; }
That's all for the code. All the code is updated on Github for your reference.
Move on to a post, let's see the final result! When we drag the middle bar, the before image will be shown less or more based on the bar position.
Last Words
Using interactive before-and-after images is a great way to show changes and engage your audience. By using custom fields with Meta Box and a bit of JavaScript, you can easily create dynamic comparisons that are simple to update. If you're interested in exploring more ways to display images dynamically, you might find this tutorial helpful: Display images from cloneable fields.