Technical Specs

Snake Game

Full technical and architectural documentation of the Snake Game arcade project.

1. Project Overview

Snake Game is a browser-based recreation of the classic arcade snake game, built entirely with vanilla HTML, CSS, and JavaScript. Players navigate a growing snake around a dynamic grid, consuming food to increase their score while avoiding walls and their own tail.

The project focuses on proving that a smooth, visually polished arcade experience can be built without a canvas or any game engine — using pure DOM manipulation and CSS Grid as the rendering layer.

Purpose

Snake Game aims to deliver a lightweight, dependency-free arcade experience with a modern glassmorphism aesthetic, demonstrating clean vanilla-JS game-loop architecture without relying on Canvas, WebGL, or any external libraries.

Core Functionalities

Target Users

Value Proposition

Snake Game delivers a performant, responsive arcade experience with zero dependencies — no game engine, no canvas, no external libraries — by rendering entirely through cached DOM nodes and CSS class toggling, styled with a premium glassmorphism UI layer.

2. Tech Stack

Markup

HTML5 — dynamically generated DOM-element grid (no <canvas>)

Rendering Method

DOM manipulation — CSS class toggling (.fill, .food) on cached grid-cell divs

Styling

Vanilla CSS — CSS Custom Properties, Flexbox (page layout) + CSS Grid (game board)

Scripting

Vanilla JavaScript (ES6+) — procedural, single-file, no modules/classes

External Assets

None — no CDNs, game engines, or third-party libraries

Data Persistence

Browser localStorage (highScore only)

Hosting

Vercel — static deployment, no build step

3. How It's Made (Architecture & Workflows)

Fixed-Tick Game Loop

Driven by setInterval() at a constant 120ms tick rate (SPEED = 120) — difficulty does not ramp up over time. The loop is started via startLoop(), torn down via clearInterval() on game over, and cleanly restarted by clearing any existing interval before spinning up a new one.

DOM-as-Canvas Rendering

The board is a hash map (blocs) of stringified coordinates ("row-col") pointing directly to cached DOM nodes — avoiding repeated querySelector calls. Every tick performs a full visual reset (clearBoardVisuals() strips .fill/.food from all cells) before re-applying classes based on the current snake array and food position — a full redraw pattern, but cheap since it's just className toggling rather than layout-triggering changes.

Tail-Aware Self-Collision (Clever Logic)

Rather than naively checking the new head against the entire snake body, the collision check excludes the last tail segment whenever the snake isn't eating that tick — correctly modeling the fact that the tail vacates its cell as the snake moves, letting the head safely follow directly behind its own tail without a false game-over.

Food Spawning Safety Net

New food positions are generated via Math.random() inside a while loop that rejects any coordinate overlapping the snake's body — capped at 1000 attempts as a fail-safe against infinite loops if the board is ever nearly full.

Input & Timing Model

A single direction variable stores heading, with a same-tick 180°-reversal guard (e.g. blocking left while moving right). No input buffer/queue exists, so a very rapid double-keypress within one 120ms tick window could theoretically slip past the reversal guard. The gameplay timer deliberately doesn't start on menu-dismiss — it waits for the player's first valid directional keypress via startTimer().

4. Data Model

Hover over each structure to reveal its shape (no database — this is the in-memory game state).

Snake Body

Hover to view

Array of {x, y} coordinate objects, index 0 is the head; grows via unshift, shrinks via pop.

[
  { x: 1, y: 3 },
  { x: 1, y: 4 }
]

Food Position

Hover to view

Single {x, y} coordinate object, regenerated on every successful eat.

{ x: 5, y: 12 }

Grid Map

Hover to view

Object mapping stringified "row-col" keys to their corresponding cached DOM div nodes.

{
  "0-0": <div class="block">,
  "0-1": <div class="block">,
  ...
}

5. File Structure

Script is loaded at the end of <body> for standard blocking execution after DOM parsing.

6. UI/UX Details

Layout is full-viewport Flexbox centering, with the game board filling available flex space while CSS Grid governs internal cell alignment — grid dimensions are computed dynamically from container clientWidth/clientHeight against a fixed 40x40px cell size.

Start and Game Over screens are rendered as fixed, full-screen modal overlays using backdrop-filter: blur(6px) over gradient backgrounds for a glassmorphism effect. The Game Over modal carries a distinct red-tinted gradient and border to visually separate it from the neutral Start screen.

The food element uses layered ::before/::after pseudo-elements with animated linear-gradient transforms to produce a multi-directional glowing "shine" effect — all done in pure CSS, no JS-driven animation.

7. Deployment Specifics

Hosting Vercel — static deployment
Live URL https://snake-game-sam-io.vercel.app/
Build Step None — no bundler, transpiler, or package.json build script
Framework Preset None (plain static site)