Skip to content
Tutorials

How to Add a Before and After Slider to Squarespace

By Squarespace Tools TeamMarch 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.

Skip the tutorial — generate your slider instantlyTry it free →

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.

How it looks on a real site
Before
Original kitchen
outdated cabinets, dark lighting
After
Renovated kitchen
white quartz, pendant lighting

Users drag the handle to reveal the before or after image. Works on desktop and mobile with touch support.

Step 1: Prepare Your Images

Both images must have identical dimensions. If your before photo is 1200 by 800 pixels, your after photo must also be 1200 by 800. Any mismatch in aspect ratio will cause misalignment.

Compress both images to under 300KB each. The slider loads both images at full resolution, so unoptimized images will double your typical image load time for that section.

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;
  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').forEach(slider => {
  let isDragging = false;

  function updatePosition(x) {
    const rect = slider.getBoundingClientRect();
    const pos = Math.max(0, Math.min(1,
      (x - rect.left) / rect.width));
    slider.style.setProperty('--position', pos * 100 + '%');
  }

  slider.addEventListener('mousedown', () => isDragging = true);
  document.addEventListener('mouseup', () => isDragging = false);
  document.addEventListener('mousemove', e => {
    if (isDragging) updatePosition(e.clientX);
  });

  // Touch support
  slider.addEventListener('touchstart', () => isDragging = true);
  document.addEventListener('touchend', () => isDragging = false);
  slider.addEventListener('touchmove', e => {
    updatePosition(e.touches[0].clientX);
  });

  // Keyboard support
  slider.setAttribute('tabindex', '0');
  slider.setAttribute('role', 'slider');
  slider.addEventListener('keydown', e => {
    const current = parseFloat(
      slider.style.getPropertyValue('--position')) || 50;
    if (e.key === 'ArrowLeft') {
      slider.style.setProperty('--position',
        Math.max(0, current - 5) + '%');
    } else if (e.key === 'ArrowRight') {
      slider.style.setProperty('--position',
        Math.min(100, current + 5) + '%');
    }
  });
});
</script>

Use Our Generator Instead

Our Before and After Slider Generator handles all of this. Upload your two images, choose a handle style, set the starting position, and copy the generated code. It outputs production-ready code with all the accessibility attributes, touch support, keyboard navigation, and responsive behavior already built in.

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 →

A little over your head?

No shame — this stuff is hard. Let the pros handle it.

Long Drive MarketingTalk to Long Drive Marketing →