What the term means now

'HTML5 game' entered common use as the replacement for 'Flash game' — a game that runs in a browser tab with no plugin, no installer and no separate runtime. The name has stuck even though it is now slightly inaccurate, since the technologies involved are mostly JavaScript APIs rather than HTML markup.

The practical definition is the useful one. An HTML5 game is a game you can start by following a link, on any device with a modern browser, with no step between the click and playing.

That definition has consequences for what kind of game makes sense. If the barrier to starting is zero, the barrier to leaving is also zero, which is why browser games converge on short sessions and immediate feedback. A game that takes twenty minutes to become interesting will not survive in a tab.

The five pieces

Everything on this site is built from five browser features and nothing else. No framework, no game engine, no asset pipeline, no third-party script.

Canvas, for drawing

The canvas element gives a bitmap surface and a two-dimensional drawing context — rectangles, arcs, paths, gradients, text. Everything visible in these games is drawn with those primitives at runtime.

That approach has three advantages over loading images. There is nothing to download, so a game starts the moment its scripts run. The artwork scales to any resolution without blurring. And it is unambiguously original, because it is generated from code rather than authored as files.

requestAnimationFrame, for the loop

This schedules a callback before the browser's next repaint, which synchronises the game loop to the display rather than to a timer. It also stops firing entirely when the tab is hidden, which is the correct behaviour and something a setInterval loop does not do.

These games stop their loop completely when the tab is hidden and show a pause screen, so nothing runs in the background and nothing tries to catch up in a burst when you return.

Web Audio, for sound

Every sound in these games is synthesised in the browser: an oscillator with a gain envelope, sometimes a short burst of filtered noise for the ball striking the table. No audio file is downloaded anywhere on the site.

Browsers block audio contexts until a user gesture, so the context is created lazily on the first interaction. Every call is wrapped so that a failure is silent rather than fatal — sound is optional, and a game that breaks because audio failed would be badly built.

Pointer events, for input

Pointer events unify mouse, touch and stylus behind one set of handlers, which removes an entire category of duplicated code and an entire category of bugs.

These games use them for dragging the paddle and for the on-screen buttons, alongside ordinary keyboard events. The input layer merges all of it into a single state object, so game code never needs to know which device produced an action.

localStorage, for records

Best scores, favourites, play history and preferences are kept in local storage. It is per-origin, per-browser, not sent with network requests, and it persists until cleared.

Every read and write is wrapped in a try/catch, because storage throws in private windows, when site data is blocked, and inside some embedded browsers. A game that crashes because a high score could not be saved is a worse game than one that quietly continues.

Why no framework

There are good game frameworks for the browser, and using one is a reasonable choice for a large project. For a site like this it would be the wrong one, for three reasons.

The first is weight. A framework has to support things these games do not need — a scene graph, a physics engine, an asset loader, a tween system — and that arrives as bytes the visitor downloads before anything happens. The engine here is about twenty-three small files loaded only on game pages.

The second is that the game is the physics. When your entire game is a ball, two paddles and a table, a general-purpose physics engine is not saving you work — it is adding a layer between you and the four parameters you actually want to tune.

The third is longevity. A static site built from browser APIs will still work in ten years. A site built on a framework works until the framework's next major version.

Editor’s note

Frameworks pay off when a project's complexity exceeds what you want to hold in your head. A ping pong game's complexity does not.

The performance constraints that shape the code

Browser games run alongside whatever else the visitor has open, on hardware ranging from a desktop to a four-year-old phone. Three techniques do most of the work of keeping them smooth.

  • A fixed simulation step — physics advance in constant 1/120-second slices regardless of frame rate, so difficulty never depends on the device
  • Object pooling — particles and entities are allocated once and reused, so a long session never triggers a garbage-collection pause mid-rally
  • Diffed DOM writes — the HUD only writes to an element when its value actually changed, so a rally of 200 does not touch the DOM 200 times for a number that did not move

The device pixel ratio is also capped at two when sizing the canvas. Beyond that the extra sharpness is imperceptible while the fill cost grows with the square, which is the kind of trade that decides whether a game is smooth on a mid-range phone.

Why these games load fast

Loading performance matters more for a browser game than for almost any other kind of site, because the visitor has not committed to anything yet.

There are no images in the games, no audio files, no fonts to download and no third-party scripts. A game page's total weight is its HTML, three small stylesheets and the engine's JavaScript modules, all of which are text and all of which compress well.

The scripts are deferred, so parsing never blocks rendering, and the page's layout reserves space for the canvas before the engine starts, so nothing shifts when the game appears. Those two details are most of what the Core Web Vitals measure on a page like this.

What HTML5 games cannot do

Being honest about limits is part of describing a technology properly.

A static HTML5 game has no server, which means no online multiplayer, no cloud saves, no global leaderboards and no cross-device sync. Those are not missing features on this site — they are impossibilities given how it is built, which is why nothing here claims them.

There is also no anti-cheat. Anything running in a browser can be inspected and modified by the person running it. For local personal bests that does not matter; for a global leaderboard it would matter enormously, which is a second reason not to pretend to have one.

And browser audio is subject to autoplay policies, storage is subject to being cleared, and the frame rate is subject to whatever else is running. Good browser games treat all three as normal conditions rather than as errors.

Building your own

If you want to write a ping pong game of your own, the order that works is roughly the order this engine was built in.

Start with a ball that has a height as well as a position, and gravity acting on it. Draw it as a circle above a shadow ellipse. That single step gives you an arc, a bounce and a readable sense of depth in a top-down view, and it is the foundation everything else sits on.

Then add a paddle with a crossing-based collision test rather than an overlap test, because tunnelling will otherwise bite you the first time you make the ball fast. Then add the shot solver, which turns aiming from a guess into arithmetic.

Only then add spin, scoring and an opponent. Each of those is small once the first three exist, and each is very difficult to get right before they do.

Key takeaways

  • An HTML5 game is one that starts from a link with no plugin, installer or runtime.
  • These games are built from five browser features: canvas, requestAnimationFrame, Web Audio, pointer events and localStorage.
  • Drawing with canvas primitives rather than images means nothing to download, no blurring and unambiguous originality.
  • A framework would add weight and a layer between the developer and the four physics parameters that matter.
  • Fixed steps, object pooling and diffed DOM writes are what keep a browser game smooth on modest hardware.
  • No server means no online play, no cloud saves and no global leaderboards — limits worth stating rather than hiding.

Frequently asked questions

Do HTML5 games need a plugin?

No. That is the defining characteristic. They run in the browser using built-in APIs, which is what replaced the plugin-based games of the previous era.

Why are there no image files in the games?

Everything is drawn with canvas primitives at runtime. That means nothing to download before play starts, no blurring at any resolution, and artwork that is generated from code rather than authored as files.

Why not use a game framework?

Weight, indirection and longevity. A framework supports features these games do not need, puts a layer between the developer and the physics values that matter, and ties the site's lifespan to the framework's.

Can HTML5 games have online multiplayer?

In general yes, with a server. On a static site like this one, no — there is nothing to run the matchmaking or relay the state, which is why nothing here claims online play.

Where are my high scores stored?

In your browser's local storage, per-origin and per-browser. It is not sent with network requests and there is no copy anywhere else, so clearing site data removes it permanently.

Why do the physics run at 120 steps per second?

So that difficulty is identical regardless of display refresh rate, and so that a fast shot cannot cross a paddle between two frames. Rendering still happens at whatever rate the display offers.

References and further reading

  1. MDN Web Docs — Canvas API
  2. MDN Web Docs — requestAnimationFrame
  3. MDN Web Docs — Web Audio API
  4. MDN Web Docs — Pointer events
  5. MDN Web Docs — Window.localStorage
  6. web.dev — Core Web Vitals