Dynamic Favicons

Favicons should ideally be easy to manipulate, as easy as manipulating the web page’s UI. (Favicons are the little website icons you see in the address bar, browser tabs, etc.) For example, a chat app like Meebo could signal that your buddy’s trying to contact you, a mail app like GMail could indicate You Have Mail!

I’ve found surprisingly little info on this – is anyone doing it? Anyway, I’ve been wanting to play around with this for a while and having recently submitted the final book draft (post pending), I finally had some spare time to play with it. Fortunately, it turns out to be perfectly feasible – it seems that Firefox and Opera both use <link> tags to determine favico, and this can be changed dynamically to satisfaction. The only gotcha is that you can’t try to be too efficient – if you reuse an existing link object and overwrite its href property, the browsers won’t pay any attention. so you simply have to remove the existing link tag and add back a new one with the new icon URL. Unfortunately, IE and Safari don’t seem to use the link technique at all – I think they just use the “favicon.ico” file. If you know of a way their icons could be dynamically manipulated, please mail me or add a comment here.

So I’ve created a library, favicon.js, that lets you manipulate favicons with a single call – changeFavicon("theIconUrl.ico");. You can also set the document title, changeFavicon("theIconUrl.ico", "Hi Everybody!"), which just sets document.title. There are a couple of demos and a brief FAQ:

Ajaxify favicon demo

Implementation Details. Here’s the favicon.js code as it stands, all 32 lines of it :-).

< view plain text >
  1. var favicon = {
  3. change: function(iconURL) {
  4.   if (arguments.length==2) {
  5.     document.title = optionalDocTitle;
  6.   }
  7.   this.addLink(iconURL, "icon");
  8.   this.addLink(iconURL, "shortcut icon");
  9. },
  11. addLink: function(iconURL, relValue) {
  12.   var link = document.createElement("link");
  13.   link.type = "image/x-icon";
  14.   link.rel = relValue;
  15.   link.href = iconURL;
  16.   this.removeLinkIfExists(relValue);
  17.   this.docHead.appendChild(link);
  18. },
  20. removeLinkIfExists: function(relValue) {
  21.   var links = this.docHead.getElementsByTagName("link");
  22.   for (var i=0; i&lt;links .length; i++) {
  23.     var link = links[i];
  24.     if (link.type=="image/x-icon" && link.rel==relValue) {
  25.       this.docHead.removeChild(link);
  26.       return; // Assuming only one match at most.
  27.     }
  28.   }
  29. },
  31. docHead:document.getElementsByTagName("head")[0]
  32. }

Update (Two Days Later)

Crikey! Dugg and on Delicious Popular. And, well, Ajaxian too ;-). Digg is interesting … The last time I submitted my own story to digg, it got precisely two diggs (thanks to the other guy!). This time, I didn’t bother. Is there a moral here?

New, improved, with animate(). Most people get dynamic favicons, but some people have said this whole thing is about animation, about as useful as a blink tag, etc. Okay, that kind of misses the main point, which is about notifying the user while a tab is in the background. The FAQ makes it pretty clear that animated icons was a kind of afterthought (actually, it only occurred to me after I created the cycling demo – changing according to a timer was simply the easiest way to update a background tab, since there’s no chat functionality needed or anything like that). But, you know, when a simple idea like that causes seems so wrong to some people, there’s probably wheels in it. And while I did say animated GIFs are possibly more elegant in the FAQ, it since occurred to me that it’s a bit of a hassle for the casual developer to make an animated GIF. You also get the benefit of compatibility with Opera (and maybe others?). So I’ve added an animate() method, only 8 more lines in all, that lets you cycle through a sequence of images. I expect to post it over the weekend. Mmm…Eye Candy!

43 thoughts on Dynamic Favicons

Comments are closed.

  1. I believe this scenario is possible:

    When an event is fired or procedure is done on the server, a new procedure will get called and create a new Favicon in the wwwroot and flush the page, that the user is currently on, to the client. This will make the page reload and “voila” new Favicon. But you need to remain some kind of viewstate so the user don’t just gets handed a new page with all hers interactions gone (like typing etc.). And most importantly the Favicon is the same for all users.

    Come to think of it, I don’t think there is any bearable solution.

  2. I’ve been using the technique for a while to add favicons to those of my more frequently visited sites that don’t provide their own (by way of client side Greasemonkey scripts).

    I just centralized those little scripts into my Mark my links tool, which relieves me of the hassle of writing a new script every once in a while.

    Thanks for pointing out that one needs to drop link tags already in place to do real overrides though; I wasn’t aware of that, as I have mostly been adding to sites sans icons until now.

  3. Neat. Can’t say I ever needed it, but that should not hold anyone back ;)

    Minor nit: You don’t need to addLink both “icon” and “shortcut icon” – rel takes a list of values, separated by space, so “shortcut icon” actually means the tokens “shortcut” and “icon” – it’s a superset of “icon“.

  4. With 56K there is a half a second delay before the image is switched, which if you are trying to make it animated; looks REALLY crappy.

    Maybe you could preload the images before changing it.

  5. Erik, The arguments.length takes care of it, it’s I think the most easiest way to do overloading in JS. You could also have the arg though as you say and check if it’s defined.

    Jon, It’s true you can change favicon on the server-side – if the JS did something like submit a form or change the document URL, it would force a page refresh and at that point the server could overwrite favicon.ico. In practice, I’m not convinced it would add anything, though, because apparently Safari and IE cache favicon.ico without shame. I’m still learning about all the subtleties from everyone, but that’s my perception right now.

    Johan, I probably made a bit of a deal about the dropping and re-adding in case it helped anyone, though most people will probably do that anyway. For instance, with On-Demand Javascript, I’ve never even tried to overwrite a script node’s source – I’ve only ever deleted and added.

    Matthias, Sweet tip. Assuming it works fine on Opera and FF, it will neaten up the code nicely.

  6. Pingback: Favicon dinamiche con AJAX e Javascript at Vortexmind: free your mind

  7. Pingback: Alvanweb » Favicon های دینامیک

  8. Pingback: marksdigital

  9. Pingback: Favicons dinámicos » Celi Online

  10. Pingback: Honorable Mention » Blog Archive » Random favicon.ico

  11. Pingback: Faviconlar: Üreteçleri, Tasarımı, Yapımı | BlogcuBlogu.com

  12. Pingback: Skylog » Blog Archive » links for 2008-02-05

  13. Pingback: Talk To Frank - dynamic favicon | Only Network

  14. Pingback: Software As She’s Developed » Blog Archive » Taking Browser Tabs Seriously

  15. Here, at Cathetel, we use a simple IF argument in the Head Section that allows us to direct our static favicon to Internet Explorer, and all others to display, if they are able to, the animated version. Netscape and Firefox show the animated favicon. Directions for doing this, if anyone is interested, is at http://www.cathetel.com/favicon.htm . We must study your coding though as it is more sophisticated.

  16. Amyobus, what you’re using is a single animated GIF file, which is fine for most purposes. This article is about programmatically changing the favicon. You can use it for a straightforward animation, but since you could already do that in the way you’ve done it, the main reason to use this library is to change the icon when an event occurs.

  17. Pingback: Design favicons For Your Site With Favicon Generators | Solid Blogger

  18. Little thing that comes to my mind… Wich icon will the browser choose if I bookmark it while it’s changing? Hope it won’t be a problem if it’s integrated in the browser functionality. =P

  19. Hi,

    I am trying to use same with dojo, it works fine if I dont put fix for back forward button as provided from dojo, with the fix, if I put above code it does not work.

    Again this code starts working if I put alert from javascript. Would really appreciate any help for that.

  20. I managed to get Google Chrome working by using an IFrame as it seems to update the favicon when the “src” is changed, even if set to “about:blank” – Safari doesn’t work still though :P

    I added this to the end of “change”:

  21. Pingback: Dynamic Favicon Library Updated

  22. I believe Erik’s comment about optionalDocTitle are correct, at least for FF (3.6.8). If an attempt is made to set a title as well, the script will fail with “optionalDocTitle is not defined”. To overload, I believe you’d want to use arguments[1] rather than an undefined variable, or explicitly set the variable name in the function definition.

  23. Pingback: Browser tab’s icon as notification tool | HelloWebApps

  24. Hi ,

    I am unable to set fevicon icons dynamically based on user.I have been set using javascript.But its not working on IE. Please help me as soon as possible.

    function SetLogo() { var link = document.createElement(‘link’); link.type = ‘image/x-icon’; link.rel = ‘shortcut icon’; link.href = ‘Images/Cart2.ico’; document.getElementsByTagName(‘head’)[0].appendChild(link); }

    Its Very urgent.

    Thanks, Reena.

  25. Pingback: Creating favicon icons « Content: Forum » Wiki » Blog

  26. Pingback: The Page Visibility API | Sam Dutton’s blog

  27. Pingback: Announcing Faviconist