A favicon link is like any other element on your page - you can update the html using javascript and see the change instantly. Hereβs how you can do it and some ideas how it might be useful.
My own personal use case for this is probably the least useful. For this site logo I decided to replace one of the 'o's in my name with an emoji. I wanted it to change frequently as a user is viewing the page so I decided to use javascript to change the emoji every five seconds (and much faster when howering over the logo).
Having this as my logo I decided I'd like the favicon to also be the matching emoji - so it too would need to update every five seconds.
Below I'll show you how I did that and also some other ideas for more practical use-cases. But first I'd like to acknowledge some rather big UX shortcoming of my implementation. A favicon in the browser tab makes it much easier to find teh tab you are looking for at a glance. But if your favicon is constantly changing, that familiarity goes away. I've had this problem myself when building this site and struggling to find my own site. I wouldn't recommend such dramatic changes for most sites.
Also it's fair to say that some users may get annoyed by a frequently changing favicon. If it's conveying some useful info that is one thing, but if it's just to be whimsical, users may find the behavior obnoxious. This is going to depend on the type of content/aesthetic of your site and taste of your users, but it would probably be good to allow this to be disabled by teh user if you decide to do something similar. I considered using the prefers-reduced-motion media query on my site but I'm not sure whether this even qualifies as motion. This is something I'll need to do some user testing on.
Updating the favicon with javascript
It's actually really simple - you just need to update the href
attribute on the link
element. The easiest way to do that is to add an id to the link
:
<link rel="shortcut icon" id="favicon" href="/favicon.png">
And then with javascript you just update the href
attribute:
const favicon = document.querySelector('#favicon);
favicon.href = "/some-other-favicon.png";
Using SVG to generate favicons without files on the server
For my use-case I could have saved separate favicons for each emoji, but that seems like a lot of work. Luckily there are a few things that meant I didn't need to do this. First, many modern browsers now support SVG format for favicons:
<link rel="shortcut icon" href="/favicon.svg">
Second you can embed image data directly into a document using a data URI
(as usual CSS-Tricks has a great intro). Here's an example of a plain red circle used as a favicon:
<link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><circle cx=%2250%22 cy=%2250%22 r=%2250%22 fill=%22red%22/></svg>";
Note the "
elements are replaced with %22
for creating valid urls (this Google Maps doc explains URL encoding pretty well.
And a third benefit is that SVGs can include live text, so I don't need to convert my emoji to images. This is even better as it means the emoji will be correct to the platform rather than showing Mac OS versions on all devices:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<text y="85" font-size="90">π€―</text>
</svg>
Putting it all together
So to get my emoji favicon updating every five seconds I have this:
<link rel="icon" id="favicon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%2285%22 font-size=%2290%22>π</text></svg>">
function getRandomEmoji() {
const emoji = ["π", "π", "π", "π€£", "π", "π", "π", "π", "π§","π₯Έ", "π₯³", "π€―", "π·", "πββοΈ", "π¨βπ€", "π§βπ³", "π§βπ»", "π₯", "π£", "π", "π§Έ", "βοΈ", "π©", "π¦₯"];
const count = emoji.length;
const random = Math.floor(Math.random() * count);
return emoji[random];
}
const faviconString = (favicon) =>
`data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%2285%22 font-size=%2290%22>${favicon}</text></svg>`;
function getFaviconEl() {
return document.querySelector("#favicon");
}
function Logo(){
const [emoji, setEmoji] = useState(getRandomEmoji());
const [timer, setTimer] = useState(5000);
useEffect(() => {
const favicon = getFaviconEl();
const updateEmoji = () => {
const newEmoji = getRandomEmoji();
setEmoji(newEmoji);
favicon.href = faviconString(newEmoji);
};
updateEmoji();
const interval = setInterval(() => updateEmoji(), timer);
return () => {
clearInterval(interval);
};
}, [timer]);
return (
// Rest of component
)
}
I'm using React, but the concept would be more or less the same for any javascript implementation - use setInterval
to schedule a regular update.
Practical use-cases
Emoji favicons aren't likely to be a comon use-case (I hope, or my site's going to need updating sooner than I'd like π) but there are plenty of things you might want to update the favicon for.
The most obvious is for notifications. I've seen some sites add a little red dot when a notification on the site comes in (I think Bitbucket and maybe Trello have done this in the past). Maybe you're making a clock or calendar app - you could add a tiny clock or date. A photo app could show a small version of your current photo - instead of an SVG you'd need to base64 encode a png file. You could even add a tiny health bar or something for a game.
One thing to be aware of is update speed. When I set the interval to 100ms the favicon couldn't change fast enough. For me it's not a problem, but just be aware it does have limitations.
More limitations
Older browsers have no support or partial svg favicon support. Base64 png support would cover more browsers but then you'd need to generate pngs (maybe using canvas) and encoding to base64 in the browser.
Emojis in paricular as less predictable as it relies on the system font of the user. It's likely my emoji get cropped off badly in some browsers. Relying on images would overcome this but that's more effort than I was going for.