Geanimeerde favicons: laat je browsertabblad bewegen (met een live demo)
Tijdens het lezen heb je waarschijnlijk iets zien bewegen bovenin dit tabblad. Dat is een geanimeerde favicon — dezelfde truc die Gmail gebruikt voor het tellen van nieuwe mail en Discord voor notificatiestippen, alleen kan die van jou zo'n beetje alles wat je op een canvas kunt tekenen.
Dit artikel bevat een live demo waar je in mag prikken. Klik op een knop, kijk naar je echte browsertabblad en zie het veranderen. Geen screenshots, geen ingebedde video's — de favicon waar je nu naar kijkt is de demo.
Waarom überhaupt een favicon animeren?
Eerlijk gezegd zouden de meeste sites het beter laten. Een draaiend icoontje in elk tabblad wordt snel irritant en eet CPU. Maar er zijn een paar gevallen waarin het echt nuttig is:
- Laad- of verwerkingstoestanden. Lange uploads, exports of builds. Gebruikers wisselen ondertussen van tabblad, en een geanimeerde favicon laat zien dat het werk nog loopt.
- Notificatiebadges. Nieuwe berichten, mentions, alerts. Een rode stip die subtiel pulseert wordt sneller opgemerkt dan een statische.
- Live datafeeds. Trading dashboards, monitoringtools, sportuitslagen — overal waar de tabbladtitel niet genoeg is.
- Brandmomentjes. Een spinner met de feestdagen, een launch-day feestje. Spaarzaam gebruiken.
Past jouw situatie hier niet bij, sla de animatie dan over. Een goede statische SVG-favicon wint sowieso al op bestandsgrootte, dark mode en accuduur.
Live demo: probeer het nu
Kies een animatie. Kijk dan naar je browsertabblad — dat piepkleine icoontje bovenin is wat opnieuw getekend wordt.
De echte favicon is 16×16 pixels. Op dat formaat zie je nauwelijks details, dus het kader links spiegelt hetzelfde canvas op 8× met nearest-neighbor scaling.
Status: inactief
De animatielus draait nu volledig binnen een Web Worker, net als favicon_worker.js in de Aymkdn-bibliotheek. Elke 20 ms (50 fps) tekent de worker op zijn OffscreenCanvas, exporteert hij dat via convertToBlob + FileReader en stuurt hij de resulterende data URL terug naar de pagina. De main thread doet maar één ding: die string toewijzen aan faviconLink.href. Daarom beweegt het icoon nu net zo soepel als in de GitHub-demo.
Wil je dit patroon in een echt product zien? Random Picker Wheel gebruikt een geanimeerde favicon die meedraait met het rad — een rotatie-gebaseerde UI is een van de weinige gevallen waarin een bewegend icoon echt bij het product past. Open de pagina, draai aan het rad en zie hoe het tabblad-icoon gewoon meedraait.
Hoe het echt werkt
Drie stappen. De hele techniek:
// 1. Haal het favicon-link-element op of maak het aan
let link = document.querySelector('link[rel~="icon"]');
if (!link) {
link = document.createElement('link');
link.rel = 'icon';
document.head.appendChild(link);
}
// 2. Teken een frame op een verborgen canvas
const canvas = document.createElement('canvas');
canvas.width = 32;
canvas.height = 32;
const ctx = canvas.getContext('2d');
function drawFrame(t) {
const scale = 0.5 + 0.5 * Math.abs(Math.sin(t / 400));
ctx.clearRect(0, 0, 32, 32);
ctx.fillStyle = '#ef4444';
ctx.beginPath();
ctx.arc(16, 16, 14 * scale, 0, Math.PI * 2);
ctx.fill();
// 3. Exporteer het canvas als data URL en zet het op de favicon
link.href = canvas.toDataURL('image/png');
requestAnimationFrame(drawFrame);
}
requestAnimationFrame(drawFrame);
Ongeveer 15 regels voor een werkende pulserende stip. Alles wat fancier is, is gewoon andere vormen op het canvas tekenen.
De realiteit van browserondersteuning
Hier wordt het lelijk. Browsers verschillen behoorlijk in hoe agressief ze de favicon animeren:
- Firefox: animeert soepel zelfs als het tabblad geen focus heeft. De gouden standaard.
- Chrome / Edge: animeren als het tabblad actief is. Wissel je weg, dan throttlet
requestAnimationFramenaar zo'n keer per seconde, dus de animatie vertraagt of pauzeert. - Safari: animeert in focus, maar werkt het icoon soms alleen op trage intervallen bij. Reken niet op vloeiende beweging.
Voor de meest voorkomende gebruiken is dat eigenlijk prima — notificatiestippen en voortgangstoestanden hoeven sowieso maar elke seconde te updaten. Vloeiende 60fps-spinners zijn vooral cosmetisch.
De Web Worker-truc (voor achtergrondtabbladen)
De knop "GitHub-stijl flip" hierboven is een directe port van de signature-animatie van Aymkdn/animated-favicon: houd icoon A 3 seconden vast, druk de breedte met cosinus naar nul, wissel naar icoon B en zet hem weer breed. De wiskunde komt rechtstreeks uit de favicon_worker.js van de bibliotheek — width = canvas.width * Math.abs(Math.cos(progress * Math.PI)), waarbij het tweede beeld het overneemt zodra progress voorbij 0,5 komt.
De bibliotheek van Aymkdn gaat een stap verder dan wat wij hier doen: hij draait die lus binnen een Web Worker. Workers worden niet getrottlet als het tabblad op de achtergrond staat, dus de animatie loopt door, en OffscreenCanvas laat de worker frames renderen zonder de DOM aan te raken.
Het patroon ziet er ongeveer zo uit:
// In je pagina
const worker = new Worker('favicon-worker.js');
worker.onmessage = (e) => {
if (e.data.type === 'updateFavicon') {
document.querySelector('link[rel~="icon"]').href = e.data.dataUrl;
}
};
worker.postMessage({ type: 'init', images: ['icon-a.png', 'icon-b.png'] });
// In favicon-worker.js
const canvas = new OffscreenCanvas(16, 16);
const ctx = canvas.getContext('2d');
// ...teken een frame...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);
De moeite waard als je app het type is dat gebruikers in een achtergrondtabblad parkeren — chatclients, build-dashboards, monitoringtools. Anders is de versie op de main thread eenvoudiger en goed genoeg.
Een paar dingen om te weten
Gebruik 16×16 of 32×32, niet groter. De favicon wordt sowieso piepklein gerenderd, en grotere canvases betekenen langere data URL's en meer CPU per frame. 32×32 met scherpe pixels is de sweet spot.
Stel de favicon in als PNG, niet ICO. canvas.toDataURL('image/png') is het enige wat betrouwbaar werkt. Probeer ICO niet zelf te coderen.
Zet de oorspronkelijke favicon terug als je stopt. Sla link.href op vóór je begint te animeren en herstel hem in beforeunload of zodra de operatie klaar is. Tabs die na navigatie nog een halfgebroken animatie laten zien voelen buggy aan.
Animeer niet eindeloos. Zelfs een subtiele puls trekt mobiele accu's leeg. Stop de animatie als de laadtoestand voorbij is, als de gebruiker de notificatie heeft gelezen of als het tabblad de focus verliest.
Sla het over voor simpele gevallen. Wil je alleen "1 ongelezen bericht" laten zien, schakel de favicon dan naar een statische rode-stip-versie. Geen animatie nodig. Het meeste waarvoor mensen geanimeerde favicons gebruiken is overkill.
Wanneer dit handig is
Geanimeerde favicons passen goed wanneer:
- De animatie echte status weerspiegelt waar de gebruiker om geeft (uploaden, verwerken, nieuw bericht)
- De pagina van het type is dat in een achtergrondtabblad leeft
- Een statische badge of alleen een gewijzigde tabbladtitel hetzelfde niet zou overbrengen
Ze passen slecht wanneer:
- Het puur decoratie is
- De animatie de hele tijd loopt dat het tabblad open is
- Je gebruikers op Safari en mobiel target, waar het amper werkt
Bouw de bovenstaande demo in je eigen project, ruil de kleuren en vormen voor je merk en deploy. De volledige broncode staat hier op deze pagina — view source, kopieer, pas aan.
Bronnen
- Aymkdn/animated-favicon op GitHub — een geanimeerde-favicon-bibliotheek op basis van Web Workers die ook in inactieve tabbladen blijft animeren
- The Making of an Animated Favicon — CSS-Tricks — Chris Coyiers walkthrough van de canvas-naar-favicon-techniek
- How to animate a favicon? — Stack Overflow — de klassieke thread met meerdere benaderingen en notities over browserondersteuning
- OffscreenCanvas — MDN — de API die het Web Worker-animatiepatroon mogelijk maakt
Use favicon.im to quickly check if your favicon is configured correctly. Our free tool ensures your website's favicon displays properly across all browsers and devices.
Free Public Service
Favicon.im is a completely free public service trusted by developers worldwide.