Skip to main content

How to Add a Before/After Image Slider in CamBuildr

Alexander Lagger avatar
Written by Alexander Lagger
Updated this week

Want to visually show the impact of your campaign or a project transformation? A before-and-after slider lets users interactively compare two images by dragging a handle between them. This is ideal for showcasing renovations, climate impact, restoration projects, or design changes.

This guide explains how to implement a responsive before/after image slider using HTML, CSS, and JavaScript—all fully compatible with CamBuildr pages.

What This Slider Does

  • Displays two stacked images with a draggable divider.

  • The left image (“before”) reveals or hides as the user moves the slider.

  • Works on desktop and mobile (touch and mouse supported).

Step 1: Insert the HTML Block

Paste the following code into a new HTML block on your landing page:

<div class="ba-slider-container">
<div id="before-after-slider">
<div id="before-image">
<img src="BEFORE_IMAGE_URL" alt="Before" draggable="false" />
</div>
<div id="after-image">
<img src="AFTER_IMAGE_URL" alt="After" draggable="false" />
</div>
<div id="resizer"></div>
</div>
</div>

Replace BEFORE_IMAGE_URL and AFTER_IMAGE_URL with the actual links to your images. Use images of equal dimensions for the best result.

Step 2: Add the CSS for Layout and Styling

In the same block (or a global style block), include this CSS to style and animate the slider:

<style>
.ba-slider-container {
width: 100%;
max-width: 100%;
margin: 0 auto;
}

#before-after-slider {
position: relative;
overflow: hidden;
width: 100%;
max-width: 800px;
margin: 0 auto;
}

#before-after-slider img {
display: block;
width: 100%;
height: auto;
pointer-events: none;
}

#after-image {
position: relative;
z-index: 1;
}

#before-image {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
overflow: hidden;
z-index: 2;
}

#resizer {
position: absolute;
top: 0;
left: 50%;
width: 4px;
height: 100%;
background: white;
z-index: 3;
cursor: ew-resize;
}

#resizer:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
border: 2px solid #ccc;
}

#before-after-slider,
#before-after-slider * {
user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
</style>

Step 3: Add the JavaScript Functionality

Below the HTML and CSS in the same block, paste the following script:

<script>
const slider = document.getElementById('before-after-slider');
const before = document.getElementById('before-image');
const beforeImg = before.querySelector('img');
const resizer = document.getElementById('resizer');
let active = false;

function syncWidth() {
beforeImg.style.width = slider.offsetWidth + 'px';
}

document.addEventListener('DOMContentLoaded', syncWidth);
window.addEventListener('resize', syncWidth);

// Mouse events
resizer.addEventListener('mousedown', () => active = true);
document.body.addEventListener('mouseup', () => active = false);
document.body.addEventListener('mouseleave', () => active = false);
document.body.addEventListener('mousemove', (e) => {
if (!active) return;
slideIt(e.pageX);
e.preventDefault();
});

// Touch events
resizer.addEventListener('touchstart', () => active = true);
document.body.addEventListener('touchend', () => active = false);
document.body.addEventListener('touchcancel', () => active = false);
document.body.addEventListener('touchmove', (e) => {
if (!active) return;
slideIt(e.touches[0].pageX);
e.preventDefault();
});

function slideIt(x) {
const rect = slider.getBoundingClientRect();
let offset = x - rect.left;
offset = Math.max(0, Math.min(offset, slider.offsetWidth));
before.style.width = offset + "px";
resizer.style.left = offset + "px";
}

// Animate in when visible
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const half = slider.offsetWidth / 2;
before.style.transition = "width 1s ease";
resizer.style.transition = "left 1s ease";
before.style.width = half + "px";
resizer.style.left = half + "px";
setTimeout(() => {
before.style.transition = "";
resizer.style.transition = "";
}, 1000);
observer.unobserve(slider);
}
});
}, {
threshold: 0.5
});

observer.observe(slider);
</script>

Best Practices

  • Image size: Use JPG or PNG images of the same aspect ratio and resolution for best performance.

  • Label your images (optional): You can add “Before” and “After” labels using text overlays in image editors or add <div> labels with absolute positioning.

  • Mobile fallback: Touch sliding is supported, but a tap-to-reveal option can be added if needed.

Common Use Cases

  • Before/after shots from field projects

  • Visual impact of a policy or initiative

  • Timeline visuals (past vs. current status)

  • “What we found” vs. “What we changed”

Did this answer your question?