Before-and-after sliders are one of the most effective ways to showcase transformations. Whether you are a photographer, interior designer, dentist, contractor, or fitness coach, a visual comparison tells a story that words alone cannot. Squarespace does not offer this as a native block, but you can add one with clean, lightweight code.
How Before-After Sliders Work
Two images are stacked on top of each other. A clip-path or overflow-hidden technique reveals only a portion of the top image, and a draggable handle lets the user control how much of each image is visible.
Step 1: Prepare Your Images
Use matching dimensions, framing, and camera position for the clearest comparison. Both images fill the same frame; a different aspect ratio can crop part of a photo. Check the preview before exporting.
Resize and compress both images for the size they will display. Upload them to your asset library or image host and use their public HTTPS addresses. Keep both source files available; deleting them can break the comparison.
Step 2: The HTML Structure
<!-- Paste into a Code Block (HTML mode) -->
<div class="ba-slider" style="--position: 50%">
<img src="/s/before.jpg" alt="Kitchen before renovation
, dark cabinets, outdated countertops" class="ba-before">
<img src="/s/after.jpg" alt="Kitchen after renovation
, white quartz counters, pendant lights" class="ba-after">
<div class="ba-handle">
<div class="ba-handle-line"></div>
<div class="ba-handle-circle">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="#fff" stroke-width="2">
<path d="M8 4l-6 8 6 8M16 4l6 8-6 8"/>
</svg>
</div>
<div class="ba-handle-line"></div>
</div>
<span class="ba-label ba-label-before">Before</span>
<span class="ba-label ba-label-after">After</span>
</div>Step 3: The CSS
.ba-slider {
position: relative;
overflow: hidden;
cursor: col-resize;
touch-action: pan-y;
user-select: none;
aspect-ratio: 3/2;
border-radius: 8px;
}
.ba-slider img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.ba-after {
clip-path: inset(0 0 0 var(--position));
}
.ba-handle {
position: absolute;
top: 0;
bottom: 0;
left: var(--position);
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
z-index: 2;
}
.ba-handle-line {
flex: 1;
width: 3px;
background: #fff;
box-shadow: 0 0 4px rgba(0,0,0,0.3);
}
.ba-handle-circle {
width: 40px;
height: 40px;
border-radius: 50%;
background: #1a1a1a;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.ba-label {
position: absolute;
bottom: 16px;
font-size: 11px;
font-weight: 600;
letter-spacing: 1.5px;
text-transform: uppercase;
color: #fff;
background: rgba(0,0,0,0.5);
padding: 6px 12px;
border-radius: 4px;
}
.ba-label-before { left: 16px; }
.ba-label-after { right: 16px; }Step 4: The JavaScript
<script>
document.querySelectorAll('.ba-slider:not([data-ready])').forEach(slider => {
slider.dataset.ready = 'true';
let position = 50;
slider.tabIndex = 0;
slider.setAttribute('role', 'slider');
slider.setAttribute('aria-label', 'Image comparison');
slider.setAttribute('aria-valuemin', '0');
slider.setAttribute('aria-valuemax', '100');
function move(value) {
position = Math.max(0, Math.min(100, value));
slider.style.setProperty('--position', position + '%');
slider.setAttribute('aria-valuenow', Math.round(position));
}
function pointer(e) {
const rect = slider.getBoundingClientRect();
move((e.clientX - rect.left) / rect.width * 100);
}
slider.addEventListener('pointerdown', e => {
if (!e.isPrimary || e.button !== 0) return;
slider.setPointerCapture(e.pointerId);
slider.focus({preventScroll: true});
pointer(e);
});
slider.addEventListener('pointermove', e => {
if (slider.hasPointerCapture(e.pointerId)) pointer(e);
});
slider.addEventListener('pointerup', e => {
if (slider.hasPointerCapture(e.pointerId))
slider.releasePointerCapture(e.pointerId);
});
slider.addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') move(position - 1);
else if (e.key === 'ArrowRight') move(position + 1);
else if (e.key === 'Home') move(0);
else if (e.key === 'End') move(100);
else return;
e.preventDefault();
});
move(position);
});
</script>Use Our Generator Instead
Our Before and After Slider Generator handles all of this. Enter your two image URLs, choose horizontal or vertical orientation, add labels and descriptions, and set the starting reveal. Preview it for free. The $11.99 personal-use purchase unlocks the complete code export in your verified account. The generated slider supports mouse, touch, and keyboard input; check it with your own site styles before publishing.
