Blog
3D CSS Flip Card: Flip an Image to Reveal Text
Learn how to build a responsive CSS 3D flip card that reveals text on the back of an image. This example uses CSS perspective and transforms, includes keyboard and touch-friendly controls, and respects reduced-motion preferences—without JavaScript.
What this demo includes
This responsive CSS-only example includes two image cards, a 3D Y-axis flip, touch-friendly checkbox controls, keyboard focus support, and a reduced-motion fallback. Use the demo below, then download the source files to customize the images, colors, card size, and back-face content.
Live CSS Flip Card Demo
Hover over a card with a mouse, focus it with a keyboard, or tap it on a touch screen to reveal the back. Try both cards.
Plan the view
Place an image on the front and a short description on the reverse.
Keep it responsive
The grid adapts to available width and stays aligned as the layout changes.
How the 3D flip effect works
A 3D flip card has two faces: a front face for the image and a back face for the revealed text. The outer card establishes perspective, which gives depth to the rotation. The inner element preserves its 3D children, while each face uses backface-visibility: hidden so the reverse side does not show through. Rotating the inner element by 180 degrees around the Y axis swaps the faces.
Build the markup with one article, a checkbox, an inner wrapper, and two faces. The checkbox makes the card operable on touch screens where hover is unavailable. Give every checkbox a unique id and connect its visible label with a matching for attribute. Add a meaningful alt description to the image; if the image is decorative, use an empty alt attribute instead.
In the stylesheet, make the card position: relative and give it a perspective value such as 1000px. Set transform-style: preserve-3d and a transition on the inner wrapper. Place both faces in the same area, hide their back faces, and rotate the back face 180 degrees before the interaction. On hover, keyboard focus, or a checked checkbox, rotate the inner wrapper 180 degrees.
Responsive sizing: use a grid with repeat(auto-fit, minmax(min(100%, 15rem), 1fr)) so cards form columns when space allows and stack on narrow screens. Keep a consistent card height with min-height, use object-fit: cover for images, and test at small widths. Avoid fixed widths that cause horizontal scrolling.
Accessibility and motion: the checkbox provides a keyboard and touch alternative to hover. Keep a visible focus indicator on the control or card. Respect the prefers-reduced-motion media query by removing or shortening the transition. Use readable contrast on both faces and make the reverse text concise.
Common fixes: if the back is visible through the front, apply backface-visibility to both faces. If the rotation looks flat, confirm perspective is on the outer wrapper and transform-style is on the rotating inner wrapper. If a tap does nothing, check that the label for value matches the checkbox id. If cards collide on mobile, increase the grid minimum width or reduce the card padding.
To customize the example, replace the sample image URLs with optimized images you own, update alt text to describe each image, and edit the front title and reverse copy. Keep image dimensions reserved to reduce layout shift. The download contains the standalone files; extract them and open index.html in a browser, or serve the folder with a local development server. Do not upload a ZIP into a page as executable content.
For production, verify the effect in current desktop and mobile browsers, check keyboard-only navigation, test reduced-motion settings, and confirm the page remains usable when CSS animations are disabled. A flip card works best for short supporting details; do not hide essential instructions or links on the back because visitors may not discover the interaction.
<article class="flip-card">
<input type="checkbox" id="flip-one" aria-label="Show card details">
<div class="flip-card__inner">
<div class="flip-card__face flip-card__front">Image and title</div>
<div class="flip-card__face flip-card__back">Details revealed on flip</div>
</div>
</article>
.flip-card {
position: relative;
min-height: 24rem;
perspective: 1000px;
}
.flip-card__inner {
position: relative;
min-height: inherit;
transform-style: preserve-3d;
transition: transform 650ms ease;
}
.flip-card:hover .flip-card__inner,
.flip-card:focus-within .flip-card__inner,
.flip-card__toggle:checked + .flip-card__inner {
transform: rotateY(180deg);
}
.flip-card__face {
position: absolute;
inset: 0;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
.flip-card__back {
transform: rotateY(180deg);
}
@media (prefers-reduced-motion: reduce) {
.flip-card__inner { transition-duration: 0.01ms; }
}