DEV Community

Cover image for HTML5 canvas... responsive!
George Francis
George Francis

Posted on

HTML5 canvas... responsive!

Hey folks,

I recently decided to learn SVG to see how it could help me with creative coding / generative art. Safe to say, I was blown away by how incredibly simple and easy it was to create truly responsive, scalable works that I could embed anywhere.

This was amazing for a while, until I started getting a craving for some bitmap action.

Cool, I thought. Let's got to <canvas> land.


Nope, not cool. I had forgotten how painful it was to make <canvas> actually look good.

The default <canvas> element was a million miles away from the responsive, crisp rendering nirvana of SVG.

Everything looked blurry on my retina screen, making the element fluid was a living nightmare and loosing my drawing state on resize made me sad (especially for generative stuff)

VBCanvas to the rescue

As a remedy to the issues outlined above, I have created a JavaScript library - VBCanvas that addresses the responsive issues of the default <canvas> element.

It does this by introducing a viewBox attribute that works just like SVG's.

You can check the library out here on Github or here on NPM

How it works

In short, you can define a viewBox for your canvas - say 0 0 100 100 (x, y, w, h) and draw everything relative to those coordinates. The setup looks something like this:

const { ctx, el } = VBCanvas.createCanvas({
  // viewBox (x, y, width, height)
  viewBox: [0, 0, canvasWidth, canvasHeight],
  // where to mount the <canvas> element
  target: '.canvas-wrapper',

// draw stuff with ctx!
Enter fullscreen mode Exit fullscreen mode

The <canvas> element will then automatically scale / respond exactly like an <svg> element. You can set any dimensions you like, VBCanvas will take care of all the scaling for you.

This makes creative truly responsive <canvas> elements extremely easy!

Here is a simple example in which the canvas is always scaled to fit it's container. Much like background-size: contain; in CSS or xMidYMid meet for SVG.

And here is an example where the canvas is scaled to fill it's container. Much like background-size: cover in CSS or xMidYMid slice for SVG.

The code for the two above examples is exactly the same, apart from the scaleMode option which defines how the canvas should scale.

Note: I have noticed that requestAnimationFrame sometimes jumps frame rate in iFrames / embeds, if you notice some slightly wacky speed stuff in the examples, it's that.

I suggest opening the examples up and seeing how the canvas responds to resizing the viewport.

Have a play!

I hope some people find this library useful, and please do give me a shout on twitter @georgedoescode if you have any feedback. PRs / issues are of course always welcome 🙏

Top comments (5)

jamesrweb profile image
James Robb

Great article, really enjoyed reading this one.

For most of my creative coding I use P5 or D3 but native canvas has always been interesting to me, the thing I don’t really like is the API, it can be quite cumbersome once you want to implement something more complex than the examples above for example. I like the abstractions that P5 and others give me in that regard.

I would like to learn more native canvas stuff though and so if you have tips about mitigating the “complexity factor” or a “best practices guide for canvas” or just some useful guides, that’d be cool! If not, maybe you’ll be writing more about canvas in the future? 😉

georgedoescode profile image
George Francis

Ah awesome thank you so much! Really glad you enjoyed the read and hope you find the lib useful. I also love p5, I got started programming with Processing and have loved that world ever since.

That's a great idea! Definitely something I would be interested in exploring, I feel like not too many people are writing about <canvas> so it could be cool to put together some posts :)

jamesrweb profile image
James Robb

Exactly, looking forward to your future content! 👌

lukeshiru profile image
Luke Shiru

Great idea and great implementation! Does it support TS? If not, are PRs welcome?

georgedoescode profile image
George Francis

Thank you! It does not right now, although PRs are 100% welcome!