VIDEO
Full Code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Arcane Vapor β 3D Perspective Experience</title>
<style>
:root {
--primary: #00f2ff;
--accent: #7000ff;
--bg: #050505;
--card-w: 340px;
--card-h: 480px;
--transition: cubic-bezier(0.23, 1, 0.32, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg);
color: white;
font-family: 'Inter', system-ui, -apple-system, sans-serif;
overflow: hidden;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
/* Ambient Background */
.ambient-light {
position: fixed;
top: 50%;
left: 50%;
width: 60vw;
height: 60vh;
background: radial-gradient(circle, rgba(112, 0, 255, 0.15) 0%, rgba(0, 0, 0, 0) 70%);
transform: translate(-50%, -50%);
filter: blur(80px);
z-index: 0;
pointer-events: none;
}
/* Perspective Container */
.stage {
perspective: 1200px;
width: 100%;
height: 600px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 1;
}
.slider-track {
display: flex;
gap: 40px;
transform-style: preserve-3d;
will-change: transform;
cursor: grab;
padding: 0 20%;
}
.slider-track:active {
cursor: grabbing;
}
/* Product Card */
.card {
position: relative;
min-width: var(--card-w);
height: var(--card-h);
background: rgba(255, 255, 255, 0.03);
border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
transform-style: preserve-3d;
transition: border-color 0.4s ease;
display: flex;
flex-direction: column;
padding: 30px;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at var(--px) var(--py), rgba(255,255,255,0.15) 0%, transparent 80%);
opacity: 0;
transition: opacity 0.3s;
}
.card:hover::before {
opacity: 1;
}
/* Product Visuals */
.product-image-container {
position: relative;
width: 100%;
height: 220px;
transform-style: preserve-3d;
pointer-events: none;
}
.product-image {
width: 120%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) translateZ(50px);
filter: drop-shadow(0 20px 30px rgba(0,0,0,0.5));
transition: transform 0.2s ease-out;
}
/* Card Content */
.card-info {
margin-top: auto;
transform: translateZ(30px);
}
.tag {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--primary);
margin-bottom: 8px;
display: block;
}
.title {
font-size: 24px;
font-weight: 800;
margin-bottom: 12px;
line-height: 1.1;
}
.price-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
}
.price {
font-size: 18px;
font-weight: 300;
opacity: 0.8;
}
.buy-btn {
background: white;
color: black;
border: none;
padding: 10px 20px;
border-radius: 30px;
font-weight: 700;
font-size: 12px;
cursor: pointer;
transition: transform 0.2s, background 0.2s;
}
.buy-btn:hover {
transform: scale(1.05);
background: var(--primary);
}
/* Navigation UI */
.controls {
position: absolute;
bottom: 50px;
display: flex;
gap: 20px;
align-items: center;
z-index: 10;
}
.nav-dot {
width: 40px;
height: 2px;
background: rgba(255,255,255,0.2);
transition: 0.4s;
}
.nav-dot.active {
background: var(--primary);
width: 80px;
}
.ui-overlay {
position: fixed;
top: 40px;
left: 40px;
z-index: 100;
}
.logo {
font-weight: 900;
letter-spacing: -1px;
font-size: 20px;
display: flex;
align-items: center;
gap: 10px;
}
.logo-box {
width: 12px;
height: 12px;
background: var(--primary);
rotate: 45deg;
}
</style>
</head>
<body>
<div class="ambient-light" id="ambient"></div>
</div>
<div class="stage" id="stage">
<div class="slider-track" id="track">
<!-- Card 1 -->
<div class="card" data-index="0">
<div class="product-image-container">
<img src="https://travel.nazmulhub.com/wp-content/uploads/2026/01/AIRJORDAN9RETRO.avif" alt="Sneaker" class="product-image">
</div>
<div class="card-info">
<h2 class="title">Air Jordan 9 Retro<br>French Blue</h2>
<div class="price-row">
<span class="price">$240.00</span>
<button class="buy-btn">Add to Bag</button>
</div>
</div>
</div>
<!-- Card 2 -->
<div class="card" data-index="1">
<div class="product-image-container">
<img src="https://travel.nazmulhub.com/wp-content/uploads/2026/01/26230-6-nike-shoes-clipart.png" alt="Sneaker" class="product-image">
</div>
<div class="card-info">
<h2 class="title">GLITCH ASPECT<br>GHOST</h2>
<div class="price-row">
<span class="price">$185.00</span>
<button class="buy-btn">Add to Bag</button>
</div>
</div>
</div>
<!-- Card 3 -->
<div class="card" data-index="2">
<div class="product-image-container">
<img src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?auto=format&fit=crop&w=800&q=80" alt="Sneaker" class="product-image">
</div>
<div class="card-info">
<h2 class="title">CRIMSON<br>ECLIPSE</h2>
<div class="price-row">
<span class="price">$210.00</span>
<button class="buy-btn">Add to Bag</button>
</div>
</div>
</div>
<!-- Card 4 -->
<div class="card" data-index="3">
<div class="product-image-container">
<img src="https://images.unsplash.com/photo-1600185365483-26d7a4cc7519?auto=format&fit=crop&w=800&q=80" alt="Sneaker" class="product-image">
</div>
<div class="card-info">
<h2 class="title">ZENITH<br>SPECTRUM</h2>
<div class="price-row">
<span class="price">$320.00</span>
<button class="buy-btn">Add to Bag</button>
</div>
</div>
</div>
</div>
</div>
<div class="controls" id="controls"></div>
<script>
const track = document.getElementById('track');
const cards = document.querySelectorAll('.card');
const controls = document.getElementById('controls');
const ambient = document.getElementById('ambient');
let isDragging = false;
let startX = 0;
let currentTranslate = 0;
let prevTranslate = 0;
let animationID = 0;
let currentIndex = 0;
// Initialize Nav Dots
cards.forEach((_, i) => {
const dot = document.createElement('div');
dot.classList.add('nav-dot');
if (i === 0) dot.classList.add('active');
controls.appendChild(dot);
});
// Mouse & Touch Events
track.addEventListener('mousedown', dragStart);
track.addEventListener('touchstart', dragStart);
track.addEventListener('mouseup', dragEnd);
track.addEventListener('touchend', dragEnd);
track.addEventListener('mousemove', dragAction);
track.addEventListener('touchmove', dragAction);
window.addEventListener('mousemove', handleHoverEffect);
function dragStart(e) {
isDragging = true;
startX = getPositionX(e);
animationID = requestAnimationFrame(animation);
track.style.transition = 'none';
}
function dragEnd() {
isDragging = false;
cancelAnimationFrame(animationID);
const movedBy = currentTranslate - prevTranslate;
if (movedBy < -100 && currentIndex < cards.length - 1) currentIndex += 1;
if (movedBy > 100 && currentIndex > 0) currentIndex -= 1;
setPositionByIndex();
}
function dragAction(e) {
if (isDragging) {
const currentPosition = getPositionX(e);
currentTranslate = prevTranslate + currentPosition - startX;
}
}
function getPositionX(e) {
return e.type.includes('mouse') ? e.pageX : e.touches[0].clientX;
}
function animation() {
setSliderPosition();
if (isDragging) requestAnimationFrame(animation);
}
function setSliderPosition() {
track.style.transform = `translateX(${currentTranslate}px)`;
updateCardParallax();
}
function setPositionByIndex() {
currentTranslate = currentIndex * -(340 + 40); // card width + gap
prevTranslate = currentTranslate;
track.style.transition = 'transform 0.6s cubic-bezier(0.23, 1, 0.32, 1)';
setSliderPosition();
updateDots();
}
function updateDots() {
document.querySelectorAll('.nav-dot').forEach((dot, i) => {
dot.classList.toggle('active', i === currentIndex);
});
}
// The "Secret Sauce": 3D Proximity Calculation
function updateCardParallax() {
const centerX = window.innerWidth / 2;
cards.forEach(card => {
const rect = card.getBoundingClientRect();
const cardCenter = rect.left + rect.width / 2;
const distanceFromCenter = cardCenter - centerX;
// Dynamic Rotation based on distance from viewport center
const rotateY = distanceFromCenter / 15;
const scale = Math.max(0.8, 1 - Math.abs(distanceFromCenter) / 2000);
const opacity = Math.max(0.4, 1 - Math.abs(distanceFromCenter) / 1000);
card.style.transform = `rotateY(${rotateY}deg) scale(${scale})`;
card.style.opacity = opacity;
// Move internal image slightly for extra depth
const img = card.querySelector('.product-image');
img.style.transform = `translate(-50%, -50%) translateZ(100px) translateX(${distanceFromCenter / 10}px)`;
});
}
// Lighting and Tilt Reactive behavior
function handleHoverEffect(e) {
const x = e.clientX;
const y = e.clientY;
// Ambient background follows mouse
ambient.style.left = `${x}px`;
ambient.style.top = `${y}px`;
cards.forEach(card => {
const rect = card.getBoundingClientRect();
const px = ((e.clientX - rect.left) / rect.width) * 100;
const py = ((e.clientY - rect.top) / rect.height) * 100;
// Set CSS variables for the spotlight effect
card.style.setProperty('--px', `${px}%`);
card.style.setProperty('--py', `${py}%`);
// Subtle local tilt on hover
if (e.target.closest('.card') === card) {
const tiltX = (y - (rect.top + rect.height/2)) / 15;
const tiltY = (x - (rect.left + rect.width/2)) / 15;
card.style.transform += ` rotateX(${-tiltX}deg) rotateY(${tiltY}deg)`;
}
});
}
// Initial Position
setPositionByIndex();
</script>
</body>
</html>