Responsive p5.js Sketches with windowResized() and Aspect Ratio Control
Learn how to keep a p5.js canvas filling the browser window while preserving a fixed aspect ratio using the windowResized() callback and createCanvas().
05 Aug 2026, 00:24 UTC

Problem: Canvas Stays Fixed When the Browser Changes Size
When you start a p5.js sketch with createCanvas(400, 400), the drawing surface keeps those pixel dimensions even if the visitor resizes the window. The result is either unwanted scrollbars or a tiny sketch surrounded by empty space. For a responsive experience you need the canvas to grow or shrink with the viewport while keeping a predictable aspect ratio.
Thesis: Use the windowResized() callback to recreate the canvas with new dimensions derived from windowWidth and windowHeight
p5.js provides two tools that make this straightforward:
windowWidthandwindowHeight– variables that update automatically to match the browser’s viewport.windowResized()– a special function that p5.js calls whenever a resize event fires.
Inside windowResized() you simply call createCanvas() again with the desired width and height. Because p5.js recreates the canvas element each time, the drawing buffer matches the new size and the coordinate system stays consistent with the draw() loop.
Worked Example: 16:9 Aspect Ratio that Scales Vertically
// Global variables to store the desired ratio
let ratioWidth = 16;
let ratioHeight = 9;
function setup() {
// Create the initial canvas using the current window size
const startWidth = windowWidth;
const startHeight = windowHeight * (ratioWidth / ratioHeight);
createCanvas(startWidth, startHeight);
}
function draw() {
background(30);
// Example drawing: a moving circle that stays within the canvas
fill(200, 100, 250);
const x = (frameCount % width) + 20;
const y = height / 2;
ellipse(x, y, 40, 40);
}
function windowResized() {
// Preserve the 16:9 ratio by basing width on the current height
const newHeight = windowHeight;
const newWidth = newHeight * (ratioWidth / ratioHeight);
resizeCanvas(newWidth, newHeight);
}
Explanation:
setup()computes an initial width that fits the current height while keeping the 16:9 proportion.draw()runs unchanged; because the canvas size is updated viaresizeCanvas()(a thin wrapper aroundcreateCanvas()that preserves the drawing buffer), all coordinates remain valid.windowResized()is triggered by the browser; we recalculate dimensions from the newwindowHeightand callresizeCanvas().
You can verify the behavior by opening the sketch in a browser, opening DevTools, and watching the <canvas> element’s width and height attributes change as you drag the window edges.
Trade‑off: Brief Flicker and Pixel‑Density Considerations
Recreating the canvas on every resize can cause a momentary visual flicker as the old element is removed and a new one painted. Mitigation strategies include:
- Setting the canvas to
display: blockin CSS so it does not cause layout shifts. - Calling
pixelDensity(1)(or your preferred density) after eachresizeCanvas()if you rely on high‑DPI rendering.
If your sketch does heavy per‑frame pixel manipulation, consider throttling the resize callback with setTimeout or requestAnimationFrame to limit how often the canvas is rebuilt.
Actionable Closing
Start with the snippet above, adjust the ratioWidth and ratioHeight constants to match your design (e.g., 4:3, 1:1, or a dynamic ratio based on windowWidth), and test across devices. The approach keeps the sketch responsive, avoids manual DOM manipulation, and works with the standard p5.js render loop.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.