17th June 2013, by Edward Cant.
In short, it is possible to use the HTML canvas element to dynamically add these resources to the HTML head when it makes sense to do so.
Generated favicons have been around a while, but the potential to use the same technique to cover touch icons encourages an efficient approach, reducing requests and bandwidth requirements in the process.
Check out deletefacebook.com (disclosure, my site) for a favicon and touch icon production example.
A favicon as well as iPhone and iPad touch icons (with Retina variations) are generated in under 2KB of JavaScript. One source file, zero icon requests.
This article serves as a demo for the art direction use case. A cloud is generated using circles and gradients appropriate to the target icon size.
The demos are built within the context of my own app engine, but the code is simple enough to modify for your own purposes.
The genImage(); function referenced initialises a canvas, draws the icon and returns a data URI via canvas.toDataURL(); of the image for insertion into the document head.
That part is up to you to implement as you see fit.
// Favicon, standard icons.
//--------------------------
this.icon = function(width, height, drawFunc) {
var d = document, img = this.genImage(width, height, drawFunc);
// Insert into head
var l = d.createElement('link');
l.rel = 'icon';
l.href = img;
l.sizes = width + 'x' + height;
d.head.appendChild(l);
};
// Touch icon
//------------
this.touch = function(width, height, drawFunc) {
var d = document, img = this.genImage(width, height, drawFunc);
// Insert into head
var l = d.createElement('link');
l.rel = 'apple-touch-icon-precomposed'; // Precomposed to support Android
l.href = img;
l.sizes = width + 'x' + height;
d.head.appendChild(l);
};
It's possible to optimise further by narrowing devices down by screen width or device pixel ratio, as demonstrated in the code from deletefacebook.com
// 16 x 16 icon
//--------------
fE.icon.icon(16, 16, function() { draw(16); });
// Touch icons
//-------------
if(scrWidth < 569) {
// iPhone
fE.icon.touch(114, 114, function() { draw(114); });
} else if(scrWidth < 1025) {
// iPad
fE.icon.touch(144, 144, function() { draw(144); });
}
// Draw icon (from deletefacebook.com)
//-------------------------------------
var draw = function(size) {
var ctx = fE.icon.c.ctx;
var linearGradient = ctx.createLinearGradient(0, 0, 0, size);
linearGradient.addColorStop(0,'#f33');
linearGradient.addColorStop(1,'#b11');
ctx.fillStyle = linearGradient;
// Background gradient
ctx.fillRect(0, 0, size, size);
// Stripe
ctx.lineWidth = size / 8;
ctx.strokeStyle = '#fee';
ctx.beginPath();
ctx.moveTo(0.75 * size, 0.25 * size);
ctx.lineTo(0.25 * size, 0.75 * size);
ctx.closePath();
ctx.stroke();
// Gloss
ctx.fillStyle = 'rgba(255, 255, 255, 0.125)';
ctx.fillRect(0, 0, size, size / 2);
};
I had hoped that this technique would make pinned icon generation easy. Sadly, I could not get IE to play ball.
A blank favicon is present in the site root directory for really old browsers.
I've generated icons for the demos, but you could just draw an image onto the canvas. The image could be one that is already on your website, thereby avoiding any extra requests.
Consider the benefits of generated graphics. Gradients, noise, tiling, shadows can all be used without the cost of transferring them via an image file.
Follow the author on Twitter.
‘Effortless responsive web design testing’.
Canvas Generated Icons. Read more.
Targeting Windows 8 Snap Mode. Read more.
CSS @viewport rule or viewport meta tag? Read more.
The Responsive Viewport. Missing piece of the responsive web design puzzle? Read more.
Getting the Viewport Scale.
Read more.
Hiding the iPhone Address Bar.
Read more.
Orientation Correct Screen Width.
Read more.
iPhone Title Modification.
Read more.
Optimising for High Pixel Density Displays.
Read more.
CSS3 Media Query Prototyping With ProtoFluid.
Read more.
AJAX Kill Switch. Version 2.
Read more.
URI Processing With JavaScript.
Read more.
All source code is provided for free.
A standard disclaimer of warranty and limitation of liability applies.