Your first starfield
A tiny animated starfield in pure HTML, CSS and JavaScript.
Open your editor, paste the code below, and save it as
starfield.html — then open it in a browser.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Starfield</title>
</head>
<body style="margin: 0; background: black;">
<canvas id="sky"></canvas>
<script>
// Grab the canvas element from the page by its id.
const canvas = document.getElementById("sky");
// Make the canvas fill the whole browser window.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Get a 2D drawing context — everything is drawn through this object.
const ctx = canvas.getContext("2d");
// Store the center of the screen. It is used as the vanishing point.
const cx = canvas.width / 2;
const cy = canvas.height / 2;
// This array will hold all our stars.
let stars = [];
// Create 100 stars with random positions and depths.
for (let i = 0; i < 100; i++) {
stars.push({
// x, y — screen position before projection.
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
// z — depth. 1000 = far away, 0 = very close.
z: Math.random() * 1000
});
}
// Main animation loop. It runs once per frame.
function draw() {
// Fill the whole canvas with black to erase the previous frame.
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Stars are white.
ctx.fillStyle = "white";
// Move and draw every star.
for (let star of stars) {
// Move the star closer to the camera.
star.z -= 5;
// If the star passed the camera, respawn it far away.
if (star.z <= 0) {
star.z = 1000;
star.x = Math.random() * canvas.width;
star.y = Math.random() * canvas.height;
}
// Project the 3D point (x, y, z) onto the 2D screen.
// Dividing by z creates perspective: closer = bigger shift.
const sx = (star.x - cx) / star.z * 500 + cx;
const sy = (star.y - cy) / star.z * 500 + cy;
// Closer stars are drawn bigger.
const size = (1 - star.z / 1000) * 4;
// Draw the star as a small filled square.
ctx.fillRect(sx, sy, size, size);
}
// Ask the browser to call draw() again before the next repaint.
requestAnimationFrame(draw);
}
// Start the animation.
draw();
</script>
</body>
</html>
How it works: each star has an
x, y position and a
z depth. Every frame we decrease
z, which makes the star move toward the
camera. We then project it onto the screen with
(x - cx) / z * 500 + cx — a classic
perspective formula. When a star reaches
z = 0, we respawn it far away to keep the
field infinite.