22 CSS Transition Effects 16 / 22

Card Tilt 3D Hover

Four cards with CSS custom property glare driven by --gx/--gy, floating gradient orbs with parallax offset, JS mousemove rotating up to 18 degrees.

CSS + JS MIT licensed
Live Demo Open in tab

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

Open in playground

The code

<h1>3D Card Tilt Effect</h1>
<p class="sub">Move your cursor over each card — perspective tilt with specular glare highlight</p>

<div class="grid">
  <div class="tilt-wrap tc1" id="c1">
    <div class="tilt-card">
      <div class="tilt-glare"></div>
      <div class="tilt-inner">
        <div class="tc-float" style="width:120px;height:120px;background:radial-gradient(#a78bfa,transparent);top:-30px;right:-30px;opacity:.4"></div>
        <div><div class="tc-badge">✦ Premium</div></div>
        <div>
          <span class="tc-icon">💎</span>
          <div class="tc-title">Holographic Card</div>
          <div class="tc-desc">CSS 3D tilt with a rotating conic gradient shimmer and a radial specular glare that follows your cursor.</div>
        </div>
        <div class="tc-footer">
          <span class="tc-action">Explore → </span>
          <span class="tc-stat">perspective: 1000px</span>
        </div>
      </div>
    </div>
  </div>

  <div class="tilt-wrap tc2" id="c2">
    <div class="tilt-card">
      <div class="tilt-glare"></div>
      <div class="tilt-inner">
        <div class="tc-float" style="width:100px;height:100px;background:radial-gradient(#fbbf24,transparent);bottom:-20px;left:-20px;opacity:.3"></div>
        <div><div class="tc-badge">★ Gold tier</div></div>
        <div>
          <span class="tc-icon">🏆</span>
          <div class="tc-title">Gold Edition</div>
          <div class="tc-desc">Warm amber gradient with a soft radial bloom. The tilt depth is controlled by JavaScript reading mousemove coordinates.</div>
        </div>
        <div class="tc-footer">
          <span class="tc-action">Unlock →</span>
          <span class="tc-stat">rotateX + rotateY</span>
        </div>
      </div>
    </div>
  </div>

  <div class="tilt-wrap tc3" id="c3">
    <div class="tilt-card">
      <div class="tilt-glare"></div>
      <div class="tilt-inner">
        <div class="tc-float" style="width:80px;height:80px;background:radial-gradient(#34d399,transparent);top:50%;right:10%;opacity:.25"></div>
        <div><div class="tc-badge">◈ Active</div></div>
        <div>
          <span class="tc-icon">⚡</span>
          <div class="tc-title">Neon Green</div>
          <div class="tc-desc">Deep forest background with teal glow accents. Floating gradient orbs shift with a parallax offset during tilt.</div>
        </div>
        <div class="tc-footer">
          <span class="tc-action">Connect →</span>
          <span class="tc-stat">will-change: transform</span>
        </div>
      </div>
    </div>
  </div>

  <div class="tilt-wrap tc4" id="c4">
    <div class="tilt-card">
      <div class="tilt-glare"></div>
      <div class="tilt-inner">
        <div class="tc-float" style="width:160px;height:160px;background:radial-gradient(rgba(148,163,184,.15),transparent);top:-40px;left:-40px"></div>
        <div><div class="tc-badge">◻ Standard</div></div>
        <div>
          <span class="tc-icon">🔮</span>
          <div class="tc-title">Chrome Grid</div>
          <div class="tc-desc">Diagonal grid texture with silver accents. The glare layer uses a CSS custom property for real-time cursor tracking.</div>
        </div>
        <div class="tc-footer">
          <span class="tc-action">Preview →</span>
          <span class="tc-stat">--gx/--gy props</span>
        </div>
      </div>
    </div>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Clash+Display:wght@400;600;700&family=General+Sans:wght@300;400;500;600&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap');
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Outfit',sans-serif;background:radial-gradient(ellipse at 30% 40%,#1a0533,#0d0d1a 60%,#000510);min-height:100vh;padding:60px 24px;display:flex;flex-direction:column;align-items:center}
h1{font-size:clamp(2rem,5vw,3.2rem);font-weight:700;color:#fff;text-align:center;margin-bottom:8px;letter-spacing:-.03em}
.sub{color:#6b7280;text-align:center;margin-bottom:60px;font-size:.9rem}

.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:32px;width:100%;max-width:1100px;perspective:2000px}

/* TILT CARD */
.tilt-wrap{perspective:1000px;width:100%}
.tilt-card{width:100%;border-radius:20px;position:relative;transform-style:preserve-3d;cursor:pointer;transition:transform .1s ease-out;will-change:transform}

/* glare layer */
.tilt-glare{position:absolute;inset:0;border-radius:20px;overflow:hidden;pointer-events:none;z-index:5}
.tilt-glare::after{content:'';position:absolute;width:100%;height:100%;background:radial-gradient(circle at var(--gx,50%) var(--gy,50%),rgba(255,255,255,.18),transparent 70%);opacity:0;transition:opacity .3s}
.tilt-wrap:hover .tilt-glare::after{opacity:1}

/* card content */
.tilt-inner{border-radius:20px;padding:32px;position:relative;overflow:hidden;height:340px;display:flex;flex-direction:column;justify-content:space-between}

/* Card 1 — Holographic */
.tc1 .tilt-inner{background:linear-gradient(135deg,#1a0533,#280648,#1a0533);border:1px solid rgba(167,139,250,.3)}
.tc1 .tilt-inner::before{content:'';position:absolute;inset:0;background:conic-gradient(from 0deg at 50% 50%,rgba(167,139,250,.08),rgba(236,72,153,.06),rgba(56,189,248,.08),rgba(167,139,250,.08));animation:trn16-holo 6s linear infinite}
@keyframes trn16-holo{to{transform:rotate(360deg)}}

/* Card 2 — Gold */
.tc2 .tilt-inner{background:linear-gradient(145deg,#1a1008,#2d1c06,#1a1008);border:1px solid rgba(251,191,36,.2)}
.tc2 .tilt-inner::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 30% 30%,rgba(251,191,36,.1),transparent 50%)}

/* Card 3 — Neon */
.tc3 .tilt-inner{background:linear-gradient(145deg,#001a14,#003020,#001a14);border:1px solid rgba(52,211,153,.25)}
.tc3 .tilt-inner::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 70% 70%,rgba(52,211,153,.08),transparent 50%)}

/* Card 4 — Chrome */
.tc4 .tilt-inner{background:linear-gradient(145deg,#111827,#1f2937,#111827);border:1px solid rgba(148,163,184,.15)}
.tc4 .tilt-inner::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,.04) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.04) 50%,rgba(255,255,255,.04) 75%,transparent 75%);background-size:20px 20px}

/* card elements */
.tc-badge{font-size:.65rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;padding:6px 12px;border-radius:20px;display:inline-flex;align-items:center;gap:6px;position:relative;z-index:2}
.tc1 .tc-badge{background:rgba(167,139,250,.15);color:#c4b5fd;border:1px solid rgba(167,139,250,.2)}
.tc2 .tc-badge{background:rgba(251,191,36,.12);color:#fde68a;border:1px solid rgba(251,191,36,.2)}
.tc3 .tc-badge{background:rgba(52,211,153,.12);color:#6ee7b7;border:1px solid rgba(52,211,153,.2)}
.tc4 .tc-badge{background:rgba(148,163,184,.1);color:#cbd5e1;border:1px solid rgba(148,163,184,.15)}

.tc-icon{font-size:3.5rem;display:block;position:relative;z-index:2;filter:drop-shadow(0 4px 16px rgba(0,0,0,.4))}
.tc-title{font-size:1.4rem;font-weight:700;color:#fff;margin-bottom:6px;position:relative;z-index:2}
.tc-desc{font-size:.82rem;color:rgba(255,255,255,.5);line-height:1.5;position:relative;z-index:2}
.tc-footer{display:flex;align-items:center;justify-content:space-between;position:relative;z-index:2}
.tc-action{font-size:.8rem;font-weight:600;color:var(--ac,#c4b5fd);display:flex;align-items:center;gap:6px}
.tc1{--ac:#c4b5fd}.tc2{--ac:#fde68a}.tc3{--ac:#6ee7b7}.tc4{--ac:#cbd5e1}
.tc-stat{font-size:.75rem;color:rgba(255,255,255,.35)}

/* parallax floating elements inside card */
.tc-float{position:absolute;border-radius:50%;pointer-events:none;z-index:1;transition:transform .15s ease-out}
document.querySelectorAll('.tilt-wrap').forEach(wrap => {
  const card = wrap.querySelector('.tilt-card');
  const glare = wrap.querySelector('.tilt-glare');
  const floats = wrap.querySelectorAll('.tc-float');
  const MAX_TILT = 18;

  wrap.addEventListener('mousemove', e => {
    const rect = wrap.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width;
    const y = (e.clientY - rect.top) / rect.height;
    const rotY = (x - .5) * MAX_TILT * 2;
    const rotX = (.5 - y) * MAX_TILT * 2;
    card.style.transform = `rotateX(${rotX}deg) rotateY(${rotY}deg) scale(1.04)`;
    glare.style.setProperty('--gx', (x * 100) + '%');
    glare.style.setProperty('--gy', (y * 100) + '%');
    glare.querySelector('::after');
    // Parallax floats
    floats.forEach(f => {
      f.style.transform = `translate(${(x-.5)*20}px,${(y-.5)*20}px)`;
    });
  });

  wrap.addEventListener('mouseleave', () => {
    card.style.transform = 'rotateX(0) rotateY(0) scale(1)';
    floats.forEach(f => { f.style.transform = ''; });
  });
});

Search CodeFronts

Loading…