We’ve seen the checkbox hack and how it can be used to build a complete state machine in CSS. Today, we’ll take that line of thought a step further and build a simple game of Whack-A-Mole, where the player needs to react quickly to win … all without a touch of JavaScript.
This might seem a little silly in a language that doesn’t have any notion of timers or intervals, but the secret is that CSS does — it’s just packaged in a little feature called CSS Animations.
Take a look at this double-click handler. Note that CSS doesn’t know what a click is, much less a double click:
How does it work? Here’s a recording of the important elements, recolored and slowed down:

The idea is that when you click on the button for the first time, it moves the double-click element in place under the cursor, but it also causes a masking element to start moving up to cover it.
- If the second click comes quickly enough after the first (as on the left side of the recording), it happens on the double-click (blue) element.
- Otherwise (as on the right side of the recording), it happens on the masking (yellow) element, which has the effect of a single-click element.
(For an in-depth explanation, take a look at my write-up on the pure-CSS double-click handler here.)
There are two ideas in play here:
- Animations can be used to manage states according to a set pattern. (I’m using the term “state” loosely.)
- By changing an element’s position, we can change whether or not an user is allowed to take an action.
That’s all we need!
Now, instead of having our target scroll into view, we could instead use animation-timing-function: step-end
to have it pop in and out, sort of like a mole in a hole:
I tried a few different options for moving the mole out of the way, and changing its absolute position — here left
— seems to work the best. Using a translation would be convenient, but unfortunately leaves Firefox thinking the cursor is on the wrong element because changing transform
in the Gecko layout engine doesn’t trigger a re-layout. (Normally, this would be a good thing for performance reasons, but not so much for our little demo!)
With a bit of styling, we can make it look more like a game element:
The “mole” here is basically a restyled CSS label that triggers the checkbox hack. So is the hole. When the mole’s animation takes it over the hole, clicking in the region triggers the mole’s radio input; when the mole is out of the way, clicking triggers the hole’s radio input.
The next step is to put a couple of holes next to each other and have the moles bounce around among them, each on a different negative animation-delay
. With a state machine reading off which of the moles have been hit and which of the holes have been collapsed, it turns into a neat little game.
I used short Python scripts to generate both the state machine selectors and the mole keyframes. It gets a bit unwieldy for hand-coding otherwise. This is mostly because CSS also has no concept of random numbers, which leaves us no choice but to hardcode the “random” mole behavior.
There we have it: a complete reaction-based game, entirely in HTML and CSS.
This is so nice I almost broke my screen.
Can you show us how to make a 2d platformer with just CSS?
I’m concerned with the accessibility of this demo, specifically the checkbox hack. When a screen reader announce the labels used in the trick, the screen reader simply inform to the user as an label. Combined with the fact that the real checkboxes has
display:none;
so that the checkboxes won’t be announced and the user cannot ‘activate’ an label, the user cannot check the boxes so as to play the game. As a result, the game is completely unusable to screen reader users.I hope that when you wrote this pose, you intention is to simply illustrate to all the people watching this page that it’s possible to construct a Whack-a-Mole game with pure CSS and not to recommend front-end developers that this is the best way to construct the game.