I have a carousel of images, which I have tilted diagonally, and now I want to scroll through the images. The only problem is that if I add more images to the carousel track than the four I have, the images get clipped by the container because of the large width of the carousel track. How can I change my CSS or JavaScript to accommodate N images and never get clipped? Below is a minimal reproducible example:
window.addEventListener('load', () => {
if (typeof gsap === 'undefined') return;
gsap.registerPlugin(ScrollTrigger);
const diagonalTrack = document.querySelector('.diagonal-carousel .carousel-track');
if (!diagonalTrack) return;
const extraOffset = 1000; // tweak as needed
// Total distance the track needs to move horizontally
const totalDiagonalScroll = diagonalTrack.scrollWidth - window.innerWidth;
gsap.to(diagonalTrack, {
x: () => -totalDiagonalScroll + window.innerWidth * 0.05 - extraOffset,
ease: "none",
scrollTrigger: {
trigger: ".diagonal-carousel",
start: "top top",
end: () => `+=${totalDiagonalScroll + extraOffset}`,
scrub: 1,
pin: true,
anticipatePin: 1,
invalidateOnRefresh: true,
markers: true // turn on markers for debugging
}
});
});
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 200vh;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: #050711;
color: #f5f5f5;
}
.spacer {
height: 80vh;
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
justify-content: center;
}
/* Basic button for card */
.btn.sm {
padding: 6px 12px;
font-size: 0.9rem;
border-radius: 8px;
border: none;
cursor: pointer;
}
/* === Diagonal Carousel Effect (extracted from your file) === */
.diagonal-carousel {
position: relative;
overflow: hidden;
width: 100%;
height: 120vh;
}
/* Center inside the container */
.diagonal-carousel .carousel-inner {
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: flex-end;
justify-content: flex-start;
transform-style: preserve-3d;
perspective: 700px;
}
/* Apply the tilt and manage width */
.diagonal-carousel .carousel-track {
display: flex;
gap: 60px;
transform-style: preserve-3d;
transform: rotate3d(2, 0, 1, 20deg) scale(0.8); /* Scale down + diagonal tilt */
width: max-content;
padding: 0 20vw;
transform-origin: bottom right;
}
/* Each card */
.diagonal-carousel .case-card {
position: relative;
flex: 0 0 80vw;
height: 70vh;
border-radius: 24px;
overflow: hidden;
background: #181b25;
box-shadow: 0 10px 40px rgba(0,0,0,0.5);
transform-style: preserve-3d;
}
/* Image + hover zoom */
.case-card .card-image img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 0;
transition: transform 0.5s ease;
}
.case-card:hover .card-image img {
transform: scale(1.05);
}
/* Text overlay */
.case-card .card-text {
position: relative;
z-index: 1;
padding: 32px;
max-width: 400px;
color: #fff;
backdrop-filter: blur(8px);
background: rgba(0, 0, 0, 0.45);
border-radius: 16px;
margin: 0 0 32px 32px;
}
.case-card h3 { margin: 0 0 4px; font-size: 1.4rem; }
.case-card h4 { margin: 0 0 12px; font-weight: 600; opacity: 0.85; }
.case-card p { margin: 0 0 16px; line-height: 1.4; color: #e5e5e5; }
@media (max-width: 720px) {
.diagonal-carousel .case-card { flex: 0 0 90vw; height: 60vh; }
.case-card .card-text { padding: 20px; margin: 0 0 20px 20px; }
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Minimal Diagonal Scroll Demo</title>
<link rel="stylesheet" href="styles.css" />
<!-- GSAP + ScrollTrigger from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js" defer></script>
<script src="main.js" defer></script>
</head>
<body>
<main>
<section class="spacer">
<h1>Scroll down to see diagonal carousel</h1>
<p>Minimal demo of the diagonal scroll effect.</p>
</section>
<!-- Diagonal Carousel -->
<section class="diagonal-carousel">
<div class="carousel-inner">
<div class="carousel-track">
<article class="case-card">
<div class="card-image">
<img src="https://images.pexels.com/photos/374870/pexels-photo-374870.jpeg" alt="Card 1" />
</div>
<div class="card-text">
<h3>Diagonal Card 1</h3>
<h4>NUTTER BUTTER, YOU GOOD?</h4>
<p>This 56-year-old cookie’s rabbit hole of absurdist escapism consumed the internet.</p>
<button class="btn sm">View case</button>
</div>
</article>
<article class="case-card">
<div class="card-image">
<img src="https://images.pexels.com/photos/196652/pexels-photo-196652.jpeg" alt="Card 2" />
</div>
<div class="card-text">
<h3>Diagonal Card 2</h3>
<h4>CRUNCH TIME CAMPAIGN</h4>
<p>A nostalgic voyage through cereal seas – reviving childhood joy for adults.</p>
<button class="btn sm">View case</button>
</div>
</article>
<article class="case-card">
<div class="card-image">
<img src="https://images.pexels.com/photos/66997/pexels-photo-66997.jpeg" alt="Card 3" />
</div>
<div class="card-text">
<h3>Diagonal Card 3</h3>
<h4>LAUNCH LAB</h4>
<p>Experiments in motion, copy, and creative strategy for bold brands.</p>
<button class="btn sm">View case</button>
</div>
</article>
<article class="case-card">
<div class="card-image">
<img src="https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg" alt="Card 4" />
</div>
<div class="card-text">
<h3>Diagonal Card 4</h3>
<h4>NIGHT DRIVE</h4>
<p>Moody, cinematic explorations of color, light, and narrative.</p>
<button class="btn sm">View case</button>
</div>
</article>
</div>
</div>
</section>
<section class="spacer">
<p>End of demo.</p>
</section>
</main>
</body>
</html>