Overlapping Slider

Documentation
Webflow
Code
Setup: External Scripts
External Scripts in Webflow
Make sure to always put the External Scripts before the Javascript step of the resource.
In this video you learn where to put these in your Webflow project? Or how to include a paid GSAP Club plugin in your project?
HTML
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Draggable.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/InertiaPlugin.min.js"></script>Step 1: Copy structure to Webflow
Copy structure to Webflow
In the video below we described how you can copy + paste the structure of this resource to your Webflow project.
Copy to Webflow
Webflow structure is not required for this resource.
Step 1: Add HTML
HTML
<div data-overlap-slider-init="" class="overlapping-slider__wrap">
<div data-overlap-slider-collection="" class="overlapping-slider__collection">
<div data-overlap-slider-list="" class="overlapping-slider__list">
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“These meal prep boxes honestly changed my evenings. Everything comes chopped, seasoned and labeled, the recipes are easy to follow, and dinner is on the table in like 15 minutes. Love it. 😍”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Nina Calder</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“I’m terrible at planning meals, but this box makes it foolproof. Fresh veggies, good proteins, and zero guesswork. I eat healthier now and barely ever order takeaway anymore.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Marcus Roque</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“Portions are perfect and the flavors are way better than I expected from a subscription. I just open a bag, toss it in the pan and feel like a real cook without any stress.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Elena Strauss</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“These boxes save me so much time after work. No grocery queues, no chopping mountains of vegetables, just quick instructions and tasty food that actually fits my diet.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Jared Kimani</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“I love how the meals are balanced without feeling like ‘diet food’. Sauces are delicious, ingredients stay super fresh, and cleanup is basically one pan and a plate. 🙌”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Priya Desai</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“The variety surprises me every week. I’ve tried dishes I’d never think to make myself, but everything is simple enough that I can cook while half-asleep and still nail it.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Tomás Herrera</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“These meal prep kits made lunches at work a lot less boring. I cook two portions at night, pack one for tomorrow, and I’m done. No more sad sandwiches or vending machines.” </h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Leah Morrison</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“I started this to stop wasting groceries and it worked. Everything is pre-measured, there’s almost no trash, and my fridge finally looks organized instead of chaotic.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Caleb Wright</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“The step-by-step cards are super clear, even for someone who usually burns toast. I feel confident in the kitchen now, and my friends keep asking for the recipes. 😅”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Sophie Lang</span>
</div>
</div>
</div>
<div data-overlap-slider-item="" class="overlapping-slider__item">
<div class="demo-card">
<h2 class="demo-card__h">“Honestly the best habit I’ve picked up all year. These boxes keep me cooking at home, eating real food, and still give me my evenings back. Feels like cheating at adulting.”</h2>
<div class="demo-card__bottom">
<div class="demo__card-avatar"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 28 28" fill="none" class="demo-card__avatar-icon">
<path d="M13.9987 13.4168C16.576 13.4168 18.6654 11.3275 18.6654 8.75016C18.6654 6.17283 16.576 4.0835 13.9987 4.0835C11.4214 4.0835 9.33203 6.17283 9.33203 8.75016C9.33203 11.3275 11.4214 13.4168 13.9987 13.4168Z" stroke="currentColor" stroke-width="1.5"></path>
<path d="M5.25 24.5002V20.6619C5.25 20.1315 5.46071 19.6228 5.83579 19.2477L7.87597 17.2075C8.41163 16.6719 9.20397 16.4848 9.92264 16.7244L13.3675 17.8727C13.7781 18.0095 14.2219 18.0095 14.6325 17.8727L18.0774 16.7244C18.796 16.4848 19.5884 16.6719 20.124 17.2075L22.1642 19.2477C22.5393 19.6228 22.75 20.1315 22.75 20.6619V24.5002" stroke="currentColor" stroke-width="1.5"></path>
</svg>
</div>
<span class="demo-card__p">Dylan Kozlov</span>
</div>
</div>
</div>
</div>
</div>
</div>HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.overlapping-slider__wrap {
width: 100%;
}
.overlapping-slider__collection {
justify-content: flex-start;
align-items: flex-start;
width: 100%;
display: flex;
position: relative;
}
.overlapping-slider__list {
flex-flow: row;
flex: none;
justify-content: flex-start;
align-items: center;
display: flex;
position: relative;
}
.overlapping-slider__item {
flex: none;
margin-right: 1.5em;
}
.demo-card {
grid-column-gap: 2em;
grid-row-gap: 2em;
aspect-ratio: 3 / 4;
background-color: #fff;
border: .1875em solid #000;
border-radius: 1em;
flex-flow: column;
justify-content: space-between;
align-items: flex-start;
width: 24em;
max-width: 85vw;
padding: 3em 2em 2em;
display: flex;
}
.demo-card__h {
margin-top: 0;
margin-bottom: 0;
font-size: 1.5em;
font-weight: 600;
line-height: 1.3;
}
.demo-card__bottom {
grid-column-gap: .75em;
grid-row-gap: .75em;
flex-flow: row;
justify-content: flex-start;
align-items: center;
display: flex;
}
.demo__card-avatar {
color: #fff;
background-color: #ffce16;
border-radius: 100em;
flex: none;
width: 3em;
height: 3em;
padding: .625em;
}
.demo-card__avatar-icon {
width: 100%;
height: 100%;
}
.demo-card__p {
font-size: 1.25em;
font-weight: 600;
line-height: 1;
}Step 2: Add custom Javascript
Custom Javascript in Webflow
In this video, Ilja gives you some guidance about using JavaScript in Webflow:
Step 2: Add Javascript
Step 3: Add Javascript
Javascript
function initOverlappingSlider() {
const inits = document.querySelectorAll('[data-overlap-slider-init]');
if (!inits.length) return;
inits.forEach(setupOverlappingSlider);
function setupOverlappingSlider(init) {
// --- attributes with defaults
const minScale = +(init.getAttribute('data-scale') ?? 0.45);
const maxRotation = +(init.getAttribute('data-rotate') ?? -8);
const inertia = true;
const wrap = init.querySelector('[data-overlap-slider-collection]');
const slider = init.querySelector('[data-overlap-slider-list]');
const slides = Array.from(init.querySelectorAll('[data-overlap-slider-item]'));
if (!wrap || !slider || !slides.length) {
console.warn("OverlappingSlider: missing required structure. Check Osmo Vault documentation please.");
return;
}
wrap.style.touchAction = 'none';
wrap.style.userSelect = 'none';
let spacing = 0;
let slideW = 0;
let maxDrag = 0;
let dragX = 0;
let draggable;
// simple clamp that always uses latest maxDrag
function clamp(value) {
if (maxDrag <= 0) return 0;
return Math.min(Math.max(value, 0), maxDrag);
}
function update() {
// move the whole list
gsap.set(slider, { x: -dragX });
// update each slide's overlap transform
slides.forEach((slide, i) => {
const threshold = i * spacing;
const local = Math.max(0, dragX - threshold);
const t = spacing > 0 ? Math.min(local / spacing, 1) : 0;
gsap.set(slide, {
x: local,
scale: 1 - (1 - minScale) * t,
rotation: maxRotation * t,
transformOrigin: '75% center'
});
});
}
function recalc() {
if (!slides.length) return;
// measure one slide to get width + margin-right as "gap"
const style = getComputedStyle(slides[0]);
const gapRight = parseFloat(style.marginRight) || 0;
slideW = slides[0].offsetWidth;
spacing = slideW + gapRight;
maxDrag = spacing * (slides.length - 1);
// keep dragX within new bounds
dragX = clamp(dragX);
update();
if (draggable) {
draggable.applyBounds({ minX: -maxDrag, maxX: 0 });
}
}
// create draggable
draggable = Draggable.create(slider, {
type: 'x',
bounds: { minX: -maxDrag, maxX: 0 }, // will be updated after recalc
inertia,
maxDuration: 1,
snap: true
? (raw) => {
// raw is the x value
const d = clamp(-raw);
const idx = spacing > 0 ? Math.round(d / spacing) : 0;
return -idx * spacing;
}
: false,
onDrag() {
dragX = clamp(-this.x);
update();
},
onThrowUpdate() {
dragX = clamp(-this.x);
update();
}
})[0];
// recalc on resize
const ro = new ResizeObserver(() => {
recalc();
});
ro.observe(init);
// keyboard navigation (arrow left/right)
let active = false;
let currentIndex = 0;
// helper function to switch slides
function goToSlide(idx) {
idx = Math.max(0, Math.min(idx, slides.length - 1));
currentIndex = idx;
const targetX = idx * spacing;
gsap.to({ value: dragX }, {
value: targetX,
duration: 0.35,
ease: "power4.out",
onUpdate: function () {
dragX = this.targets()[0].value;
gsap.set(slider, { x: -dragX });
update(); // animate overlap transforms properly
}
});
wrap.setAttribute("aria-label", `Slide ${idx + 1} of ${slides.length}`);
}
// Observe visibility
const io = new IntersectionObserver(entries => {
active = entries[0].isIntersecting;
}, {
threshold: 0.25 // slider must be at least 25% visible
});
io.observe(init);
// Aria labels for accessibility
wrap.setAttribute("role", "region");
wrap.setAttribute("aria-roledescription", "carousel");
wrap.setAttribute("aria-label", "Testimonial slider");
// key listener
function onKey(e) {
if (!active) return; // only respond when slider in view
if (e.key === "ArrowLeft") {
e.preventDefault();
goToSlide(currentIndex - 1);
}
if (e.key === "ArrowRight") {
e.preventDefault();
goToSlide(currentIndex + 1);
}
}
window.addEventListener("keydown", onKey);
// initial layout
recalc();
}
}
document.addEventListener("DOMContentLoaded", function () {
initOverlappingSlider();
})Step 3: Add custom CSS
Step 2: Add custom CSS
Custom CSS in Webflow
Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:
CSS
.wf-design-mode [data-overlap-slider-collection]{
overflow: auto;
}Implementation
Init
Use [data-overlap-slider-init] to activate the Overlapping Slider instance, allowing all measurements and draggable behavior to initialize correctly.
Wrap
Use [data-overlap-slider-collection] to define the outer container that handles ARIA roles, visibility tracking, and keyboard-driven slide announcements.
Slider
Use [data-overlap-slider-list] to create the horizontally draggable list element that GSAP positions using drag values and inertia. This is the direct parent of all slides. Make sure it keeps the combined width of all slides. In our example, we do this by setting the wrap (see previous step) to display: flex; which then allows us to set the slider list to flex: none;
Slides
Use [data-overlap-slider-item] to register each card as a draggable slide that participates in the overlapping transform logic.
Space between
Simply add some margin-right to your slides in CSS to define the space or 'gap' between all slides.
Scale
Use [data-scale] (default 0.45) to set the minimum scale applied to background cards as they move behind the active slide.
Rotation
Use [data-rotate] (default -8) to define how much each background card tilts while transitioning between positions.
Slide content
We recommend to leave the slides themselves pretty much unstyled. In our demo we just place an actual 'card' div inside of each [data-overlap-slider-item]. This way, it's much easier to re-use this slider across multiple instances, with different content and/or styling.
Keyboard Navigation
The slider supports arrow-key navigation out of the box, automatically activating when the component becomes at least 25% visible to ensure accessible slide control.
Resource details
Last updated
November 26, 2025
Category
Sliders & Marquees
Need help?
Join Slack





























































































































