The problem
You want to create engaging 3D card effects that follow mouse movement for a modern interactive experience.
The solution
.card-3d-container {
perspective: 1000px;
width: 300px;
height: 400px;
}
.card-3d {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s ease;
border-radius: 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}
.card-3d:hover {
transform: rotateY(10deg) rotateX(10deg);
}
/* Dynamic rotation with CSS variables */
.card-3d-dynamic {
transform:
rotateY(calc(var(--mouse-x, 0) * 20deg))
rotateX(calc(var(--mouse-y, 0) * -20deg));
}
/* Inner shine effect */
.card-3d::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.2) 0%,
rgba(255, 255, 255, 0) 50%
);
border-radius: 16px;
opacity: 0;
transition: opacity 0.3s;
}
.card-3d:hover::before {
opacity: 1;
}See it live
Put it to work
<div class="card-3d-container">
<div class="card-3d">
<div style="padding: 24px; color: white;">
<h2>3D Card</h2>
<p>Hover to see the 3D effect</p>
</div>
</div>
</div>
<script>
// Dynamic mouse-based rotation
const card = document.querySelector('.card-3d-dynamic');
card.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
card.style.setProperty('--mouse-x', x);
card.style.setProperty('--mouse-y', y);
});
</script>Worth knowing
Use perspective on parent element for 3D effect. preserve-3d maintains 3D space for child elements.