CSS Gradients via Canvas
JavaScript
Latest commit 959e6d4 May 7, 2012 @westonruter Update README.md
Permalink
Failed to load latest commit information.
.gitignore
README.md
css-gradients-via-canvas.js
example.html
linear1.png
linear2.png
radial1.png

README.md

CSS Gradients via Canvas

In a current project an old project when I worked at Shepherd Interactive, certain page elements were designed with background gradients. Given the desire to minimize the need for externally-loaded background images wherever possible, I thought this would be a great opportunity to play around with WebKit's proposed CSS Gradients, which are natively supported by Safari, Chrome, and other WebKit-based browsers. In being a WebKit proposal, however, CSS Gradients are not (yet) natively supported in other rendering engines as used by Firefox, Opera, and Internet Explorer.

CSS Gradients via Canvas provides a subset of WebKit's CSS Gradients proposal for browsers that implement the HTML5 canvas element. To use, just include css-gradients-via-canvas.js (12KB) anywhere on the page. Unlike WebKit, this implementation does not currently allow gradients to be used for border images, list bullets, or generated content. The script employs document.querySelectorAll()—it has no external dependencies if this function is implemented; otherwise, it looks for the presence of jQuery, Prototype, or Sizzle to provide selector-querying functionality.

The implementation works in Firefox 2/3+ and Opera 9.64 (at least). Safari and Chrome have native support for CSS Gradients since they use WebKit, as already mentioned. Beginning with version 3.6, CSS Gradients are also natively supported by Firefox and this implementation will defer in such case; note that you will need to specify two separate background CSS properties, one with -webkit-gradient and another with -moz-linear/radial-gradient which has a different syntax). This implementation does not work in Internet Explorer since IE does not support Canvas, although IE8 does support the data: URI scheme, which is a prerequisite (see support detection method). When/if Gears's Canvas API fully implements the HTML5 canvas specification, then this implementation should be tweakable to work in IE8. In the mean time, rudimentary gradients may be achieved in IE by means of its non-standard gradient filter.

CSS Gradients via Canvas works by parsing all stylesheets upon page load (DOMContentLoaded), and searches for all instances of CSS gradients being used as background images. The source code for the external stylesheets is loaded via XMLHttpRequest—ensure that they are cached by serving them with a far-future Expires header to avoid extra HTTP traffic. The CSS selector associated with the gradient background image property is used to query all elements on the page; for each of the selected elements, a canvas is created of the same size as the element's dimensions, and the specified gradients are drawn onto that canvas. Thereafter, the gradient image is retrieved via canvas.toDataURL() and this data is supplied as the background-image for the element.

A few notes regarding interactivity with this implementation: CSS gradients will not be applied to elements dynamically added after DOMContentLoaded. Additionally, each element that has a CSS gradient applied to it gets assigned a method called refreshCSSGradient(); at any time, this method may be invoked to redraw the gradient on a given element. This is especially useful (and necessary) when an element's size dynamically changes, for example as the result of some user interaction. Likewise, it is important to note that it will not work to rely on event handlers to invoke refreshCSSGradient() on elements whose style is changed by CSS rules with pseudo-selectors like :hover and :active; this is because event handlers are fired before the rule's style changes are applied to the element. Toggling an element's class name by scripting is how you can assure that its style will be changed before calling refreshCSSGradient().

See examples.

Changelog

2010-04-29
Updated license to be GPL/MIT dual license instead of just GPL.
1.3 (2010-03-09):
Detecting native support in Firefox 3.6; it had only been detecting support for 3.6 alpha, which had significantly different syntax. I ported the linear gradient examples over to use the new native Firefox syntax, but am still working on the radial gradients; the syntax has changed a lot!
1.2 (2009-09-30):
Phong Nguyen raised an excellent point in that stylesheets which don't contain any CSS Gradients should be ignored in order to improve performance (in his case, for example, the jQuery UI stylesheets are large and don't need to be parsed). Now you can add class="no-css-gradients" to any style or link element and that will prevent this script from looking for CSS Gradients to apply with canvas.
1.1 (2009-08-12):
Now if cssGradientsViaCanvas.useCache is set to true, the CSS rules containing gradients are cached in sessionStorage instead of having to be re-parsed out of the stylesheets each time a page loads. For this to work, there must be implementations of JSON.stringify() and JSON.parse() available (e.g. json2.js).
Ability to use data: URIs for images is not explicitly detected since testing for the presence of canvas.toDataURI() is sufficient.
1.0.3 (2009-08-10):
Detecting support for native support for CSS Gradients in Firefox 3.6
1.0.2 (2009-08-05):
Now requiring that gradient(…) only be used with the background-image property instead of with the background shorthand properties since the additional background-* properties are not parsed out.

(Since I started redirecting from my blog to GitHub, I've archived the old comments I had received there.)


Developed by Weston Ruter (@westonruter).