Animerade favicons: få webbläsarflikens ikon att röra på sig (med live-demo)

Favicon.im

Du har förmodligen sett något röra sig högst upp i den här fliken medan du läste. Det är en animerad favicon — samma trick som Gmail använder för att räkna nya mejl och Discord för notisprickar, fast din kan göra i stort sett vad som helst som du kan rita på en canvas.

Den här artikeln innehåller en live-demo som du kan peta på. Klicka på en knapp och se din riktiga webbläsarflik förändras. Inga skärmdumpar, inga inbäddade videor — favicon:en du tittar på just nu blir demon.

Varför animera en favicon överhuvudtaget?

Ärligt talat borde de flesta webbplatser låta bli. En snurrande ikon i varje flik blir tröttsam fort, och slukar CPU. Men det finns några fall där det faktiskt är användbart:

  • Laddnings- eller bearbetningstillstånd. Långa uppladdningar, exporter eller byggen. Användare byter flik medan de väntar, och en animerad favicon säger att jobbet fortfarande pågår.
  • Notisbadgar. Nya meddelanden, omnämnanden, larm. En röd prick som pulserar diskret märks snabbare än en statisk.
  • Live-data. Trading-dashboards, övervakningsverktyg, sportresultat — överallt där fliktiteln inte räcker.
  • Brandtillfällen. En högtidsspinner, en lanseringsdag. Använd sparsamt.

Om ditt fall inte är något av dessa — strunta i animationen. En bra statisk SVG-favicon vinner redan på filstorlek, dark mode och batteritid.

Live-demo: testa direkt

Välj en animation. Titta sedan på din webbläsarflik — den lilla ikonen däruppe är det som ritas om.

8× inzoomad förhandsvisning

Den riktiga favicon:en är 16×16 pixlar. Detaljer är svåra att se i den storleken, så rutan till vänster speglar samma canvas i 8× med nearest-neighbor-skalning.

Status: vilande

Animationsloopen kör nu helt inuti en Web Worker, precis som favicon_worker.js i Aymkdn-biblioteket. Var 20:e ms (50 fps) ritar workern på sin OffscreenCanvas, exporterar via convertToBlob + FileReader och skickar tillbaka data-URL:en till sidan. Huvudtråden gör en enda sak: tilldelar strängen till faviconLink.href. Det är därför ikonen nu rör sig lika mjukt som GitHub-demon.

Vill du se mönstret i en riktig produkt? Random Picker Wheel använder en animerad favicon som följer det snurrande hjulet — ett rotationsbaserat gränssnitt är ett av de få fall där en rörlig ikon verkligen passar produkten. Öppna sidan, snurra på hjulet och se hur flikens ikon snurrar med.

Hur det egentligen fungerar

Tre steg. Det är hela tekniken:

// 1. Hämta eller skapa favicon-link-elementet
let link = document.querySelector('link[rel~="icon"]');
if (!link) {
  link = document.createElement('link');
  link.rel = 'icon';
  document.head.appendChild(link);
}

// 2. Rita en bildruta på en dold 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. Exportera canvasen till data-URL och tilldela favicon:en
  link.href = canvas.toDataURL('image/png');

  requestAnimationFrame(drawFrame);
}

requestAnimationFrame(drawFrame);

Ungefär 15 rader för en fungerande pulserande prick. Allt mer avancerat är bara att rita andra former på samma canvas.

Verkligheten kring browserstöd

Här blir det rörigt. Browsers skiljer sig en hel del i hur aggressivt de animerar favicon:

  • Firefox: animerar mjukt även när fliken inte har fokus. Guldstandarden.
  • Chrome / Edge: animerar när fliken är aktiv. Byter du flik bromsar requestAnimationFrame ned till ungefär en gång per sekund, så animationen saktar in eller pausar.
  • Safari: animerar i fokus men uppdaterar ikonen ibland bara i sega intervall. Räkna inte med mjuk rörelse.

Det funkar faktiskt fint för de vanligaste fallen — notisprickar och förloppslägen behöver ändå bara uppdatera ungefär en gång per sekund. Mjuka 60 fps-spinners är mest kosmetiska.

Web Worker-tricket (för bakgrundsflikar)

Knappen "GitHub-stil flip" ovan är en direkt port av signaturanimationen i biblioteket Aymkdn/animated-favicon: håll ikon A i 3 sekunder, komprimera bredden med cosinus ner till noll, byt till ikon B och bred ut den igen. Matematiken kommer rakt från bibliotekets favicon_worker.jswidth = canvas.width * Math.abs(Math.cos(progress * Math.PI)), där den andra bilden tar över så fort progress passerar 0,5.

Aymkdns bibliotek går ett steg längre än vad vi gör här: det kör loopen i en Web Worker. Workers strypts inte när fliken hamnar i bakgrunden, så animationen fortsätter, och OffscreenCanvas låter workern rendera bildrutor utan att röra DOM:en.

Mönstret ser ungefär ut så här:

// I din sida
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'] });

// I favicon-worker.js
const canvas = new OffscreenCanvas(16, 16);
const ctx = canvas.getContext('2d');
// ...rita en bildruta...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);

Värt mödan om appen är den typen användare parkerar i en bakgrundsflik — chattklienter, bygg-dashboards, övervakningsverktyg. Annars är main thread-versionen enklare och tillräckligt bra.

Några saker värda att veta

Använd 16×16 eller 32×32, inte större. Favicon:en renderas pyttesmå ändå, och större canvas ger längre data-URL och mer CPU per bildruta. 32×32 med skarpa pixlar är sweet spot.

Sätt favicon som PNG, inte ICO. canvas.toDataURL('image/png') är det enda som funkar pålitligt. Försök inte koda ICO själv.

Återställ original-favicon när du stoppar. Spara link.href innan du börjar animera och återställ den i beforeunload eller när operationen är klar. Flikar som fortsätter visa en halvtrasig animation efter navigering ser buggiga ut.

Animera inte i evighet. Även en diskret puls drar mobilbatteri. Stoppa animationen när laddningen är klar, när användaren har läst notisen eller när fliken förlorar fokus.

Hoppa över för enkla fall. Vill du bara visa "1 oläst meddelande", byt till en statisk röd-pricks-favicon. Animation behövs inte. Det mesta folk använder animerade favicons till är overkill.

När det är värt det

Animerade favicons passar när:

  • Animationen speglar verklig status användaren bryr sig om (uppladdning, bearbetning, nytt meddelande)
  • Sidan är en sådan som lever i en bakgrundsflik
  • En statisk badge eller ändrad fliktitel inte skulle förmedla samma sak

De passar dåligt när:

  • Det bara är dekoration
  • Animationen körs hela tiden fliken är öppen
  • Du riktar dig mot Safari- och mobilanvändare där det knappt funkar

Bygg in demon ovan i ditt eget projekt, byt färger och former mot ditt brand, och släpp det. Hela källkoden står här på sidan — view source, kopiera, anpassa.

Referenser

  1. Aymkdn/animated-favicon på GitHub — Web Worker-baserat animerat favicon-bibliotek som fortsätter animera i inaktiva flikar
  2. The Making of an Animated Favicon — CSS-Tricks — Chris Coyiers genomgång av canvas-till-favicon-tekniken
  3. How to animate a favicon? — Stack Overflow — den klassiska tråden med flera angreppssätt och anteckningar om browserstöd
  4. OffscreenCanvas — MDN — API:t som gör Web Worker-animationsmönstret möjligt
Check Your Favicon

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.

15M+
Monthly Favicon Requests
100%
Free Forever