3D Card Flip Hover โ Pure CSS Animation with Source Code
The 3D Card Flip reveals a hidden back face when the user hovers over it โ creating a satisfying 3D perspective rotation entirely with CSS. No JavaScript is needed. It uses the critical three-property combination of perspective, transform-style: preserve-3d, and backface-visibility: hidden to create a convincing three-dimensional flip effect.
How It Works
The cardโs parent .scene sets the perspective depth (900px). The .card element has transform-style: preserve-3d to allow children to exist in 3D space. On :hover, the card rotates 180 degrees on the Y axis. The front face is a normal element; the back face has transform: rotateY(180deg) pre-applied so it lines up correctly after the flip. Both faces have backface-visibility: hidden so the back of each plate is invisible.
Use Cases
- Product cards (front = image, back = details / buy button)
- Team member cards (front = photo, back = bio + social links)
- Flashcard study applications
- Pricing cards with feature comparisons
- Portfolio thumbnail grids
How to Customize
- Change flip direction: Replace
rotateY(180deg)withrotateX(180deg)for a vertical flip - Change flip speed: Modify
0.85sin the.cardtransitionproperty - Trigger on click instead of hover: Remove the
.scene:hover .cardrule and add a JSclassList.toggleon click
Frequently Asked Questions
Why does the back card text appear reversed without backface-visibility?
Without backface-visibility: hidden, the browser renders both faces of the card simultaneously, causing you to see the back face content through the front during the flip. The property hides the โwrongโ face at each rotation stage.
How do I make this work on mobile tap?
Since :hover doesnโt persist on mobile, add a click listener in JavaScript: document.querySelector('.scene').addEventListener('click', () => card.classList.toggle('flipped')) and add .card.flipped { transform: rotateY(180deg); } in CSS.
Can I add images to the front and back faces?
Yes! Add an <img> element inside .card-front or .card-back and set it to width: 100%; height: 100%; object-fit: cover;. The border-radius on .card-face will automatically clip the image.