Skip to content
Tutorials

How to Add a Before and After Slider to Squarespace

Updated October 12, 2026

By Squarespace Tools TeamUpdated October 12, 20266 min read

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.

Build your before/after slider with our generatorTry it free →

Best Practices for Before-After Content

Shoot from the same angle. Use a tripod or mark your camera position. The comparison only works if both photos have the same perspective.
Match the lighting. Different lighting between shots makes the comparison feel unfair. Photograph at the same time of day.
Don't over-edit the after image. Real results build more trust than polished perfection.
Label clearly. Add Before and After labels. Even though the interaction is intuitive, explicit labels remove ambiguity.
Try the Before & After Slider GeneratorTry it free →

Need a hand with your site?

Get help installing, styling, or troubleshooting your changes.