dom3d: rendering 3d with CSS3
Fork me on github!
James Long works for Mozilla and can be reached at [email protected]
Here is a 3d object. It is rendered with pure HTML and CSS
using 2d
transforms. These let you specify a transform
property on a DOM element composed
of translate
, rotate
,
skew
, and scale
functions.
To achieve the 3d effect, I project the 3d triangles into 2d
screen space using javascript, and then calculate the necessary
transform
value to display the 2d triangle.
.off:nth-of-type(2n) { top: 100px; opacity: 0; -moz-transition: all 2s; }
So without any SVG or canvas, you can have real-time 3d objects in modern browsers! What's the benefit? Well, you don't have to deal with a canvas, and you can click on links underneath it. Maybe this is just a cool hack, maybe not?
What's the point?
This is mainly just a cool hack, but I think there's use cases for quick 3d effects on websites. There are a few benefits to this approach: you get to manipulate the elements with normal CSS, and you can overlay 3d objects onto pages and still let the user interact with the page.
I'm interested to see what others think of this hack and see how far it can go. I'd like to see this library turn into a quick 3d effects library that supports HTML/CSS, SVG, canvas, and webgl.
How's it work?
A 2d triangle is really a quad, but imagine cutting the quad from two opposite corners and taking only the left triangle. That's essentially what I do, by way of the CSS3 background linear-gradient property. It aligns the background with two opposite corners and makes one side completely transparent.
Here's an example (only showing the -moz properties, but dom3d supports -webkit and -o too):
background-image: -moz-linear-gradient(-45deg, red 50%, transparent 0);
It turns out that you can render any 2d triangle with the
right translate
, rotate
, skew
,
and scale
settings for the transform
CSS property.
So you just have to project all the 3d triangles onto the 2d screen space, and manipulate the DOM triangles to render them according to the 2d coordinates.
Here is example CSS from a rendered triangle:
-moz-transform: translate(442.176px, 306.35px) rotate(2.12662rad) skew(2.7961rad) scale(197.767, 180.506); background: -moz-linear-gradient(45deg, rgb(87, 111, 121) 50%, transparent 0pt);
Notes
CSS3 isn't fully supported yet across all browsers, but dom3d supports Firefox, Chrome, Safari, and Opera. I think IE9 support is possible too.
Obviously there are issues with seams. This is due to anti-aliasing that is done on the edges. Different browsers have slightly different effects.
In Firefox 4, there is also a glitch where if I re-use DOM elements between frames, you can see the other edge of the DOM elements briefly. The example above creates new DOM elements per frame, but if you turn on any of the options to the right it'll switch to re-using DOM nodes and you'll see the effect. Firefox 6 (nightly) does not have this glitch.
Various browsers will have glitches with this hack, as it's really a severe and gross hack. Or maybe just a good test case?