Single HTML file games

A game in one HTML file needs no install and no build. The constraint is that every asset has to live inside the file, and some things simply will not.

Single HTML file games are playable pages with no install step: markup, styles, script and art in one document. Anything the page has to fetch from beside it is what breaks the format.

A single file game running in a browser, with the network panel showing no additional requests.
A single file game running in a browser, with the network panel showing no additional requests.

The appeal is portability. The cost is that a few categories of game cannot be built this way at all, and it is worth knowing which before you start.

The rule that defines single HTML file games

One file, zero neighbours. That means:

  • Styles in a <style> block, not in an external stylesheet.
  • Script in a <script> block, not in a separate .js file.
  • Art drawn on canvas, or embedded as base64 data URIs.
  • Level data written as a JavaScript object, not fetched as JSON.

The last one catches people out. A page opened from disk is not allowed to read files next to it, so fetch('levels.json') fails even though the file is right there. That restriction is the file protocol doing its job.

What fits and what does not

Game feature Fits in one file Why
Canvas arcade loop Yes Drawing commands need no assets
Puzzle or word game Yes Word lists inline as an array
Turn based board game Yes State lives in memory
High score on this device Yes Local storage, per browser
Small sound effects Yes Short clips embed as data URIs
Background music Awkward File size, or hotlink to a full address
Shared leaderboard No Needs a server to hold scores
Multiplayer No Needs a connection between players
Accounts and cloud saves No Needs a backend

If your idea is in the bottom three rows, a single file is the wrong container and no amount of embedding fixes it.

Saving progress within the limits

Local storage is the only persistence available, and it has a specific shape worth understanding before you rely on it.

It is keyed to one browser at one address. A player who switches from a laptop to a phone starts over. A player who clears site data starts over. Nobody else can see the value.

That is fine for a personal best or a level unlock. It is not a leaderboard, and presenting it as one produces complaints.

Session storage is the shorter option, cleared when the tab closes, which suits an in progress run you do not want persisted.

Keeping the file small

A single file game's size shown in a file listing, with art drawn on canvas rather than embedded.
A single file game's size shown in a file listing, with art drawn on canvas rather than embedded.

The whole file downloads before anything appears, so weight is felt as a blank screen.

Draw instead of embed. Rectangles, circles and paths cost bytes in the dozens. A sprite sheet costs bytes in the hundreds of thousands.

Prefer SVG to raster. SVG inside the HTML is text, compresses well, and scales to any screen without a second copy.

Generate sound rather than embedding it. Tones from the audio API cost nothing in file size and suit arcade effects.

Skip web fonts. A web font that fails leaves the game in a default face anyway, and the system stack is instant.

Sharing so people actually play

  1. Open it somewhere neutral. The HTML file opener has never seen your folder, so a forgotten asset path fails there immediately.
  2. Paste the complete HTML into a document. It renders as a page of its own and the scripts run.
  3. Create the share link. Share, then Share link, then Create link. It is unlisted unless you tick Public on the web.
  4. Send the link. One tap on a phone, no download, no install.
The share panel with a link created for a single file game, still unlisted.
The share panel with a link created for a single file game, still unlisted.

Sending the file itself is the route that fails. Mail gateways strip HTML attachments, and a phone puts the file in storage with nothing offering to run it.

Most people who open your link are on a phone, so keyboard only controls exclude them.

Add touch handlers next to the key handlers and map screen regions to the same actions. Include the viewport meta tag so the canvas is not rendered at desktop scale and shrunk.

Size the canvas in CSS and scale the drawing context, rather than fixing pixel dimensions that happen to suit your monitor.

Why one file is worth the constraint

Everything in the page is visible in one place, which makes a game easy to hand to someone, easy to fork, and easy to archive. There is no build to reproduce in two years.

It also means the game can be revised in place. Paste it into a document once, and correcting a typo in the instructions is a click on the text rather than a re-upload, with the address unchanged.

For the code side of this, see HTML game code. For the general packaging technique, see self-contained HTML files.

Testing, distributing and archiving

Three checks, in order, catch nearly everything.

  1. Open the file from a folder containing nothing else. Any asset it was silently relying on now fails visibly.
  2. Open the console and play a full round. Errors thrown in a rare branch do not appear on the title screen.
  3. Open it on a phone. Touch input and canvas scaling are where single file games most often disappoint.

A single file game is unusually easy to keep. There is no repository to clone and no build to reproduce.

Put the version and date in the title, so a file found in two years identifies itself. Keep each release as its own document rather than overwriting, if the versions matter to you.

For the playable copy people use, keep one address and revise the page behind it. Players bookmark the link, and a bookmark that keeps working is worth more than a versioned filename.

If you want others to build on it, the source is already in the page. Anyone can view source, copy the file and change it, which is the oldest distribution model the web has.

Questions people ask

What counts as a single HTML file game?

One .html document containing the markup, styles, script and any art, with no references to files beside it. Double clicking it starts the game, and sending the file or its address sends the whole game.

What cannot go in a single HTML file?

Anything that needs a server. Multiplayer, a shared leaderboard, accounts, or saving progress across devices. Large audio and video are also impractical, because embedding them inflates the file past what loads comfortably.

How big can the file get?

There is no fixed limit, but embedded art as base64 is roughly a third larger than the original bytes, and the whole file must download before anything appears. Keep art geometric or small and the file stays comfortable.

How do I let people play it without downloading anything?

Put the page at an address. Paste the HTML into a document that renders it, create a share link and send that. Scripts run in the rendered page, so the game is playable in one click.

Keep reading