Triangles in Javascript

This is demonstration of rendering arbitrary triangles (relatively fast) with javascript/DOM/css (no images, flash, canvas tags or java applets). This is known so far to work in IE6 (with some hacks to render transparent borders) and IE7, as well as the latest versions of Firefox, Opera and Safari. This was hacked together in 2 evenings, so there are some glitches and the code is not great; it's just a proof of concept.

Yes, that is a 3D object being rotated and rendered in real-time! Use the following keys to rotate the shape:

  • rotate around x-axis (green): W/S
  • rotate around y-axis (blue): A/D
  • rotate around z-axis (red): Q/E

How it Works

The technique used here is different than other Javascript drawing libraries. Usually, triangles are constructed by stacking several 1-pixel tall DIVs of varying widths on top of each other. A 100-pixel tall triangle would need 100 DIVs! My method uses many fewer DIVs, and here's how...

It's All About Borders

Let's render a DIV with very thick borders of differing colors:
Look at my borders!

See that nice diagonal line in each corner? What if we only use two adjacent borders, and set the color of one to "transparent"?
Look at my borders!

Now let's make the DIV have a width and height of zero:

We've got ourselves a right triangle! Varying the widths of the adjacent borders yields right triangles of different sizes and proportions. Different orientations can be achieved by carefully selecting which two adjacent borders to use.

But What Good is a Right Triangle?

So a right triangle is nice to have, but we want triangles of ANY shape and size. The following image shows how an arbitrary triangle can be broken into several right triangles:

As you can see, this 256-pixel tall triangle only requires about 10 DIVs, as opposed to 256 DIVs. This reduction in DIVs to be rendered by the browser greatly increases the speed of triangle rendering.

But IE6 Doesn't Support Transparent Borders

IE does have several filters. One of them (chroma) allows you to specify a color that you would like to be rendered as transparent. I chose the color "cyan" because it's an ugly color that is traditionally used for indicating transparent portions of sprites. I use IE's conditional HTML comments to conditionally add the filter to the CSS for the triangle divs and use "cyan" in the javascript instead of "transparent" for the color of the borders that should be invisible. The drawback to this work-around is that if I try to render a cyan-colored triangle, the whole triangle will be invisible. The transparency color must be carefully selected to avoid accidental transparency where it is not wanted.

Further Explanation

I am flattered to have my ideas expanded upon and more thoroughly explained by Brian Beckman and Erik Meijer.

The Story of the Teapot in DHTML

  • Article in "Communications of the ACM", Vol. 56 No. 3, Pages 50-55
    Online abstract (full article is premium content; can also be purchased as PDF or hard-copy of magazine)
  • Article in "acmqueue", February 11, 2013, Volume 11, issue 2
    HTML | PDF
  • Lecture at "YOW! Australia", 2012
    Video