While designing this site, I thought it would look cool to create an animated background for the homepage, and maybe some other pages (pending). I always felt that Processing was a nice way to write graphics, and was pretty excited to find a JavaScript library, p5js, that seemed to function in practically the same way.
Starting with p5js
p5js uses, similarly to Processing, just 2 routines: setup(), which is run once at the very
beginning of execution; and draw(), which runs continuously and is responsible for updating the
graphics. By default,
draw() runs as often as
possible, but a frame rate can be set.
For example, this program:
1function setup() {
2//create canvas
3createCanvas();
4
5//set constant framerate -- this is important for consistent speed across devices
6frameRate(30);
7
8//setup the shape object we will draw
9shape = {
10pos: createVector(0, 0),
11dir: createVector(5, 4),
12size: width / 10,
13};
14}
15
16function draw() {
17//setup colours
18background(102, 92, 84);
19stroke(169, 172, 38);
20fill(169, 172, 38);
21
22//draw square
23square(shape.pos.x, shape.pos.y, shape.size);
24
25//move square
26shape.pos.add(shape.dir);
27
28//bounce off of walls
29if (shape.pos.x < 0 || shape.pos.x + shape.size > width) {
30shape.dir.x _= -1;
31}
32if (shape.pos.y < 0 || shape.pos.y + shape.size > height) {
33shape.dir.y_= -1;
34}
35}renders to:
I have omitted some of the lines that deal with canvas sizing and placement, but I’ll come on to that in a second. For the sake of interest, this is the full script.
So that’s awesome, we can now animate whatever relatively painlessly. I’ll omit the details on how I created the boids now, and move on to:
But how do I make it a background
The first thing you’ll notice if you try to create a canvas on a page that already has content is that it’ll just drop it at the end. We obviously want to be able to position the animation as a normal HTML element:
Create a containing
<div>at the very top of your page, and make its position fixed:… </head> <body> <div id="background" style="position: fixed; width: 100%; height: 100%;"></div> <div class="content"> …You also want to make the canvas position fixed:
canvas { position: fixed; }Identify this
<div>as the parent element of your canvas in the sketch code, making sure to specify that the width and height of your canvas should be the same as that of the window:function setup() { canvas = createCanvas(windowWidth, windowHeight); canvas.parent("background"); … }Finally, we need to make sure the background is actually in the background, this can be done by setting the z-index of the canvas:
function setup() { … canvas.style("z-index", "-1"); … }Of course it's important to make sure that all the other elements on your page have z-indeces > -1.
Getting that sweet blur effect
The last thing you might notice on my homepage is the blurring effect on the central panel. This is, unbelievably, very easy to achieve. There is a CSS opacity property, however this doesn’t work very well (or at all) with the blurring, so instead we can just set the background color to have some alpha, and use the backdrop-filter property to get the blur:
.page\_\_body {
background-color: #3c3836a4;
backdrop-filter: blur(10px);
}And that’s it! I didn’t mention a lot of the quirks of getting all this to work with hugo, and a custom theme, but that probably wouldn’t have been so difficult if I understood hugo better. I think the effect looks really nice, although admittedly it might be a bit distracting for anything but a splash page.
[Update 2025-10-31]
The background has now been rewritten in Rust and WASM. It’s (upsettingly) not much faster at the moment, but hopefully will be easier to rewrite in an efficient way in future.
Back to the other posts?