Back to Components
3D Interactive Flip Cards with Tilt and Bounce Animation using HTML, CSS & JavaScript
Component

3D Interactive Flip Cards with Tilt and Bounce Animation using HTML, CSS & JavaScript

CodewithLord
October 4, 2025

Experience smooth 3D flip animations with realistic tilt and bounce effects using just HTML, CSS, and JavaScript

🧠 Description

Experience smooth 3D flip animations with realistic tilt and bounce effects using just HTML, CSS, and JavaScript. Each card flips on click (or tap) to reveal more details on the back and tilts dynamically with mouse movement for a futuristic, interactive experience. Perfect for portfolios, product showcases, or feature highlights, this project combines modern UI design with subtle motion effects to create an engaging user interface.


💻 HTML Code


1<!DOCTYPE html> 2<html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>3D Interactive Cards with Tilt &amp; Bounce</title> 7 <link rel="stylesheet" href="./style.css"> 8 9 </head> 10 11 <body> 12 <div class="card-grid"> 13 14 <!-- Card 1 --> 15 <div class="card"> 16 <div class="card-inner"> 17 <div class="card-face card-front one"> 18 <div> 19 <h2>Quantum UI</h2> 20 <p>Next-gen UI framework designed for speed, interactivity, and effortless scalability.</p> 21 </div> 22 <p>Tap or click to flip</p> 23 </div> 24 <div class="card-face card-back"> 25 <div> 26 <h3>Features</h3> 27 <ul class="features"> 28 <li>Lightning-fast rendering</li> 29 <li>Modular component system</li> 30 <li>Seamless API integration</li> 31 <li>AI-powered UI suggestions</li> 32 </ul> 33 </div> 34 <div class="cta-buttons"> 35 <a href="#" class="primary">Get Started</a> 36 <a href="#" class="secondary">Learn More</a> 37 </div> 38 </div> 39 </div> 40 </div> 41 42 <!-- Card 2 --> 43 <div class="card"> 44 <div class="card-inner"> 45 <div class="card-face card-front two"> 46 <div> 47 <h2>Neon Cloud</h2> 48 <p>Cloud-native infrastructure that scales dynamically and keeps latency near zero.</p> 49 </div> 50 <p>Tap or click to flip</p> 51 </div> 52 <div class="card-face card-back"> 53 <div> 54 <h3>Advantages</h3> 55 <ul class="features"> 56 <li>Auto-scaling engine</li> 57 <li>low-latency network</li> 58 <li>Zero-downtime</li> 59 <li>Built-in analytics</li> 60 </ul> 61 </div> 62 <div class="cta-buttons"> 63 <a href="#" class="primary">Deploy Now</a> 64 <a href="#" class="secondary">Docs</a> 65 </div> 66 </div> 67 </div> 68 </div> 69 70 <!-- Card 3 --> 71 <div class="card"> 72 <div class="card-inner"> 73 <div class="card-face card-front three"> 74 <div> 75 <h2>Nova AI</h2> 76 <p>Advanced AI toolkit to build, train, and deploy models directly in the browser.</p> 77 </div> 78 <p>Tap or click to flip</p> 79 </div> 80 <div class="card-face card-back"> 81 <div> 82 <h3>What's Inside</h3> 83 <ul class="features"> 84 <li>In-browser training engine</li> 85 <li>Model visualization tools</li> 86 <li>Secure model hosting</li> 87 <li>Dataset builder</li> 88 </ul> 89 </div> 90 <div class="cta-buttons"> 91 <a href="#" class="primary">Try Nova</a> 92 <a href="#" class="secondary">Explore API</a> 93 </div> 94 </div> 95 </div> 96 </div> 97 98 <!-- Card 4 --> 99 <div class="card"> 100 <div class="card-inner"> 101 <div class="card-face card-front four"> 102 <div> 103 <h2>Pulse Metrics</h2> 104 <p>Real-time monitoring platform with predictive analytics and anomaly detection.</p> 105 </div> 106 <p>Tap or click to flip</p> 107 </div> 108 <div class="card-face card-back"> 109 <div> 110 <h3>Highlights</h3> 111 <ul class="features"> 112 <li>Live dashboards</li> 113 <li>Predictive forecasting</li> 114 <li>Custom alerts & triggers</li> 115 <li>AI-based anomaly tracking</li> 116 </ul> 117 </div> 118 <div class="cta-buttons"> 119 <a href="#" class="primary">Start Free</a> 120 <a href="#" class="secondary">View Demo</a> 121 </div> 122 </div> 123 </div> 124 </div> 125 126</div> 127 <script src="./script.js"></script> 128 129 </body> 130 131</html> 132

.card-grid — A responsive grid container that holds all the cards.

.card — Each individual card element that reacts to user interaction.

.card-inner — The 3D container that flips between front and back.

.card-face — Two sides of the card:

.card-front → visible by default.

.card-back → revealed when flipped (rotated 180°).

Each card includes titles, short descriptions, feature lists, and CTA (Call To Action) buttons.


CSS Code


1@import url("https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Inter:wght@400;600&display=swap"); 2 3:root { 4 --bg: #0a0c10; 5 --card-bg: rgba(20, 25, 35, 0.9); 6 --accent: #00f5ff; 7 --text: #fafbfd; 8 --text-dim: #c6c7cc; 9 --radius: 20px; 10 --shadow: 0 10px 30px rgba(0, 255, 255, 0.2); 11} 12 13* { 14 box-sizing: border-box; 15 margin: 0; 16 padding: 0; 17} 18 19body { 20 background: var(--bg); 21 color: var(--text); 22 font-family: "Inter", sans-serif; 23 display: flex; 24 justify-content: center; 25 align-items: center; 26 min-height: 100vh; 27 padding: 40px; 28} 29 30.card-grid { 31 display: grid; 32 grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); 33 gap: 30px; 34 width: 100%; 35 max-width: 1200px; 36} 37 38.card { 39 perspective: 1000px; 40 cursor: pointer; 41 position: relative; 42 transform-style: preserve-3d; 43} 44 45.card-inner { 46 position: relative; 47 width: 100%; 48 min-height: 360px; 49 transform-style: preserve-3d; 50 border-radius: var(--radius); 51 transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1); 52} 53 54.card.flipped .card-inner { 55 transform: rotateY(180deg); 56} 57 58.card-face { 59 position: absolute; 60 inset: 0; 61 border-radius: var(--radius); 62 background: var(--card-bg); 63 box-shadow: var(--shadow); 64 padding: 24px; 65 display: flex; 66 flex-direction: column; 67 justify-content: space-between; 68 backface-visibility: hidden; 69 transform-style: preserve-3d; 70 transition: box-shadow 0.3s, filter 0.3s; 71} 72 73.card-face::before { 74 content: ""; 75 position: absolute; 76 inset: 0; 77 border-radius: var(--radius); 78 box-shadow: 0 0 12px rgba(0, 255, 255, 0.25), 79 0 0 25px rgba(0, 255, 255, 0.15) inset; 80 opacity: 0; 81 transition: opacity 0.4s; 82} 83 84.card:hover .card-face::before, 85.card.flipped .card-face::before { 86 opacity: 1; 87 animation: pulse 2s infinite alternate; 88} 89 90@keyframes pulse { 91 0% { 92 box-shadow: 0 0 12px rgba(0, 255, 255, 0.25), 93 0 0 25px rgba(0, 255, 255, 0.15) inset; 94 } 95 50% { 96 box-shadow: 0 0 22px rgba(0, 255, 255, 0.4), 97 0 0 35px rgba(0, 255, 255, 0.25) inset; 98 } 99 100% { 100 box-shadow: 0 0 12px rgba(0, 255, 255, 0.25), 101 0 0 25px rgba(0, 255, 255, 0.15) inset; 102 } 103} 104 105.card-front h2 { 106 font-family: "Orbitron", sans-serif; 107 font-size: 1.6rem; 108 color: var(--accent); 109 margin-bottom: 0.5rem; 110} 111 112.card-front p { 113 font-size: 1rem; 114 color: var(--text-dim); 115 line-height: 1.5; 116} 117 118.one { 119 background: url("https://iili.io/KSTN6ps.png"); 120 background-position: center; 121 background-repeat: no-repeat; 122 background-size: cover; 123} 124.two { 125 background: url("https://iili.io/KSTNsjf.png"); 126 background-position: center; 127 background-repeat: no-repeat; 128 background-size: cover; 129} 130.three { 131 background: url("https://iili.io/KSTNLQ4.png"); 132 background-position: center; 133 background-repeat: no-repeat; 134 background-size: cover; 135} 136.four { 137 background: url("https://iili.io/KST8L1R.png"); 138 background-position: center; 139 background-repeat: no-repeat; 140 background-size: cover; 141} 142 143.card-back { 144 transform: rotateY(180deg); 145 display: flex; 146 flex-direction: column; 147 justify-content: space-between; 148} 149 150.card-back h3 { 151 font-family: "Orbitron", sans-serif; 152 font-size: 1.4rem; 153 color: var(--accent); 154 margin-bottom: 1rem; 155} 156 157ul.features { 158 list-style: none; 159 padding: 0; 160 margin: 0; 161} 162 163ul.features li { 164 margin-bottom: 0.6rem; 165 padding-left: 1.4rem; 166 position: relative; 167 color: var(--text-dim); 168 font-size: 0.95rem; 169} 170 171ul.features li::before { 172 content: "⚡"; 173 position: absolute; 174 left: 0; 175 color: var(--accent); 176} 177 178.cta-buttons { 179 display: flex; 180 gap: 12px; 181 margin-top: 1.5rem; 182} 183 184.cta-buttons a { 185 flex: 1; 186 text-align: center; 187 text-decoration: none; 188 padding: 10px 14px; 189 border-radius: 8px; 190 font-weight: 600; 191 transition: all 0.3s; 192} 193 194.cta-buttons a.primary { 195 background: var(--accent); 196 color: #000; 197} 198 199.cta-buttons a.primary:hover { 200 background: #00ffff; 201} 202 203.cta-buttons a.secondary { 204 border: 1px solid var(--accent); 205 color: var(--accent); 206} 207 208.cta-buttons a.secondary:hover { 209 background: rgba(0, 255, 255, 0.1); 210} 211 212@media (max-width: 768px) { 213 body { 214 padding: 20px; 215 } 216 .card-inner { 217 min-height: 300px; 218 } 219 .card-face { 220 padding: 18px; 221 } 222 .card-front h2 { 223 font-size: 1.3rem; 224 } 225 .card-back h3 { 226 font-size: 1.2rem; 227 } 228 ul.features li { 229 font-size: 0.9rem; 230 } 231}

perspective gives a sense of 3D depth.

preserve-3d allows front and back faces to exist in 3D space.

When the .flipped class is added, the card rotates 180° on the Y-axis to reveal the back side. Adds a cyberpunk glow effect on hover.

Uses @keyframes pulse to make the glow breathe dynamically.

🧬 Typography & Color Scheme

Fonts: “Orbitron” for headings (tech style), “Inter” for readability.

Accent Color: Cyan (#00f5ff) for a futuristic look.

Backgrounds: Dark gradient with translucent card backgrounds.

📱 Responsiveness

Uses grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)) to make the layout automatically adjust for mobile.

Text and padding scale down below 768px.

Javascipt Code


1 2const isTouch = "ontouchstart" in window; 3 4document.querySelectorAll(".card").forEach((card) => { 5 const inner = card.querySelector(".card-inner"); 6 7 // Tap/click flip met subtiele scale-bounce 8 card.addEventListener("click", () => { 9 const baseRotate = card.classList.contains("flipped") ? 0 : 180; 10 11 inner.style.transition = "transform 0.15s ease-out"; 12 inner.style.transform = `rotateY(${baseRotate}deg) scale(1.05)`; 13 14 setTimeout(() => { 15 inner.style.transition = "transform 0.7s cubic-bezier(.4,.2,.2,1)"; 16 inner.style.transform = `rotateY(${baseRotate}deg) scale(1)`; 17 card.classList.toggle("flipped"); 18 }, 150); 19 }); 20 21 if (!isTouch) { 22 card.addEventListener("mousemove", (e) => { 23 const rect = card.getBoundingClientRect(); 24 const x = e.clientX - rect.left; 25 const y = e.clientY - rect.top; 26 const centerX = rect.width / 2; 27 const centerY = rect.height / 2; 28 const rotateX = ((y - centerY) / centerY) * -10; 29 const rotateY = ((x - centerX) / centerX) * 10; 30 const baseRotate = card.classList.contains("flipped") ? 180 : 0; 31 inner.style.transform = `rotateY(${baseRotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1)`; 32 }); 33 34 card.addEventListener("mouseleave", () => { 35 const baseRotate = card.classList.contains("flipped") ? 180 : 0; 36 inner.style.transform = `rotateY(${baseRotate}deg) rotateX(0deg) rotateY(0deg) scale(1)`; 37 }); 38 } 39});const isTouch = "ontouchstart" in window; 40 41document.querySelectorAll(".card").forEach((card) => { 42 const inner = card.querySelector(".card-inner"); 43 44 // Tap/click flip met subtiele scale-bounce 45 card.addEventListener("click", () => { 46 const baseRotate = card.classList.contains("flipped") ? 0 : 180; 47 48 inner.style.transition = "transform 0.15s ease-out"; 49 inner.style.transform = `rotateY(${baseRotate}deg) scale(1.05)`; 50 51 setTimeout(() => { 52 inner.style.transition = "transform 0.7s cubic-bezier(.4,.2,.2,1)"; 53 inner.style.transform = `rotateY(${baseRotate}deg) scale(1)`; 54 card.classList.toggle("flipped"); 55 }, 150); 56 }); 57 58 if (!isTouch) { 59 card.addEventListener("mousemove", (e) => { 60 const rect = card.getBoundingClientRect(); 61 const x = e.clientX - rect.left; 62 const y = e.clientY - rect.top; 63 const centerX = rect.width / 2; 64 const centerY = rect.height / 2; 65 const rotateX = ((y - centerY) / centerY) * -10; 66 const rotateY = ((x - centerX) / centerX) * 10; 67 const baseRotate = card.classList.contains("flipped") ? 180 : 0; 68 inner.style.transform = `rotateY(${baseRotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1)`; 69 }); 70 71 card.addEventListener("mouseleave", () => { 72 const baseRotate = card.classList.contains("flipped") ? 180 : 0; 73 inner.style.transform = `rotateY(${baseRotate}deg) rotateX(0deg) rotateY(0deg) scale(1)`; 74 }); 75 } 76}); 77

The JavaScript adds interactivity and motion logic.

Touch Detection

The code first checks if the user’s device supports touch input.

If it’s a touch device (like a phone), only the click-to-flip feature is active.

If it’s a desktop, additional mouse-based tilt effects are enabled.

Card Flipping Interaction

When you click or tap a card:

The card slightly scales up for a “bounce” effect.

Then it smoothly rotates 180 degrees along the Y-axis.

The .flipped class is toggled, which triggers the CSS to switch between the front and back faces.

Clicking again flips it back to the original side.

This makes it feel like a real card flipping in 3D space.

Tilt Effect (Desktop Only)

When you move the mouse across a card:

The JavaScript calculates how far the mouse is from the card’s center.

Based on that position, it tilts the card slightly up, down, left, or right.

The farther you move from the center, the stronger the tilt.

When you move the mouse away, the card smoothly returns to its flat, neutral position.

Smooth Transitions and Timing

The script uses small delays and easing transitions to make movements smooth and natural.

The bounce when flipping, and the gentle tilt return, add a realistic physical feel.

Love this component?

Explore more components and build amazing UIs.

View All Components