Flip Card Entry
A single-sided card that enters by pivoting from −90° (seen edge-on) to 0° in 0.6 s with a slight bounce, and leaves by continuing its rotation to +90°: always in the same direction, like a card dealt and then taken away. 800 px perspective, automatic entrance 600 ms after load, 1.3 KB of JavaScript, a 0.15 s fade under reduced motion.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Transitions has 52 effects, including 9 free. Explore the category →
3 usage examples



How it works
The .flip-entry-card (160 × 100 px, amber gradient #f59e0b → #d97706, 14 px corners) lives in a .flip-entry-wrapper frame carrying perspective: 800px. At rest, it is rotateY(-90deg) and opacity: 0: edge-on, with no thickness, so invisible, with backface-visibility: hidden. This is not a front/back card: there is only one face, which comes and goes.
The entrance (.flip-visible) brings it back to 0° in 0.6 s on cubic-bezier(.34, 1.56, .64, 1) — it slightly overshoots before settling — and the opacity rises in 0.3 s. The exit (.flip-exit) carries it on to +90° in 0.4 s, the opacity leaving 0.1 s later. So that a new entrance really starts again from −90° and not from +90°, the script sets a .flip-reset class (transition: none), removes the exit state, forces a calculation (offsetWidth) and then starts the entrance. Measured 120 ms after a second entrance click: −25° in Chromium 151, −26° in Firefox 153, −32° in WebKit 26.5 — the card arrives from the same side as the first time.
The script (1.3 KB) links each .flip-entry-btn button to its card through aria-controls (several cards per page) and brings the card in 600 ms after load, unless the user has already clicked. While hidden, the card carries pointer-events: none and inert. The first avoids a measured trap: an edge-on card (±90°) in perspective intercepts, in Chromium and WebKit, clicks aimed at the button placed under it; without this rule (and without inert, which backs it up), the button would stop responding after the first exit. The second removes the hidden content from the tab order and from screen readers.
Accessibility
- Hidden card truly absent: opacity 0 is not enough to hide content from screen readers; the script sets
inerton the card until it has entered (measured:trueon load,falseonce entered), and removes it on every entrance. - Button: a real
<button>witharia-controlsandaria-expanded(truewhen the card is present, measured). The automatic entrance on load updatesaria-expandedtoo. - Reduced motion: under
prefers-reduced-motion, no rotation: the card appears and disappears with a 0.15 s fade (measured in all three engines: 0° angle at all times). - Contrast: 13.6 px bold white text on the
#f59e0b→#d97706amber, i.e. 2.2 to 3.2:1, not enough. Write in dark brown (#422006, as in scene 1) or darken the card (#b45309→#92400e: 5.0 and 7.1:1 with white).
Browser compatibility
CSS (perspective, rotateY, backface-visibility, transitions) + 1.3 KB of JavaScript, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26.5: same entrance from −90°, same exit toward +90°, same return from the same side, button still clickable after an exit. 3D transforms have existed everywhere for a long time; the inert attribute since Chrome 102, Firefox 112 and Safari 15.5.
Before inert, the rotation is the same but the hidden card stays readable by a screen reader. Without JavaScript, the card stays hidden (edge-on, opacity 0): remove rotateY(-90deg) and opacity: 0 from the base rule if its content must be read without script.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="flip-entry-stage">
<div class="flip-entry-wrapper">
<div class="flip-entry-card" id="flipEntryCard">…</div>
</div>
<button class="flip-entry-btn" type="button" aria-controls="flipEntryCard" aria-expanded="false">…</button>
</div>
The full HTML + CSS + JS of Flip Card Entry, 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 |
|---|---|---|
Entrance and exit angle (CSS — base rotateY(-90deg), rotateY(90deg) in .flip-exit) |
−90° → 0° → +90° | Swap both signs for a card arriving from the right. rotateX instead of rotateY makes it tip from the top, like a shutter. |
Perspective (CSS — perspective: 800px on .flip-entry-wrapper) |
800 px | 400 px emphasizes depth, 1,500 px flattens it. Keep it on the frame, not on the card. |
| Durations (CSS — 0.6 s entrance, 0.4 s exit) | entrance slower than exit | A shorter exit hands control back faster; keep at least 0.3 s so the rotation reads. |
Entrance on load (JS — setTimeout(…, 600)) |
the card enters 600 ms after load | Delete the line so the card only enters on click, or call the same trigger when your content arrives (a search result, a notification). |
Colors (CSS — background and color of .flip-entry-card) |
amber #f59e0b → #d97706, white text |
See the contrast note: dark text on the amber, or a darker background to keep white. |
FAQ
inert: card at +90°, a click in the center of the button below it hits the card, and the button no longer responds. pointer-events: none on every state except .flip-visible settles it; do not remove it if you move the card close to other elements.