Grids a la CANVAS
December 29th, 2011There are lots of grid libraries out there. Naturally, this means we need to reinvent the wheel. With HTML5, we have a fantastic new tool called the CANVAS tag which frees us from the limitations of CSS.
The canvas tag is beautifully documented and supported on most modern browsers. Further, aside from IE 6-8, the vast majority of the browsers support the element as it is defined, which means we don’t need wrapping libraries to deal with browser quirks.
Using all of these libraries as baselines, there are a few essential pieces of functionality:
We must be dimension agnostic. Whether our space is 480px or 2560px wide, it should work well
We must support any number of columns
We must support n-wide columns
We must support arbitrary gutter sizes
We must get results consistent with those other libraries
To that end, I present the grid() function. It returns an object with an array of offsets, as well as plenty of other information that facilitates writing still more content to the canvas (or advanced features like simulating sub-columns). It has no library dependencies, although it currently does not gracefully handle older browsers.
Basic usage is simple:
result = AB.grid(canvas, 16, 20);
This one line takes the canvas element specified in the first parameter and divides it into 16 columns separated by 20 pixel gutters. The function returns an object that looks like this:
{
cols: 16,
element: canvas#tutorial,
gutter: 20,
offsets: [0, 60, 120, ..., 900],
width: 40
}
You can also pass arrays:
result = AB.grid(canvas, [1, 3, 1], 10);
This divides the element into a 20% panel on the left and right and 60% in the middle. Now our response looks like this:
{
cols: 3,
element: canvas#tutorial,
gutter: 20,
offsets: [0, 194, 756],
width: 186
}
Let’s go changing the colors:
result = AB.grid(canvas, [1, 4], 10, { foreground: '#CCC', background: '#EEE' });
Need to pad the outer margins as well?
result = AB.grid(canvas, [1, 4], 10, { includeOuter: true });
Maybe we just want to simulate the arithmetic, without drawing anything?
result = AB.grid(canvas.width, [1, 4], 10);
This would also work:
result = AB.grid(canvas, [1, 4], 10, { overrideWidth: canvas.width });
Now you’re probably saying that this is all well and good, but why bother when we are already using a CSS layout library for the site in general? Aside from making it easier to construct graphs, we can also use this to generate perfectly sized images within the client.
The following three lines will create an image tag from a canvas and do it faster than the human eye can detect:
var img = document.createElement('img');
img.setAttribute('src', canvas.toDataURL());
document.getElementsByTagName('body')[0].appendChild(img);
You could almost as easily assign it as a background image (here I am finally employing jQuery):
$('body').css('background', 'url(' + canvas.toDataURL() + ')');
Note that you must wrap the image data in the strings url( and ) for this to work.
Check out the code on GitHub.




