Favicons animés en pratique : faire bouger un onglet de navigateur (avec démo en direct)
Vous avez probablement remarqué quelque chose bouger en haut de cet onglet pendant que vous lisez. C'est un favicon animé : la même astuce que celle utilisée par Gmail pour le compteur de nouveaux messages et par Discord pour ses pastilles de notification, sauf que le vôtre peut faire à peu près tout ce que vous savez dessiner sur un canvas.
Cet article inclut une démo avec laquelle vous pouvez jouer. Cliquez sur un bouton, regardez votre vrai onglet de navigateur changer. Pas de capture d'écran, pas de vidéo embarquée — le favicon que vous voyez là tout de suite, c'est la démo.
Pourquoi animer un favicon ?
Honnêtement, la plupart des sites ne devraient pas. Une icône qui tourne dans chaque onglet devient vite agaçante, et ça consomme du CPU. Mais il y a quelques cas où c'est vraiment utile :
- États de chargement ou de traitement. Téléversements longs, exports, builds. Les utilisateurs changent d'onglet pendant qu'ils attendent, et un favicon animé leur dit que le travail est toujours en cours.
- Pastilles de notification. Nouveaux messages, mentions, alertes. Un point rouge qui pulse subtilement attire l'œil plus vite qu'un point statique.
- Flux de données en direct. Tableaux de trading, outils de monitoring, scores sportifs — partout où le titre de l'onglet ne suffit pas.
- Moments de marque. Un cadran festif, une célébration de jour de lancement. À utiliser avec parcimonie.
Si votre cas n'entre dans aucune de ces catégories, sautez l'animation. Un bon favicon SVG statique gagne déjà sur la taille, le mode sombre et l'autonomie.
Démo en direct : essayez tout de suite
Choisissez une animation. Puis regardez votre onglet — cette toute petite icône en haut, c'est ce qui est en train d'être redessiné.
Le vrai favicon fait 16×16 pixels. Difficile de voir les détails à cette taille, donc le cadre de gauche reflète le même canvas en ×8 avec mise à l'échelle au plus proche voisin.
Statut : au repos
Toute la boucle d'animation tourne désormais à l'intérieur d'un Web Worker, exactement comme favicon_worker.js dans la librairie Aymkdn. Toutes les 20 ms (50fps), le worker dessine sur son OffscreenCanvas, l'exporte via convertToBlob + FileReader et renvoie le data URL résultant à la page. Le thread principal ne fait qu'une seule chose : assigner cette chaîne à faviconLink.href. C'est pour ça que l'icône bouge maintenant aussi fluidement que sur la démo GitHub.
Envie de voir ce pattern dans un vrai produit ? Random Picker Wheel utilise un favicon animé qui suit sa roue qui tourne — une interface basée sur la rotation est l'un des rares cas où une icône animée colle vraiment au produit. Ouvrez la page, lancez la roue et regardez l'icône de l'onglet tourner avec elle.
Comment ça marche, vraiment
Trois étapes. C'est toute la technique :
// 1. Récupérer ou créer l'élément link du favicon
let link = document.querySelector('link[rel~="icon"]');
if (!link) {
link = document.createElement('link');
link.rel = 'icon';
document.head.appendChild(link);
}
// 2. Dessiner une frame sur un canvas masqué
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. Exporter le canvas en data URL et l'assigner au favicon
link.href = canvas.toDataURL('image/png');
requestAnimationFrame(drawFrame);
}
requestAnimationFrame(drawFrame);
Une quinzaine de lignes pour un point rouge qui pulse. Tout ce qui est plus sophistiqué consiste juste à dessiner d'autres formes sur le canvas.
La réalité du support navigateurs
C'est là que ça se gâte. Les navigateurs varient pas mal sur leur niveau d'agressivité à animer le favicon :
- Firefox : anime sans à-coups même quand l'onglet n'a pas le focus. C'est la référence.
- Chrome / Edge : animent quand l'onglet est actif. Quand on s'en éloigne,
requestAnimationFrameest limité à environ une fois par seconde, donc l'animation ralentit ou s'arrête. - Safari : anime quand l'onglet est au premier plan, mais met parfois plus de temps à rafraîchir l'icône. Ne comptez pas sur du fluide.
Pour les usages les plus courants — pastilles de notification et états de progression — ce n'est pas un problème de toute façon : ils n'ont pas besoin d'être rafraîchis plusieurs fois par seconde. Les spinners parfaitement fluides à 60fps sont surtout cosmétiques.
L'astuce du Web Worker (pour les onglets en arrière-plan)
Le bouton "Bascule façon GitHub" plus haut est un portage direct de l'animation phare de la librairie Aymkdn/animated-favicon : on garde l'icône A pendant 3 secondes, on comprime sa largeur jusqu'à zéro avec un cosinus, on bascule sur l'icône B et on la redéploie. Les calculs viennent directement de favicon_worker.js de la librairie : width = canvas.width * Math.abs(Math.cos(progress * Math.PI)), la deuxième image prenant le relais quand progress dépasse 0.5.
La librairie d'Aymkdn va un cran plus loin que ce qu'on fait ici : elle exécute cette boucle à l'intérieur d'un Web Worker. Les workers ne sont pas ralentis quand l'onglet passe en arrière-plan, donc l'animation continue, et OffscreenCanvas permet au worker de produire les frames sans toucher au DOM.
Le motif ressemble plus ou moins à ça :
// Côté page
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'] });
// Dans favicon-worker.js
const canvas = new OffscreenCanvas(16, 16);
const ctx = canvas.getContext('2d');
// ...dessiner une frame...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);
Ça vaut le coup si votre application est du genre que les utilisateurs gardent dans un onglet en arrière-plan : clients de chat, tableaux de build, outils de monitoring. Sinon la version sur le thread principal est plus simple et fait le job.
Quelques détails à connaître
Utilisez 16×16 ou 32×32, pas plus. Le favicon est rendu tout petit de toute façon, et un canvas plus grand veut dire des data URL plus volumineux et plus de CPU par frame. 32×32 avec des pixels nets est le bon compromis.
Définissez le favicon en PNG, pas en ICO. canvas.toDataURL('image/png') est la seule chose qui fonctionne de manière fiable. N'essayez pas d'encoder de l'ICO à la main.
Restaurez le favicon original quand vous arrêtez. Sauvegardez link.href avant de démarrer l'animation et rétablissez-le sur beforeunload ou en fin d'opération. Les onglets qui restent avec une animation à moitié cassée après une navigation ont l'air bogués.
N'animez pas indéfiniment. Même un battement discret consomme de la batterie sur mobile. Arrêtez l'animation quand l'état de chargement se termine, quand l'utilisateur lit la notification, ou quand l'onglet perd le focus.
Sautez ça pour les cas simples. Si vous voulez juste afficher "1 message non lu", remplacez le favicon par une version statique avec un point rouge. Pas besoin d'animation. La plupart de ce que les gens font avec des favicons animés est exagéré.
Quand y avoir recours
Les favicons animés ont leur place quand :
- L'animation reflète un état réel auquel l'utilisateur tient (téléversement, traitement, nouveau message)
- La page est du genre à vivre dans un onglet en arrière-plan
- Une pastille statique ou un simple changement de titre d'onglet ne transmettrait pas la même info
Mauvais choix quand :
- C'est purement décoratif
- L'animation tourne pendant toute la durée de vie de l'onglet
- Vos utilisateurs sont sur Safari ou mobile, où ça fonctionne à peine
Récupérez la démo plus haut, transposez-la dans votre projet, échangez les couleurs et formes contre celles de votre marque, livrez. Le code source complet est dans cette page : Voir le code source, copier, adapter.
Références
- Aymkdn/animated-favicon sur GitHub — Librairie de favicon animé basée sur Web Worker qui continue à animer dans les onglets inactifs
- The Making of an Animated Favicon — CSS-Tricks — La marche à pied de Chris Coyier sur la technique canvas → favicon
- How to animate a favicon? — Stack Overflow — Le fil classique avec plusieurs approches et notes de support
- OffscreenCanvas — MDN — L'API qui rend possible le motif d'animation par Web Worker
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.