Skip to content

Tilt 3D

A copy-paste cards & hover component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

Cards & HoverHTMLCSSJavaScriptany framework
Tilt 3D
Tilts toward cursor

Copy into your project

HTML
<!-- Tilt 3D — 3D tilt toward cursor (vanilla JS) -->
<div class="nuda-tilt3d">
  <div class="nuda-tilt3d__inner">
    <h3 class="nuda-tilt3d__title">Tilt 3D</h3>
    <p class="nuda-tilt3d__desc">Tilts toward your cursor</p>
  </div>
</div>
CSS
/* ── Tilt 3D ─────────────────────────────────────────────────
   Tilt driven by JS via --nuda-t3-rx / -ry custom properties.
   Customize:
     --nuda-t3-bg     : card background
   ──────────────────────────────────────────────────────────── */
.nuda-tilt3d {
  --nuda-t3-rx: 0deg;
  --nuda-t3-ry: 0deg;

  width: 280px;
  perspective: 800px;
}

.nuda-tilt3d__inner {
  padding: 32px 24px;
  background: linear-gradient(135deg, #18181b, #09090b);
  border: 1px solid rgba(228, 255, 84, 0.15);
  border-radius: 16px;
  color: #fafafa;
  text-align: center;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
  transform: rotateX(var(--nuda-t3-rx)) rotateY(var(--nuda-t3-ry));
  transition: transform 0.15s ease;
  will-change: transform;
}

.nuda-tilt3d__title {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0;
}

.nuda-tilt3d__desc {
  font-size: 0.85rem;
  opacity: 0.65;
  margin: 6px 0 0;
}

/* ── Accessibility ──────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .nuda-tilt3d__inner {
    transition: none;
    transform: none !important;
  }
}
JavaScript
/* ── Tilt 3D — vanilla JS ────────────────────────────────────
   Maps cursor position to rotateX / rotateY.
   Respects prefers-reduced-motion.
   ──────────────────────────────────────────────────────────── */
;(function () {
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;

  var maxTilt = 14; /* degrees */

  document.querySelectorAll(".nuda-tilt3d").forEach(function (card) {
    var inner = card.querySelector(".nuda-tilt3d__inner");
    if (!inner) return;

    card.addEventListener("mousemove", function (e) {
      var rect = card.getBoundingClientRect();
      var x = (e.clientX - rect.left) / rect.width;
      var y = (e.clientY - rect.top) / rect.height;
      inner.style.setProperty("--nuda-t3-rx", ((0.5 - y) * maxTilt) + "deg");
      inner.style.setProperty("--nuda-t3-ry", ((x - 0.5) * maxTilt) + "deg");
    });

    card.addEventListener("mouseleave", function () {
      inner.style.setProperty("--nuda-t3-rx", "0deg");
      inner.style.setProperty("--nuda-t3-ry", "0deg");
    });
  });
})();

How to use Tilt 3D

Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.

Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.

More cards & hover components

← Browse all NudaUI components