Perspective Tilt
A copy-paste 3d effects component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
3D EffectsHTMLCSSJavaScriptany framework
Hover to tilt
Copy into your project
HTML
<div class="nuda-tilt" style="perspective: 600px">
<div class="nuda-tilt__card">
<p>Hover to tilt in 3D</p>
</div>
</div>CSS
/* Perspective Tilt
Element that tilts toward the cursor in 3D on hover.
Customize: --tilt-max (degrees), --tilt-speed */
.nuda-tilt {
perspective: 600px;
display: inline-block;
}
.nuda-tilt__card {
--tilt-max: 15deg;
--tilt-speed: 0.15s;
width: 200px;
height: 140px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
font-size: 0.85rem;
transition: transform var(--tilt-speed) ease, box-shadow var(--tilt-speed) ease;
cursor: pointer;
will-change: transform;
}
.nuda-tilt__card:hover {
box-shadow: 0 10px 40px rgba(228, 255, 84, 0.08);
}
@media (prefers-reduced-motion: reduce) {
.nuda-tilt__card {
transition: none;
}
}JavaScript
/* Perspective Tilt — Tilts the card toward the cursor position. */
(function () {
var cards = document.querySelectorAll('.nuda-tilt__card');
if (!cards.length) return;
var reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reducedMotion) return;
var maxDeg = 15;
cards.forEach(function (card) {
card.addEventListener('mousemove', function (e) {
var rect = card.getBoundingClientRect();
var x = (e.clientX - rect.left) / rect.width; // 0 to 1
var y = (e.clientY - rect.top) / rect.height; // 0 to 1
var rotateX = (0.5 - y) * maxDeg * 2; // tilt up/down
var rotateY = (x - 0.5) * maxDeg * 2; // tilt left/right
card.style.transform =
'rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)';
});
card.addEventListener('mouseleave', function () {
card.style.transform = 'rotateX(0deg) rotateY(0deg)';
});
});
})();How to use Perspective Tilt
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.