-
3D Carousel animation
HTML
CSS
JavaScript
×
* { margin: 0; padding: 0; box-sizing: border-box; } body { background: radial-gradient(circle, #020617, #000); height: 100vh; display: flex; justify-content: center; align-items: center; font-family: Arial; overflow: hidden; } .scene { width: min(90vw, 320px); height: min(90vw, 320px); perspective: 1000px; } .carousel { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; animation: rotate 20s infinite linear; } @keyframes rotate { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } } /* Card */ .card { position: absolute; width: min(40vw, 150px); height: min(70vw, 180px); left: 50%; top: 50%; transform-origin: center; margin-left: calc(-1 * min(55vw, 150px) / 2); margin-top: calc(-1 * min(70vw, 180px) / 2); border-radius: 16px; overflow: hidden; cursor: pointer; } .card img { width: 100%; height: 100%; object-fit: cover; } /* Circular Layout */ .card:nth-child(1) { transform: rotateY(0deg) translateZ(45vw); } .card:nth-child(2) { transform: rotateY(60deg) translateZ(45vw); } .card:nth-child(3) { transform: rotateY(120deg) translateZ(45vw); } .card:nth-child(4) { transform: rotateY(180deg) translateZ(45vw); } .card:nth-child(5) { transform: rotateY(240deg) translateZ(45vw); } .card:nth-child(6) { transform: rotateY(300deg) translateZ(45vw); } /* Pause on interaction */ .scene:active .carousel, .scene:hover .carousel { animation-play-state: paused; } /* Modal */ .modal { position: fixed; inset: 0; background: rgba(0,0,0,0.95); display: none; justify-content: center; align-items: center; z-index: 999; } .modal img { max-width: 95%; max-height: 85%; border-radius: 10px; } /* Close */ .close { position: absolute; top: 15px; right: 20px; font-size: 28px; color: white; cursor: pointer; }
const carousel = document.getElementById('carousel'); const cards = document.querySelectorAll('.card img'); const modal = document.getElementById('modal'); const modalImg = document.getElementById('modalImg'); let isDragging = false; let startX = 0; let currentRotate = 0; /* TOUCH DRAG ROTATION */ carousel.addEventListener('touchstart', e => { isDragging = true; startX = e.touches[0].clientX; carousel.style.animation = 'none'; }); carousel.addEventListener('touchmove', e => { if (!isDragging) return; let delta = e.touches[0].clientX - startX; carousel.style.transform = `rotateY(${currentRotate + delta * 0.3}deg)`; }); carousel.addEventListener('touchend', e => { isDragging = false; currentRotate += (e.changedTouches[0].clientX - startX) * 0.3; }); /* CLICK FULLSCREEN */ cards.forEach(img => { img.addEventListener('click', () => { modal.style.display = 'flex'; modalImg.src = img.src; }); }); /* CLOSE MODAL */ document.getElementById('closeBtn').onclick = () => modal.style.display = 'none'; modal.onclick = e => { if (e.target === modal) modal.style.display = 'none'; };
Live Preview