The actual web

Every now and again I have a weird little idea for an app — a game, whatever. And my default position is to build it with HTML and CSS. The DOM, that is. Not canvas; not WebGL. Now, I freely admit that you can do great things with both; most of the exciting games out there are <canvas>, and most of the really impressive demos out there are WebGL. three.js is flat-out genius. But they’re very much “here is a box, draw in it” do-it-yourself solutions. There would have been a pretty similar situation available to everyone had every browser just shipped the Unity3D browser plugin. I like having the browser do the heavy lifting for me: create a <div> and use CSS to colour it in with a radial-gradient, move it around and distort it with transform, handle events with mouseover and touchmove, handle making all my elements be textures on the graphics card for fast movement without me having to force it. I don’t want to have to reimplement all that stuff by asking the browser for a sectioned-off square to draw in and then handling all the hard work myself.

Of course, this utopia I describe doesn’t actually work all that well. There’s a fairly large disconnect — it gets smaller all the time, but it’s there, it really is — between using the browser engine to do the work and actually getting what you want done.

Tiny example. I had this idea for a game where you’d drag a circle (think of it as a criminal, viewed top down) through a maze, with searchlights around. Now, it’s perfectly possible to make a searchlight-looking thing with pure CSS. You get a square <div>, skew it with transform to give yourself a triangle, fill it with a radial-gradient from yellow to transparent, and animate it with a CSS animation.

[raw]

[/raw]

And, we have a searchlight. Now, drop a wall in place so that the searchlight hits the wall and doesn’t extend beyond it:

[raw]

[/raw]

All well and good. Now, though, you need to turn it into a game. So, a couple of things: be able to ask the question “is this point here inside a searchlight?” and make the wall look like it’s reflecting the light a bit rather than going under it.

And, as far as I can tell, you just flat out can’t do that. If you’ve transformed an element, how can you work out the pixel position it’s now at? Well… by implementing the matrix transformations that transform executes yourself in code, that’s how. If you’re going to go to all the effort of working out all the maths yourself… what benefit is there in having the browser work them out for you as well, eh? Not all that much; at that point, if you’re doing all the work yourself anyway, you might as well draw on a <canvas>. Similarly with having the wall “reflect” light: you want it to look something like this:

searchlight-wall-reflected.png

and, you know what? You can’t do that with CSS at all (maybe Adobe’s blending spec will make it doable, but you can’t right now). So the instant you want to do something a little out-of-the-ordinary, you end up thinking… well, I’ll just draw it on a <canvas>… and then you’re totally outside the browser. All the elements on your canvas have to be handled by you. You have to do collision detection yourself. You’ve got no :hover, no touchstart, nothing.

CSS is great for documents, don’t get me wrong, and it’s great for adding little frissons to your pages. But if you try and use it for games, for things that aren’t documents… well, you step one inch outside what it can do, and suddenly you’re in a world where you have to do all the work yourself, where you get a black box to draw in and you’re just an old-fashioned games programmer writing her own mouse-handling routines.

The chasm between these two is dark and yawning and it makes me sad. It’s the sheer disconnect here that depresses me: you’re fine up to a point with CSS, and suddenly you think “I want to do this one thing that CSS can’t do” and then you have to throw away all your existing work and reimplement everything from scratch — fonts, pointer events, gradients, layout, positioning, colouring, shadows, blurring, everything — completely by hand.

It’s hard to drum up conversation about this, because most people don’t want to use the DOM for this stuff: almost every “HTML5 game” I’ve seen has been <canvas>-based. People don’t want to use the DOM. I’m swimming against the tide, here.

Should I be swimming against the tide? Is this not what the DOM is for? Is it just for making words bold and for adding neat little effects to static websites? For anything more complex should I just be embracing canvas and WebGL? And if so… why wouldn’t I just write a native app?