Animerte favicons: få nettleserfanen til å bevege seg (med live-demo)

Favicon.im

Du la sannsynligvis merke til at noe beveget seg øverst i denne fanen mens du leste. Det er en animert favicon — det samme trikset Gmail bruker for å telle nye e-poster og Discord bruker til varselsprikker, bortsett fra at din kan gjøre stort sett alt du kan tegne på et canvas.

Denne artikkelen inneholder en live-demo du kan tukle med. Klikk en knapp, se den faktiske nettleserfanen din endre seg. Ingen skjermbilder, ingen innebygde videoer — favicon:en du ser på akkurat nå blir demoen.

Hvorfor i det hele tatt animere en favicon?

Ærlig talt burde de fleste sider la være. Et roterende ikon i hver fane blir fort irriterende, og det spiser CPU. Men det finnes noen tilfeller hvor det faktisk er nyttig:

  • Lasting eller behandling. Lange opplastinger, eksporter eller bygg. Brukerne bytter fane mens de venter, og en animert favicon forteller dem at jobben fortsatt går.
  • Varsel-badges. Nye meldinger, omtaler, alarmer. En rød prikk som pulser diskret merkes raskere enn en statisk.
  • Live-data-feeder. Trading-dashbord, overvåkingsverktøy, sportsresultater — alle steder der fanetittelen ikke er nok.
  • Brand-øyeblikk. En høytidsspinner, en lanseringsdag. Bruk sparsommelig.

Hvis ditt tilfelle ikke er ett av disse, dropp animasjonen. En god statisk SVG-favicon vinner allerede på filstørrelse, mørk modus og batteritid.

Live-demo: prøv den nå

Velg en animasjon. Se så på nettleserfanen din — det bittelille ikonet der oppe er det som tegnes om.

8× zoomet forhåndsvisning

Den ekte favicon:en er 16×16 piksler. Detaljer er vanskelige å se i den størrelsen, så boksen til venstre speiler samme canvas i 8× med nearest-neighbor-skalering.

Status: hviler

Animasjons-loopen kjører nå helt inne i en Web Worker, akkurat som favicon_worker.js i Aymkdn-biblioteket. Hver 20. ms (50 fps) tegner workeren på sin OffscreenCanvas, eksporterer via convertToBlob + FileReader, og sender den resulterende data-URL-en tilbake til siden. Hovedtråden gjør én ting: tilordner den strengen til faviconLink.href. Det er derfor ikonet nå beveger seg like jevnt som GitHub-demoen.

Vil du se mønsteret i et ekte produkt? Random Picker Wheel bruker en animert favicon som følger det roterende hjulet — et rotasjonsbasert UI er ett av de få tilfellene der et bevegelig ikon faktisk passer produktet. Åpne siden, snurr hjulet, og se hvordan fanens ikon snurrer med.

Hvordan det egentlig fungerer

Tre steg. Hele teknikken:

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

// 2. Tegn et frame på et skjult 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. Eksporter canvas til data-URL og tilordne favicon:en
  link.href = canvas.toDataURL('image/png');

  requestAnimationFrame(drawFrame);
}

requestAnimationFrame(drawFrame);

Cirka 15 linjer for en fungerende pulserende prikk. Alt mer fancy er bare å tegne andre former på samme canvas.

Virkeligheten rundt nettleserstøtte

Her blir det stygt. Nettlesere varierer ganske mye i hvor aggressivt de animerer favicon:

  • Firefox: animerer jevnt selv når fanen ikke har fokus. Gullstandarden.
  • Chrome / Edge: animerer mens fanen er aktiv. Bytter du bort, struper requestAnimationFrame ned til omtrent én gang i sekundet, så animasjonen sløver eller pauses.
  • Safari: animerer i fokus, men oppdaterer ikonet av og til bare med trege intervaller. Ikke regn med jevn bevegelse.

Det er faktisk greit for de mest vanlige bruksområdene — varselsprikker og fremdriftstilstander trenger uansett bare å oppdatere omtrent én gang i sekundet. Jevne 60 fps-spinnere er stort sett kosmetiske.

Web Worker-trikset (for bakgrunnsfaner)

Knappen "GitHub-stil flip" over er en direkte port av signaturanimasjonen til biblioteket Aymkdn/animated-favicon: hold ikon A i 3 sekunder, komprimer bredden med cosinus til null, bytt til ikon B, og utvid det igjen. Matematikken er hentet rett fra bibliotekets favicon_worker.jswidth = canvas.width * Math.abs(Math.cos(progress * Math.PI)), der det andre bildet tar over når progress krysser 0,5.

Aymkdns bibliotek går ett skritt lenger enn det vi gjør her: det kjører den loopen inne i en Web Worker. Workers strupes ikke når fanen er i bakgrunnen, så animasjonen fortsetter, og OffscreenCanvas lar workeren rendre frames uten å berøre DOM-en.

Mønsteret ser omtrent slik ut:

// I siden din
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');
// ...tegn et frame...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);

Verdt bryet hvis appen din er den typen brukerne parkerer i en bakgrunnsfane — chatklienter, build-dashbord, overvåkingsverktøy. Ellers er hovedtråd-versjonen enklere og god nok.

Et par ting verdt å vite

Bruk 16×16 eller 32×32, ikke større. Favicon:en blir uansett rendret bittelite, og større canvas betyr lengre data-URL og mer CPU per frame. 32×32 med skarpe piksler er sweet spot.

Sett favicon som PNG, ikke ICO. canvas.toDataURL('image/png') er det eneste som virker pålitelig. Ikke prøv å kode ICO selv.

Gjenopprett original favicon når du stopper. Lagre link.href før animasjonen starter, og gjenopprett ved beforeunload eller når operasjonen er ferdig. Faner som fortsetter å vise en halvbrokken animasjon etter navigering virker buggy.

Ikke animer for evig. Selv en diskret puls drar mobilbatteri. Stopp animasjonen når lastetilstanden er ferdig, når brukeren har lest varselet, eller når fanen mister fokus.

Hopp over for enkle tilfeller. Vil du bare vise "1 ulest melding", bytt favicon til en statisk rød-prikk-versjon. Ingen animasjon nødvendig. Det meste folk bruker animerte favicons til, er overkill.

Når det er verdt det

Animerte favicons passer godt når:

  • Animasjonen reflekterer faktisk tilstand brukeren bryr seg om (laster opp, behandler, ny melding)
  • Siden er av typen som lever i en bakgrunnsfane
  • Et statisk badge eller bare en endret fanetittel ikke ville formidlet det samme

De passer dårlig når:

  • Det er bare dekorasjon
  • Animasjonen kjører hele tiden fanen er åpen
  • Du retter deg mot Safari- og mobilbrukere der det knapt fungerer

Bygg demoen over inn i ditt eget prosjekt, bytt farger og former til ditt brand, og send det. Hele kildekoden er rett her på siden — view source, kopier, tilpass.

Referanser

  1. Aymkdn/animated-favicon på GitHub — Web Worker-basert animert favicon-bibliotek som fortsetter å animere i inaktive faner
  2. The Making of an Animated Favicon — CSS-Tricks — Chris Coyiers gjennomgang av canvas-til-favicon-teknikken
  3. How to animate a favicon? — Stack Overflow — den klassiske tråden med flere tilnærminger og notater om nettleserstøtte
  4. OffscreenCanvas — MDN — API-et som gjør Web Worker-animasjonsmønsteret mulig
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