Flip Card
Pure-CSS 3D flip on hover — two faces swap with a spring effect and zero lines of JavaScript.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Cards has 43 effects, including 6 free. Explore the category →
3 usage examples



How it works
The effect relies on a CSS 3D projection context: perspective: 1000px is set on the .card-flip-container, and transform-style: preserve-3d is applied to .card-flip. This creates a three-dimensional space where child faces each exist on their own Z plane, without collapsing onto each other on screen.
The back face is pre-rotated 180° from the start with transform: rotateY(180deg), back-to-back with the front face. The backface-visibility: hidden property on both faces ensures that the face turned away from the viewer stays invisible — this produces the illusion of an opaque double-sided card rather than a transparent stack.
On hover, .card-flip-container:hover .card-flip applies transform: rotateY(180deg) to the assembly — the front face rotates and disappears while the back face, already pre-rotated, comes back to face the viewer. The cubic-bezier (.175, .885, .32, 1.275) transition produces a slight overshoot beyond 180° before settling, giving the characteristic spring feel.
The effect is 100% CSS with no JavaScript. No requestAnimationFrame, no event listeners, no external dependencies — the browser delegates interpolation to the GPU compositing engine. The 0.8 s duration strikes a good balance between smoothness and perceived responsiveness.
Accessibility
- prefers-reduced-motion: ABSENT from the code — the transition always runs, even when the OS prefers reduced motion. Minimal fix:
@media (prefers-reduced-motion: reduce) { .card-flip { transition: none; } }. - Hover-only trigger: the card does not respond to Tab or keyboard navigation as provided. Adding
.card-flip-container:focus-within .card-flip { transform: rotateY(180deg); }fixes this without modifying the HTML. - The
.card-flip-frontand.card-flip-backfaces carry neitherrolenoraria-labelin the base code — enrich them based on content (e.g.role="group" aria-label="Team card: front"). backface-visibility: hiddencorrectly hides the face turned away from the viewer — no ghost content is visible or read by assistive technology.- Text contrast depends on the added content: the provided background gradients (indigo and pink) are purely decorative; overlaid text colors must meet WCAG AA (ratio ≥ 4.5:1).
Browser compatibility
Relies on transform-style: preserve-3d and backface-visibility: hidden — natively supported in all modern browsers without vendor prefixes.
Without 3D CSS transform support, the card displays only the front face flat — no errors, content remains readable.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="card-flip-container">
<div class="card-flip">
<div class="card-flip-front">Front face</div>
<div class="card-flip-back">Back face</div>
</div>
</div>
The full HTML + CSS + JS of Flip Card, ready to paste — plus all 840 effects. Or $299 once, lifetime access.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| perspective (on .card-flip-container) | 1000px | Depth of the 3D context. 600 px = close-up dramatic view, 2000 px = near-flat rotation. Lower values exaggerate the depth effect. |
| transition-duration (on .card-flip) | 0.8s | Flip duration. 0.4 s = snappy and sharp, 1.2 s = cinematic and slow. |
| cubic-bezier (on .card-flip) | (.175,.885,.32,1.275) | Easing curve. The default produces a spring overshoot. Replace with ease-in-out for a smooth flip without bounce. |
| rotateY / rotateX (on :hover .card-flip and .card-flip-back) | rotateY(180deg) | Rotation axis. rotateX(180deg) gives a vertical flip (top to bottom). Change both occurrences (hover trigger and back pre-rotation) simultaneously. |
| --radius-xl (CSS variable on :root) | 1rem | Corner radius of both faces. 0 = sharp rectangle, 50% = circular card (portrait only). |
| width / height (on .card-flip-container) | 280px / 180px | Card dimensions. Any proportion works — portrait (200×280 px), square (240×240 px), or landscape (320×180 px). |
| background (on .card-flip-front) | linear-gradient(135deg,#6366f1,#8b5cf6) | Front face color or gradient. Replace with your brand palette or an image via background-image. |
| background (on .card-flip-back) | linear-gradient(135deg,#d946ef,#f43f5e) | Back face color or gradient. Clearly differentiate both faces so the flip reads immediately. |
FAQ
:hover only. Add to your CSS: .card-flip-container:focus-within .card-flip { transform: rotateY(180deg); }. Any focusable element (link or button) inside a face is enough to activate this selector — no changes to the effect HTML are needed..card-flip-container.is-flipped .card-flip { transform: rotateY(180deg); }. From your script, toggle it with container.classList.toggle('is-flipped'). The hover CSS can coexist or be removed. The transition plays both ways automatically.transform-style: preserve-3d and backface-visibility: hidden are natively supported without -webkit-. If your audience includes Safari 14 or earlier, add -webkit-transform-style: preserve-3d and -webkit-backface-visibility: hidden as duplicates.