Favicon animate: fai muovere la scheda del browser (con demo dal vivo)
Probabilmente, mentre leggevi, hai notato qualcosa muoversi in cima a questa scheda. È una favicon animata — lo stesso trucco che Gmail usa per il contatore delle nuove email e Discord per i puntini di notifica, solo che la tua può fare praticamente qualunque cosa tu sappia disegnare su un canvas.
Questo articolo include una demo dal vivo con cui giocare. Clicca un pulsante, guarda la scheda del tuo browser cambiare davvero. Niente screenshot, niente video incorporati — la favicon che stai guardando in questo momento diventa la demo.
Perché animare una favicon?
Onestamente, la maggior parte dei siti non dovrebbe. Un'icona che gira in ogni scheda diventa fastidiosa in fretta e mangia CPU. Ma ci sono casi in cui è davvero utile:
- Stati di caricamento o elaborazione. Upload, export o build lunghi. Gli utenti cambiano scheda mentre aspettano e una favicon animata gli dice che il lavoro sta ancora andando avanti.
- Badge di notifica. Nuovi messaggi, menzioni, alert. Un puntino rosso che pulsa con discrezione si nota più in fretta di uno statico.
- Feed di dati live. Dashboard di trading, tool di monitoraggio, risultati sportivi — ovunque il titolo della scheda non basti.
- Momenti di brand. Uno spinner per le festività, una celebrazione del giorno del lancio. Da usare con parsimonia.
Se il tuo caso non rientra in questi, lascia perdere l'animazione. Una buona favicon SVG statica vince già su dimensione del file, dark mode e durata della batteria.
Demo dal vivo: provala adesso
Scegli un'animazione. Poi guarda la scheda del browser — l'icona piccolina lassù è proprio quella che viene ridisegnata.
La favicon vera è di 16×16 pixel. A quella dimensione i dettagli si vedono male, perciò il riquadro a sinistra rispecchia lo stesso canvas a 8× con scaling nearest-neighbor.
Stato: in attesa
Il loop di animazione ora gira interamente dentro un Web Worker, esattamente come favicon_worker.js nella libreria Aymkdn. Ogni 20 ms (50 fps) il worker disegna sul suo OffscreenCanvas, lo esporta tramite convertToBlob + FileReader e rimanda alla pagina il data URL ottenuto. Il main thread fa solo una cosa: assegna quella stringa a faviconLink.href. Per questo l'icona ora si muove con la stessa fluidità della demo di GitHub.
Vuoi vedere questo pattern in un prodotto reale? Random Picker Wheel usa una favicon animata che segue la sua ruota che gira — un'interfaccia basata sulla rotazione è uno dei pochi casi in cui un'icona in movimento si sposa davvero con il prodotto. Apri la pagina, fai girare la ruota e osserva l'icona della scheda girare insieme.
Come funziona davvero
Tre passi. È tutta qui la tecnica:
// 1. Recupera o crea l'elemento link della favicon
let link = document.querySelector('link[rel~="icon"]');
if (!link) {
link = document.createElement('link');
link.rel = 'icon';
document.head.appendChild(link);
}
// 2. Disegna un frame su un canvas nascosto
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. Esporta il canvas come data URL e assegnalo alla favicon
link.href = canvas.toDataURL('image/png');
requestAnimationFrame(drawFrame);
}
requestAnimationFrame(drawFrame);
Più o meno 15 righe per un puntino pulsante funzionante. Tutto ciò che è più sofisticato è solo disegnare forme diverse sullo stesso canvas.
La realtà del supporto browser
Qui la situazione si fa scomoda. I browser variano parecchio nel modo in cui animano la favicon:
- Firefox: anima fluido anche quando la scheda non ha il focus. È lo standard di riferimento.
- Chrome / Edge: animano mentre la scheda è attiva. Quando passi a un'altra scheda,
requestAnimationFrameviene throttlato a circa una volta al secondo, quindi l'animazione rallenta o si ferma. - Safari: anima quando è in focus ma a volte aggiorna l'icona solo a intervalli lenti. Non aspettarti movimenti fluidi.
In realtà va bene così per gli usi più comuni: i puntini di notifica e gli stati di progresso devono aggiornarsi al massimo ogni secondo. Spinner fluidi a 60 fps sono perlopiù estetica.
Il trucco del Web Worker (per le schede in background)
Il pulsante "Flip stile GitHub" qui sopra è un porting diretto dell'animazione caratteristica della libreria Aymkdn/animated-favicon: tieni l'icona A per 3 secondi, comprimi la sua larghezza con un coseno fino a zero, scambia con l'icona B, poi riallargala. La matematica viene direttamente da favicon_worker.js della libreria — width = canvas.width * Math.abs(Math.cos(progress * Math.PI)), con la seconda immagine che subentra non appena progress supera 0,5.
La libreria di Aymkdn fa un passo in più rispetto a noi: esegue quel loop dentro un Web Worker. I worker non vengono throttlati quando la scheda è in background, quindi l'animazione continua, e OffscreenCanvas permette al worker di renderizzare i frame senza toccare il DOM.
Lo schema è più o meno così:
// Nella tua 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');
// ...disegna un frame...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);
Vale la pena se la tua app è del tipo che gli utenti parcheggiano in una scheda di sfondo — chat, dashboard di build, tool di monitoraggio. Altrimenti la versione sul main thread è più semplice e basta e avanza.
Un paio di cose che vale la pena sapere
Usa 16×16 o 32×32, non più grande. La favicon viene comunque renderizzata piccola, e canvas più grandi significano data URL più pesanti e più CPU per frame. 32×32 con pixel netti è il punto giusto.
Imposta la favicon come PNG, non ICO. canvas.toDataURL('image/png') è l'unica cosa che funziona davvero. Non provare a codificare l'ICO a mano.
Ripristina la favicon originale quando ti fermi. Salva link.href prima di iniziare l'animazione e rimettilo a posto al beforeunload o quando l'operazione finisce. Le schede che continuano a mostrare un'animazione monca dopo la navigazione sembrano buggate.
Non animare in eterno. Anche una pulsazione discreta consuma batteria sul mobile. Ferma l'animazione quando lo stato di caricamento finisce, quando l'utente legge la notifica o quando la scheda perde il focus.
Salta tutto per i casi semplici. Se vuoi solo mostrare "1 messaggio non letto", cambia la favicon con una versione statica con il pallino rosso. Niente animazione. Buona parte di ciò per cui si usano le favicon animate è eccessivo.
Quando ricorrere a questa tecnica
Le favicon animate calzano bene quando:
- L'animazione riflette uno stato reale che interessa l'utente (caricamento, elaborazione, nuovo messaggio)
- La pagina è di quelle che vivono in una scheda di sfondo
- Un badge statico o un semplice cambio di titolo della scheda non comunicherebbe la stessa cosa
Calzano male quando:
- È solo decorazione
- L'animazione gira per tutto il tempo in cui la scheda è aperta
- Stai puntando utenti su Safari o mobile, dove funziona a malapena
Porta la demo qui sopra nel tuo progetto, scambia i colori e le forme con quelli del tuo brand e mandalo in produzione. Il sorgente completo è proprio qui in questa pagina — view source, copia, adatta.
Riferimenti
- Aymkdn/animated-favicon su GitHub — libreria di favicon animate basata su Web Worker che continua ad animare anche nelle schede inattive
- The Making of an Animated Favicon — CSS-Tricks — la spiegazione di Chris Coyier della tecnica canvas-to-favicon
- How to animate a favicon? — Stack Overflow — il thread classico con vari approcci e note sul supporto browser
- OffscreenCanvas — MDN — l'API che rende possibile il pattern di animazione in 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.