Google Calendar released a new favicon which prompted a few mentions from friends on Twitter. The first, probably more important was from Cennydd:
New Google Calendar icon most un-Googley. I like it.
Then Danny pitched in with:
I see Google Calendar has a new icon. They could use the current date rather than "31" though
So let's fix that shall we?
UK EVENTAttend ffconf.org 2024
The conference for people who are passionate about the web. 8 amazing speakers with real human interaction and content you can't just read in a blog post or watch on a tiktok!
£249+VAT - reserve your place today
How it's done
The trick here is to use a canvas element and export the image data as a png. Since favicons can be pngs then we know this can work. Note that this technique has been done before.
The setup is needing to create two calendar images: one with the date if this doesn't work (defaulting to something like 31) and the second without the date text. For whatever reason, I went and replicated the Google Calendar icon in Photoshop:
The plan now is to use the favicon template and lay the text over. Simple.
The minimum starting point
Start your document by including the favicon link
element in the head
:
<link id="favicon" rel="icon" type="image/png" href="ical-icon-complete.png" />
The "complete" version is the favicon with the 31 on it already. Next we'll use JavaScript to dynamically create the favicon.
Using a canvas for dynamic favicons
We need the following items to make this effect work:
- A canvas that doesn't have to live in the DOM, that's 16x16 - our favicon size
- The template favicon image
- Once, and only once, the template image has loaded, we then go adding the text
- The date in a two character format, i.e. 04 is the 4th
That's it. For connivence I've added an id
to the link
element so that I can just change the href
when the image is ready. The following JavaScript can be included anywhere below the link
element:
(function () {
var canvas = document.createElement('canvas'),
ctx,
img = document.createElement('img'),
link = document.getElementById('favicon').cloneNode(true),
day = (new Date).getDate() + '';
if (canvas.getContext) {
canvas.height = canvas.width = 16; // set the size
ctx = canvas.getContext('2d');
img.onload = function () { // once the image has loaded
ctx.drawImage(this, 0, 0);
ctx.font = 'bold 10px "helvetica", sans-serif';
ctx.fillStyle = '#F0EEDD';
if (day.length == 1) day = '0' + day;
ctx.fillText(day, 2, 12);
link.href = canvas.toDataURL('image/png');
document.body.appendChild(link);
};
img.src = 'ical-icon.png';
}
})();
The important part is the order in which the code runs. It creates an image element, and hooks an onload
event handler. When this onload
event runs, it draws the image on to the canvas using ctx.drawImage(this, 0, 0)
. this
refers to the image the onload
event acted upon, and 0, 0
is the top, left position to start drawing.
Next we style the text and draw it on.
Finally using canvas.toDataURL
we set a new href to the link.
You should be able to see the code running on this blog post, if you look at the favicon associated with this page, it should be the calendar icon with the correct date if your browser supports the canvas API (IE8 and below don't, all other browsers do).
Try changing the date to test it out.