The occlusion problem nobody tests for
The defining difference between mouse and touch is that your hand is on the screen. A mouse cursor occupies a few pixels somewhere else; a thumb occupies a couple of square centimetres of the display, and whatever is underneath it is invisible while you play.
This is trivially obvious and routinely missed, because it does not show up when you test touch with a mouse in a browser's device emulator. The emulator has no thumb. A control that works perfectly in emulation can be unusable on a real phone because the hand operating it covers the thing you need to see.
Our response is a rule rather than a case-by-case judgement: controls sit in the lower corners, and nothing gameplay-critical is drawn in the lower third of the canvas. Where a game needs full-width movement at the bottom - the cart in Candy Rush, the basket in Candy Catcher - the character follows your finger anywhere on the lower half instead of using buttons, so your hand stays below the action.
Test with a thumb, on a real device, in the hand you would actually hold it in. It is the single highest-value mobile test available and it takes thirty seconds.
Choosing a control scheme per game
There is no universal touch layout. The right scheme depends on what the game asks for, and using one layout everywhere produces a game that is awkward in most of them. We implement twelve schemes and pick per game.
| Game needs | Scheme | Why |
|---|---|---|
| Horizontal position only | Finger-follow on the lower half | Precise, no buttons, hand stays clear of the play area |
| Vertical position only | Hold-anywhere to steer | Same reasoning, rotated |
| Walk and jump | Left and right pads plus a wide JUMP button | Two independent inputs need two targets |
| Lane changes | Swipes, with pads as a fallback | Discrete inputs suit discrete gestures |
| A single action | Tap anywhere | The largest possible target is the whole screen |
| Continuous thrust | Touch and hold anywhere | Hold duration is the input, so position is irrelevant |
| Free 2D movement | Drag to steer | A virtual stick is worse than direct following for this |
| Grid direction | Swipes | Cell-based movement makes swipes reliable, unlike continuous movement |
The general principle: prefer the whole screen as a target where the game allows it. A tap-anywhere game is the most accessible design available on a phone, and three of our thirty games are built that way.
Advertising keeps Candy Arcade free. Ads never cover gameplay or controls.
Canvas scaling and device pixel ratio
A canvas has two sizes: its CSS layout size and its backing buffer size. Getting the relationship wrong produces either a blurry game or a slow one, and both are common.
The sizing pattern
Read the element's CSS size from getBoundingClientRect. Multiply by devicePixelRatio, capped - we cap at 2 - and set canvas.width and canvas.height to that. Then apply a context transform of the same scale so all your drawing code can work in CSS pixels.
The cap matters. A 3x display genuinely exists, and rendering nine times the pixels of a 1x display costs far more than it shows on a screen held at arm's length.
The second half of the problem is your coordinate system. Writing a game against actual pixel dimensions means every position needs per-device adjustment. Our solution is a virtual system: the play area is always 600 units tall and the width is 600 times the aspect ratio. One implementation is then correct in portrait and landscape with no conditional code, and a game written once is correct on every device.
Aspect ratio, not resolution
Phones in portrait are tall and narrow; desktops are wide. That is a much bigger design problem than resolution, and it cannot be solved by scaling.
A game designed for a 16:10 canvas and displayed at 4:5 either crops - hiding gameplay - or letterboxes, wasting most of the screen. Neither is acceptable, so games need to adapt to the shape rather than fit inside it.
- Use relative positioning throughout. A lane at 'width / 4' is correct at any aspect; a lane at '240' is not.
- Let the play area change shape. Our CSS gives the stage 16:10 on desktop, 3:2 on tablets and 4:5 on phones, and the games adapt.
- Spawn relative to the visible area, so a wide screen does not produce empty space and a narrow one does not produce impossible density.
- Handle orientation changes by recomputing, not by asking the player to rotate. A game that demands landscape is a game half the audience will not play.
Touch events that behave
Touch handling on the web has a set of specific traps, and every one of them produces a game that feels broken rather than difficult.
- Set 'touch-action: none' on the stage, or the browser will scroll the page while the player is trying to steer.
- Call preventDefault on touch events inside the stage, for the same reason.
- Use Pointer Events where available; they unify mouse, touch and pen behind one code path and remove an entire class of duplicate-handler bugs.
- Set '-webkit-tap-highlight-color: transparent', or iOS draws a grey flash over every tap.
- Disable text selection on the stage, or a long press starts selecting the page.
- Handle pointercancel as well as pointerup. A gesture interrupted by the system otherwise leaves a control stuck down.
- Suppress the context menu on the stage, or a long press opens it mid-game.
That list is not design philosophy; it is the difference between a canvas game that feels native on a phone and one that fights the browser. All seven are three lines of code each.
Touch target size
Small targets are the most common mobile failure and the easiest to fix. Fingers are imprecise, the contact area is larger than the visual point of contact, and there is no hover state to confirm what you are about to press.
Our on-screen controls are 64 pixels across, and every interactive element on the site is at least 44 pixels on a coarse pointer, applied through a 'pointer: coarse' media query so desktop layouts stay compact. Buttons are also spaced apart: two adjacent 64-pixel buttons with no gap still produce mispresses at the boundary.
Semi-transparent controls are worth mentioning as well. Ours sit at about twenty percent opacity, rising on press. They remain clearly visible while obscuring as little of the canvas as possible, which matters because on a phone every pixel of play area is contested.
Performance on real phones
A mid-range phone from a few years ago is the device that actually matters, and it is several times slower than a development machine. The constraints that follow are not exotic.
- Cap the device pixel ratio. This is the single largest performance lever available.
- Pool objects. Allocating hundreds of short-lived objects per second produces visible garbage-collection stutter on phones long before it does on desktop.
- Cap particles. An unbounded burst that drops frames looks far worse than a smaller burst that does not. Ours cap at 220.
- Never allocate in the draw loop. Build gradients and paths once where possible.
- Draw procedurally rather than loading images. Our whole site has no gameplay bitmaps, which removes decode time and memory pressure entirely.
- Pause when the tab is hidden. A game running in a background tab drains battery for nothing, and browsers throttle it unpredictably anyway.
The procedural point deserves emphasis because it is unusual and it pays off repeatedly. Drawing the artwork from code means no image decoding, no texture memory, no loading state, no resolution variants and no blurriness at any scale. The cost is that complex scenes take more CPU per frame, which is a trade worth making at the visual complexity an arcade game needs.
The mobile testing checklist
- Play it with a thumb on a real device, held the way you would actually hold it.
- Check that nothing important sits under your hand.
- Try it in portrait and landscape and rotate mid-game.
- Check every control is at least 44 pixels and spaced from its neighbours.
- Confirm the page never scrolls while you are playing.
- Confirm no grey tap flash and no text selection on long press.
- Watch the frame rate during the densest moment, not the calm opening.
- Switch away mid-game and come back; the game should be paused and intact.
- Test with a case on. It changes where your thumb naturally sits more than you would expect.
Common mistakes
- Testing touch with a mouse in a device emulatorThe emulator has no thumb, so it cannot reveal occlusion - the single biggest difference between touch and mouse.
- Using one control layout for every gameDifferent games need different schemes. A virtual stick on a one-button game is worse than tap-anywhere in every respect.
- Ignoring device pixel ratioIgnore it and the game is blurry; apply it uncapped on a 3x display and it is slow. Cap at 2.
- Designing for resolution instead of aspect ratioScaling solves resolution. It does not solve a 4:5 screen displaying a 16:10 design.
- Small or adjacent touch targetsFingers are imprecise and there is no hover to confirm. Minimum 44 pixels, with gaps.
- Requiring landscapeA game that demands rotation is a game a significant share of visitors will not play at all.
Practical tips
- Prefer tap-anywhere or finger-follow over virtual buttons whenever the game allows it.
- Keep gameplay out of the lower third on phones, where a hand will be.
- Work in a virtual coordinate system rather than pixels, so one implementation fits every device.
- Use Pointer Events, and handle pointercancel as well as pointerup.
- Cap device pixel ratio at 2 - it is the biggest single performance win available.
- Test during the densest moment of your game, not the opening.
Key takeaways
- Occlusion is the defining difference between touch and mouse, and emulators cannot show it.
- Pick a control scheme per game; there is no universal touch layout.
- Cap device pixel ratio at 2 and use a context transform so drawing code stays in CSS pixels.
- Aspect ratio is a harder problem than resolution and cannot be solved by scaling.
- Touch targets need to be at least 44 pixels and spaced apart.
- Object pooling and particle caps matter far more on phones than on desktop.
Frequently Asked Questions
What is the most common mistake in mobile game design?
Putting something important where the player's hand will be. It is invisible in a desktop device emulator and immediately obvious on a real phone.
Why cap device pixel ratio at 2?
A 3x display means rendering nine times the pixels of a 1x display, which costs far more performance than it gains in visible sharpness on a handheld screen.
Should games require landscape orientation?
No. A game that demands rotation loses a significant share of players. Design for both and recompute on orientation change.
How large should touch controls be?
At least 44 pixels, and larger where possible. Ours are 64 pixels and spaced apart, because adjacent buttons produce mispresses at the boundary.
Why does Candy Arcade draw its art rather than loading images?
No decode time, no texture memory, no loading state, no resolution variants and no blurriness at any scale. The cost is more CPU per frame, which is an easy trade at arcade-game complexity.
Read next
- accessibility in browser arcade games — the accessibility companion
- how browser arcade games save high scores — more on the web platform
- how to master one-tap candy games — the most mobile-friendly format
- One-Tap Candy Collector — tap-anywhere in practice
- Candy Rush — finger-follow control
- reflex and candy arcade games — the one-input games
References
- Pointer events - MDN Web Docs — The unified input model used across every game on this site.
- touch-action - MDN Web Docs — How to stop the browser scrolling while a player is steering.
Every external source listed here has been read. We do not cite sources we have not checked, and we do not invent references. See our fact-checking policy.