webdevpuneet.com

Coin Flip — CSS 3D Coin Flip Animation (JS)

Coin Flip · Games · Plain HTML, CSS & JS · Live preview

CategoryGames

For supporters

Source Code

Want the source code?

Play the game for free. Become a WebDevPuneet supporter to unlock the complete HTML, CSS and JavaScript source code, the exports (HTML, React, Vue, Angular, Tailwind) and Fork.

Play freeSource code: Patreon

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Two-sided 3D coin
Two faces in a preserve-3d scene with perspective for a real tumble.
backface-visibility flip
Hidden backfaces show exactly one side at a time as the coin rotates.
Parity-based landing
Heads at even, tails at odd 180° multiples, so the coin rests on the reported side.
Honest randomness
Math.random() picks the result before the spin, so the visual always matches.
Forward-spinning
An accumulating turn count keeps the coin rotating the same way between flips.
Running tally
A heads/tails counter tracks the session and shows the 50/50 split holding.
Flip guard
The button disables during the tumble so flips can't overlap.
No images, no library
Pure HTML/CSS/JS — themeable and dependency-free.

About this UI Snippet

Coin Flip — A 3D CSS Coin That Tumbles to Heads or Tails

Screenshot of the Coin Flip snippet rendered live

Flipping a coin is the simplest possible randomiser, and a 3D coin that actually tumbles makes it satisfying. This snippet builds a two-sided coin that spins and lands on heads or tails, with a running tally, in pure HTML, CSS, and a few lines of vanilla JavaScript — no images, no library.

Two faces with backface-visibility

The coin is two circular faces stacked on the same spot inside a preserve-3d scene. The tails face is pre-rotated 180° so it points the opposite way, and both faces use backface-visibility: hidden — the key property that makes a flippable two-sided element work, because it hides whichever face is currently turned away from the viewer. Without it you'd see a mirror-image bleed-through; with it, exactly one side shows at a time as the coin rotates. The scene's perspective gives the spin real depth.

Landing on the right side via rotation parity

Heads shows when the coin's rotateY is at an even multiple of 180° (0°, 360°, …) and tails at an odd multiple (180°, 540°, …). A flip picks the result first with Math.random(), then computes a final angle that has the correct parity for that result plus several extra full spins so the coin visibly tumbles before settling. Because the landing angle is derived from the chosen outcome, the coin always rests on the side it reported — the randomness is honest, decided before the animation, never faked afterward. The Math.ceil((turns * 180) / 360) * 360 step is the part that keeps this correct flip after flip: it rounds the accumulated half-turns up to the next full 360°, discarding any leftover odd half-turn from the previous landing, before the new parity offset (0 or 180) is added back on top — without it, the parity from one flip could bleed into the next and land the coin on the wrong face.

Always spinning forward

An accumulating turns counter ensures each flip adds rotation on top of the last, so the coin keeps spinning in the same direction rather than snapping back to zero between flips. This continuity is a small detail that makes repeated flips feel like one continuous physical object rather than a resetting widget.

A running tally

Each result increments a heads/tails count, shown beneath the coin. Over many flips this both adds a sense of a session and quietly demonstrates that the 50/50 split holds — a nice touch for anything that uses the coin to make repeated decisions. The button disables during the ~1.1s tumble so flips can't overlap and desync the tally from the resting face.

Drop-in and adaptable

The coin is self-contained and easy to theme — swap the H/T glyphs for icons or images, change the metals, or resize it. Use it as a decision-maker, a game mechanic, or a playful "let fate decide" control, and as a clear reference for two-sided CSS 3D flips with backface-visibility.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA 3D coin renders on a dark stage with a Flip button.
  2. 2
    Flip itClick Flip (or the coin) and it tumbles for about a second, landing on heads or tails.
  3. 3
    Read the resultThe text shows the outcome, which always matches the resting face.
  4. 4
    Watch the tallyEach flip updates the running heads/tails count beneath the coin.
  5. 5
    Restyle itSwap the H/T glyphs for icons, change the coin colours, or resize it.
  6. 6
    Hook into your appRead the chosen side in flip() to drive a decision, game, or picker.

Real-world uses

Common Use Cases

Decision making
Settle a yes or no question, pairing with a dice roller or spin wheel for other kinds of random choice.
Game mechanics
Drive a coin toss in a game interface, with parity-based landing putting heads at even and tails at odd multiples of 180 degrees.
Sports and matchups
Pick who goes first with a visible, fair flip, since Math.random() chooses the result before the spin so the animation always matches.
Gamified prompts
Add chance to onboarding or quizzes as a gamified prompt, with a confetti button rewarding a lucky result.
Party apps and 3D flip learning
Let fate decide at icebreakers, and study backface-visibility, comparing with a 3D flip card for content cards.
Related: Cursor Spotlight Reveal
See the Cursor Spotlight Reveal for a related animations pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Heads corresponds to an even multiple of 180° of rotateY and tails to an odd one. The flip picks the result with Math.random() first, then computes a final angle with the matching parity plus several full spins for flourish. Because the resting angle is derived from the chosen outcome, the coin always settles on the side it announced — the result is decided before the animation, not after.

It hides the side of each face that's turned away from the viewer. The coin is two faces on the same spot, with tails pre-rotated 180°. As the coin spins, backface-visibility:hidden ensures only the face pointing toward you is visible, so you never see the reverse bleeding through. It's the essential property for any two-sided 3D flip element.

A turns counter accumulates across flips, so each new flip's target angle is larger than the last. That keeps the rotation always increasing — the coin spins forward continuously instead of snapping back toward zero between flips, which would look like a glitch. The parity of the final angle still encodes heads or tails correctly.

Yes — Math.random() < 0.5 gives each side an equal chance on every independent flip. The running tally beneath the coin lets you watch the split converge toward 50/50 over many flips. There's no weighting or memory between flips, so it behaves like a fair coin.

In React, hold the rotation, result, and counts in state and set the coin's transform in the click handler with a timeout to settle; in Vue, bind :style with refs; in Angular, bind [style.transform] with component properties. The parity math and randomness are framework-agnostic — only the state and the transform binding move into the framework.