Technical Specs
Full technical and architectural documentation of the Snake Game arcade project.
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.
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.
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.
HTML5 — dynamically generated DOM-element grid (no <canvas>)
DOM manipulation — CSS class toggling (.fill, .food) on cached grid-cell divs
Vanilla CSS — CSS Custom Properties, Flexbox (page layout) + CSS Grid (game board)
Vanilla JavaScript (ES6+) — procedural, single-file, no modules/classes
None — no CDNs, game engines, or third-party libraries
Browser localStorage (highScore only)
Vercel — static deployment, no build step
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.
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.
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.
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.
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().
Hover over each structure to reveal its shape (no database — this is the in-memory game state).
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 }
]
Single {x, y} coordinate object, regenerated on every successful eat.
{ x: 5, y: 12 }
Object mapping stringified "row-col" keys to their corresponding cached DOM div nodes.
{
"0-0": <div class="block">,
"0-1": <div class="block">,
...
}
Page layout, stats header, dynamically-populated game board container, and Start/Game Over modals.
CSS reset, theme variables, Flexbox/Grid layout rules, glassmorphism modal styling, and keyframe animations for the food's shine effect.
All game logic — grid initialization, game loop, rendering, collision detection, food spawning, input handling, timer, and localStorage high-score persistence.
Script is loaded at the end of <body> for standard blocking execution after DOM parsing.
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.
| 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) |