Description
Uses the recursive backtracker algorithm to generate a maze with SVG.
Created on 4 June 2026.
Code
<svg stroke='#fff'>
<circle r='200%'/>
</svg>
<script>
const SVG_NS = 'http://www.w3.org/2000/svg';
const svg = document.querySelector('svg');
const cellSize = 20, // in pixels
pathWidth = 0.8,
width = Math.floor(innerWidth / cellSize),
height = Math.floor(innerHeight / cellSize);
// Set up SVG
svg.setAttribute('viewBox', [ -.6, -.6, width + .2, height + .2 ]);
svg.setAttribute('stroke-width', pathWidth);
// Maze variables
class Cell {
constructor(x, y) {
this.x = x;
this.y = y;
this.unvisited = true;
}
};
const randomInt = (max) => Math.floor(max * Math.random()),
randomArrayItem = (array) => array[randomInt(array.length)],
grid = Array(width).fill``.map((_, x) => Array(height).fill``.map((_, y) => new Cell(x, y))),
stack = [ randomArrayItem(randomArrayItem(grid)) ];
let pathData = '';
// Maze generation
while (stack.length) {
const currentCell = stack.pop(),
{ x, y } = currentCell,
unvisitedNeighbours = [
grid?.[x]?.[y - 1],
grid?.[x + 1]?.[y],
grid?.[x]?.[y + 1],
grid?.[x - 1]?.[y],
].filter(cell => cell?.unvisited);
if (unvisitedNeighbours.length) {
const chosenNeighbour = randomArrayItem(unvisitedNeighbours);
chosenNeighbour.unvisited = false;
stack.push(currentCell, chosenNeighbour);
pathData += `M${[x, y, chosenNeighbour.x, chosenNeighbour.y]}v${pathWidth / 2}v-${pathWidth}`;
}
}
const path = document.createElementNS(SVG_NS, 'path');
path.setAttribute('d', pathData);
svg.append(path);
</script>