UI Component
✨ NewUI Element

Holographic 3D Tilt Cards with Flip Animation

Collectible-style cards that tilt in 3D as you move your cursor or finger, with a rainbow holographic foil and a glare that follows the pointer. Click or press Enter to flip a card and reveal its back. Built with pure HTML, CSS and vanilla JavaScript.

September 26, 20263 views
  • Cards
  • cards
  • 3d-tilt
  • holographic
  • hover-effect
  • flip-card
  • css-animation
Holographic 3D Tilt Cards with Flip Animation
Free

Download instantly, no signup required.

Features Included

Smooth 3D tilt driven by pointer position (mouse and touch)
Rainbow holographic foil using blend modes, stronger at the edges
Glare highlight that follows the pointer
Click / tap / Enter to flip and show the card back
Three ready-made cards with SVG artwork and stats
Keyboard accessible and responsive
Dependencies
Google Fonts — Space Groteskcdn

Holographic 3D Tilt Cards with Flip Animation

Trading-card style UI with a real holographic feel — 3D tilt, rainbow foil, moving glare and a flip animation. Pure HTML, CSS and vanilla JavaScript.


What's Included

  • Smooth 3D tilt driven by pointer position (mouse and touch)
  • Rainbow holographic foil using blend modes, stronger at the edges
  • Glare highlight that follows the pointer
  • Click / tap / Enter to flip and show the card back
  • Three ready-made cards with SVG artwork and stats
  • Keyboard accessible and responsive

Dependencies

Already linked inside the component's files — no extra setup needed.


Desktop Preview


HTML

html
1<!doctype html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6    <title>Holographic 3D Tilt Cards | MetaSkillGroup</title>
7    <link rel="stylesheet" href="style.css" />
8  </head>
9  <body>
10    <!-- created by metaskillgroup-team -->
11    <main class="showcase">
12      <header class="intro">
13        <h1>Holo<span>Cards</span></h1>
14        <p>Move your cursor (or finger) over a card to tilt it. Click to flip.</p>
15      </header>
16
17      <div class="deck">
18        <!-- Card 1 -->
19        <div class="card" style="--c1: #7c5cff; --c2: #22d3ee" tabindex="0" aria-label="Frontend Wizard card, press Enter to flip">
20          <div class="card-inner">
21            <div class="face front">
22              <div class="card-head">
23                <span class="card-name">Frontend Wizard</span>
24                <span class="card-hp">HP <b>120</b></span>
25              </div>
26              <div class="card-art">
27                <svg viewBox="0 0 200 140" aria-hidden="true">
28                  <defs>
29                    <linearGradient id="g1" x1="0" x2="1" y1="0" y2="1">
30                      <stop offset="0" stop-color="#7c5cff" />
31                      <stop offset="1" stop-color="#22d3ee" />
32                    </linearGradient>
33                  </defs>
34                  <circle cx="100" cy="70" r="46" fill="url(#g1)" opacity=".25" />
35                  <path d="M70 90 L100 30 L130 90 Z" fill="none" stroke="url(#g1)" stroke-width="4" stroke-linejoin="round" />
36                  <path d="M82 70 l-14 12 14 12 M118 70 l14 12 -14 12 M106 64 l-12 36" fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
37                  <circle cx="100" cy="30" r="6" fill="#fff" />
38                </svg>
39              </div>
40              <div class="card-type"><span>⚡ Rare</span><span>#001</span></div>
41              <ul class="card-moves">
42                <li><b>Pixel Perfect</b><em>60</em></li>
43                <li><b>Flexbox Fury</b><em>90</em></li>
44              </ul>
45              <p class="card-flavor">Turns Figma files into living, breathing interfaces.</p>
46            </div>
47            <div class="face back">
48              <div class="back-logo">M</div>
49              <p>MetaSkill</p>
50              <small>Collectors Edition</small>
51            </div>
52          </div>
53          <div class="holo" aria-hidden="true"></div>
54          <div class="glare" aria-hidden="true"></div>
55        </div>
56
57        <!-- Card 2 -->
58        <div class="card" style="--c1: #f97316; --c2: #f43f5e" tabindex="0" aria-label="Backend Titan card, press Enter to flip">
59          <div class="card-inner">
60            <div class="face front">
61              <div class="card-head">
62                <span class="card-name">Backend Titan</span>
63                <span class="card-hp">HP <b>150</b></span>
64              </div>
65              <div class="card-art">
66                <svg viewBox="0 0 200 140" aria-hidden="true">
67                  <defs>
68                    <linearGradient id="g2" x1="0" x2="1" y1="0" y2="1">
69                      <stop offset="0" stop-color="#f97316" />
70                      <stop offset="1" stop-color="#f43f5e" />
71                    </linearGradient>
72                  </defs>
73                  <circle cx="100" cy="70" r="46" fill="url(#g2)" opacity=".25" />
74                  <rect x="66" y="34" width="68" height="20" rx="6" fill="none" stroke="url(#g2)" stroke-width="4" />
75                  <rect x="66" y="60" width="68" height="20" rx="6" fill="none" stroke="url(#g2)" stroke-width="4" />
76                  <rect x="66" y="86" width="68" height="20" rx="6" fill="none" stroke="url(#g2)" stroke-width="4" />
77                  <circle cx="78" cy="44" r="3" fill="#fff" /><circle cx="78" cy="70" r="3" fill="#fff" /><circle cx="78" cy="96" r="3" fill="#fff" />
78                </svg>
79              </div>
80              <div class="card-type"><span>🔥 Epic</span><span>#002</span></div>
81              <ul class="card-moves">
82                <li><b>Query Storm</b><em>80</em></li>
83                <li><b>Zero Downtime</b><em>120</em></li>
84              </ul>
85              <p class="card-flavor">Scales to a million users before breakfast.</p>
86            </div>
87            <div class="face back">
88              <div class="back-logo">M</div>
89              <p>MetaSkill</p>
90              <small>Collectors Edition</small>
91            </div>
92          </div>
93          <div class="holo" aria-hidden="true"></div>
94          <div class="glare" aria-hidden="true"></div>
95        </div>
96
97        <!-- Card 3 -->
98        <div class="card" style="--c1: #10b981; --c2: #a3e635" tabindex="0" aria-label="Design Oracle card, press Enter to flip">
99          <div class="card-inner">
100            <div class="face front">
101              <div class="card-head">
102                <span class="card-name">Design Oracle</span>
103                <span class="card-hp">HP <b>110</b></span>
104              </div>
105              <div class="card-art">
106                <svg viewBox="0 0 200 140" aria-hidden="true">
107                  <defs>
108                    <linearGradient id="g3" x1="0" x2="1" y1="0" y2="1">
109                      <stop offset="0" stop-color="#10b981" />
110                      <stop offset="1" stop-color="#a3e635" />
111                    </linearGradient>
112                  </defs>
113                  <circle cx="100" cy="70" r="46" fill="url(#g3)" opacity=".25" />
114                  <circle cx="84" cy="62" r="20" fill="none" stroke="url(#g3)" stroke-width="4" />
115                  <circle cx="116" cy="62" r="20" fill="none" stroke="url(#g3)" stroke-width="4" />
116                  <circle cx="100" cy="88" r="20" fill="none" stroke="url(#g3)" stroke-width="4" />
117                  <circle cx="100" cy="70" r="5" fill="#fff" />
118                </svg>
119              </div>
120              <div class="card-type"><span>✨ Legendary</span><span>#003</span></div>
121              <ul class="card-moves">
122                <li><b>Color Harmony</b><em>70</em></li>
123                <li><b>Grid Mastery</b><em>100</em></li>
124              </ul>
125              <p class="card-flavor">Sees whitespace the way others see gold.</p>
126            </div>
127            <div class="face back">
128              <div class="back-logo">M</div>
129              <p>MetaSkill</p>
130              <small>Collectors Edition</small>
131            </div>
132          </div>
133          <div class="holo" aria-hidden="true"></div>
134          <div class="glare" aria-hidden="true"></div>
135        </div>
136      </div>
137    </main>
138
139    <script src="script.js"></script>
140  </body>
141</html>
142

CSS

css
1/* Importing Google Fonts - Space Grotesk */
2@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap");
3
4* {
5  margin: 0;
6  padding: 0;
7  box-sizing: border-box;
8  font-family: "Space Grotesk", sans-serif;
9}
10
11:root {
12  --bg: #0a0a12;
13  --text: #f5f5fa;
14  --muted: #8f8fa8;
15}
16
17body {
18  min-height: 100vh;
19  color: var(--text);
20  background:
21    radial-gradient(circle at 20% 20%, rgba(124, 92, 255, 0.15), transparent 40%),
22    radial-gradient(circle at 80% 80%, rgba(244, 63, 94, 0.12), transparent 40%),
23    var(--bg);
24}
25
26.showcase {
27  max-width: 1200px;
28  margin: 0 auto;
29  padding: 70px 20px 90px;
30}
31
32.intro {
33  text-align: center;
34  margin-bottom: 60px;
35}
36
37.intro h1 {
38  font-size: clamp(2.6rem, 7vw, 4.4rem);
39  font-weight: 700;
40  letter-spacing: -0.04em;
41}
42
43.intro h1 span {
44  background: linear-gradient(90deg, #7c5cff, #22d3ee, #a3e635, #f97316, #f43f5e);
45  background-size: 200% auto;
46  -webkit-background-clip: text;
47  background-clip: text;
48  color: transparent;
49  animation: rainbow 6s linear infinite;
50}
51
52@keyframes rainbow {
53  to {
54    background-position: 200% center;
55  }
56}
57
58.intro p {
59  margin-top: 10px;
60  color: var(--muted);
61}
62
63/* ---------- Deck ---------- */
64.deck {
65  display: flex;
66  flex-wrap: wrap;
67  justify-content: center;
68  gap: 40px;
69  perspective: 1200px;
70}
71
72/* ---------- Card ---------- */
73.card {
74  --rx: 0deg;
75  --ry: 0deg;
76  --px: 50%;
77  --py: 50%;
78  --hyp: 0;
79  position: relative;
80  width: 280px;
81  aspect-ratio: 5 / 7;
82  border-radius: 20px;
83  cursor: pointer;
84  outline: none;
85  transform-style: preserve-3d;
86  transform: rotateX(var(--rx)) rotateY(var(--ry));
87  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
88  will-change: transform;
89}
90
91.card.active {
92  transition: transform 0.08s linear;
93}
94
95.card:focus-visible {
96  box-shadow: 0 0 0 3px var(--c2);
97}
98
99.card-inner {
100  position: absolute;
101  inset: 0;
102  transform-style: preserve-3d;
103  transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
104}
105
106.card.flipped .card-inner {
107  transform: rotateY(180deg);
108}
109
110.face {
111  position: absolute;
112  inset: 0;
113  border-radius: 20px;
114  backface-visibility: hidden;
115  -webkit-backface-visibility: hidden;
116  overflow: hidden;
117  box-shadow: 0 25px 60px rgba(0, 0, 0, 0.55);
118}
119
120/* ---------- Front face ---------- */
121.front {
122  display: flex;
123  flex-direction: column;
124  gap: 10px;
125  padding: 14px;
126  background:
127    linear-gradient(160deg, color-mix(in srgb, var(--c1) 35%, #15151f), #15151f 55%, color-mix(in srgb, var(--c2) 30%, #15151f));
128  border: 6px solid transparent;
129  background-clip: padding-box;
130  outline: 2px solid color-mix(in srgb, var(--c1) 70%, #fff);
131  outline-offset: -6px;
132}
133
134.card-head {
135  display: flex;
136  justify-content: space-between;
137  align-items: baseline;
138}
139
140.card-name {
141  font-weight: 700;
142  font-size: 1.05rem;
143}
144
145.card-hp {
146  font-size: 0.72rem;
147  color: var(--muted);
148}
149
150.card-hp b {
151  font-size: 1.1rem;
152  color: var(--text);
153}
154
155.card-art {
156  flex: 1;
157  display: grid;
158  place-items: center;
159  border-radius: 10px;
160  background:
161    radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--c2) 40%, transparent), transparent 70%),
162    #0c0c14;
163  border: 2px solid rgba(255, 255, 255, 0.12);
164  overflow: hidden;
165}
166
167.card-art svg {
168  width: 90%;
169  filter: drop-shadow(0 0 12px color-mix(in srgb, var(--c1) 60%, transparent));
170  animation: bob 4s ease-in-out infinite;
171}
172
173@keyframes bob {
174  50% {
175    transform: translateY(-6px);
176  }
177}
178
179.card-type {
180  display: flex;
181  justify-content: space-between;
182  padding: 4px 10px;
183  border-radius: 6px;
184  font-size: 0.72rem;
185  font-weight: 600;
186  background: rgba(255, 255, 255, 0.08);
187}
188
189.card-moves {
190  list-style: none;
191}
192
193.card-moves li {
194  display: flex;
195  justify-content: space-between;
196  padding: 6px 2px;
197  font-size: 0.85rem;
198  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
199}
200
201.card-moves em {
202  font-style: normal;
203  font-weight: 700;
204  color: var(--c2);
205}
206
207.card-flavor {
208  font-size: 0.7rem;
209  font-style: italic;
210  color: var(--muted);
211  line-height: 1.4;
212  min-height: 2.8em;
213}
214
215/* ---------- Back face ---------- */
216.back {
217  display: flex;
218  flex-direction: column;
219  align-items: center;
220  justify-content: center;
221  gap: 6px;
222  transform: rotateY(180deg);
223  background:
224    repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.04) 0 10px, transparent 10px 20px),
225    linear-gradient(145deg, var(--c1), var(--c2));
226  border: 8px solid #15151f;
227}
228
229.back-logo {
230  display: grid;
231  place-items: center;
232  width: 96px;
233  height: 96px;
234  border-radius: 50%;
235  font-size: 3rem;
236  font-weight: 700;
237  background: #15151f;
238  box-shadow:
239    0 0 0 6px rgba(255, 255, 255, 0.25),
240    0 0 40px rgba(0, 0, 0, 0.4);
241}
242
243.back p {
244  margin-top: 14px;
245  font-size: 1.4rem;
246  font-weight: 700;
247  letter-spacing: 0.1em;
248  text-transform: uppercase;
249}
250
251.back small {
252  font-size: 0.75rem;
253  opacity: 0.85;
254}
255
256/* ---------- Holo + glare overlays ---------- */
257.holo,
258.glare {
259  position: absolute;
260  inset: 0;
261  border-radius: 20px;
262  pointer-events: none;
263  transform: translateZ(2px);
264  opacity: 0;
265  transition: opacity 0.4s ease;
266}
267
268/* Rainbow foil that shifts with the pointer */
269.holo {
270  background:
271    repeating-linear-gradient(
272      115deg,
273      #ff0080 0%,
274      #ffb300 8%,
275      #3dff8a 16%,
276      #00c3ff 24%,
277      #a64dff 32%,
278      #ff0080 40%
279    ),
280    repeating-linear-gradient(35deg, rgba(255, 255, 255, 0.4) 0 2px, transparent 2px 6px);
281  background-size:
282    300% 300%,
283    100% 100%;
284  background-position:
285    var(--px) var(--py),
286    center;
287  mix-blend-mode: color-dodge;
288  filter: brightness(0.6) contrast(1.4) saturate(1.2);
289}
290
291/* Soft light spot under the pointer */
292.glare {
293  background: radial-gradient(
294    circle at var(--px) var(--py),
295    rgba(255, 255, 255, 0.55) 0%,
296    rgba(255, 255, 255, 0.15) 25%,
297    transparent 55%
298  );
299  mix-blend-mode: overlay;
300}
301
302.card.active .holo {
303  opacity: calc(0.35 + var(--hyp) * 0.5);
304}
305
306.card.active .glare {
307  opacity: 1;
308}
309
310/* ---------- Responsive ---------- */
311@media (max-width: 640px) {
312  .deck {
313    gap: 28px;
314  }
315
316  .card {
317    width: min(280px, 82vw);
318  }
319}
320
321@media (prefers-reduced-motion: reduce) {
322  *,
323  *::before,
324  *::after {
325    animation: none !important;
326  }
327}
328

JavaScript

javascript
1const cards = document.querySelectorAll(".card");
2const MAX_TILT = 16; // degrees
3
4cards.forEach((card) => {
5  let resetTimer;
6
7  const update = (e) => {
8    const rect = card.getBoundingClientRect();
9    // Pointer position inside the card, 0..1
10    const x = Math.min(Math.max((e.clientX - rect.left) / rect.width, 0), 1);
11    const y = Math.min(Math.max((e.clientY - rect.top) / rect.height, 0), 1);
12    const dx = x - 0.5;
13    const dy = y - 0.5;
14
15    // Flipped cards mirror horizontally, so invert the Y rotation
16    const flip = card.classList.contains("flipped") ? -1 : 1;
17
18    card.style.setProperty("--rx", `${-dy * MAX_TILT * 2}deg`);
19    card.style.setProperty("--ry", `${dx * MAX_TILT * 2 * flip}deg`);
20    card.style.setProperty("--px", `${x * 100}%`);
21    card.style.setProperty("--py", `${y * 100}%`);
22    // Distance from the centre drives how strong the foil looks
23    card.style.setProperty("--hyp", Math.min(Math.hypot(dx, dy) * 2, 1).toFixed(2));
24  };
25
26  card.addEventListener("pointerenter", () => {
27    clearTimeout(resetTimer);
28    card.classList.add("active");
29  });
30
31  card.addEventListener("pointermove", update);
32
33  card.addEventListener("pointerleave", () => {
34    card.classList.remove("active");
35    card.style.setProperty("--rx", "0deg");
36    card.style.setProperty("--ry", "0deg");
37    resetTimer = setTimeout(() => {
38      card.style.setProperty("--px", "50%");
39      card.style.setProperty("--py", "50%");
40    }, 400);
41  });
42
43  // Flip on click / tap / keyboard
44  const flip = () => card.classList.toggle("flipped");
45  card.addEventListener("click", flip);
46  card.addEventListener("keydown", (e) => {
47    if (e.key === "Enter" || e.key === " ") {
48      e.preventDefault();
49      flip();
50    }
51  });
52});
53

Built by Meta Skill Group — copy it, use it, make it yours.

Built With

🌐

HTML5

⚡

JavaScript

🎨

CSS3

Compatibility

Browsers
ChromeOperaBraveFirefoxSafariArcVivaldiEdge
Devices
DesktopMobileSmartwatchTVTablet
Frameworks
HTML/CSSVanilla JS

Found this useful?

MetaSkillGroup

Written by

MetaSkillGroup

September 26, 2026

❓ FAQs

Subscribe to Newsletter

Get latest updates, tutorials and resources delivered to your inbox.

No spam. Unsubscribe anytime.

Holographic 3D Tilt Cards | HTML CSS JS | MetaSkillGroup