Animowane favicony: spraw, by ikona karty przeglądarki ożyła (z demem na żywo)
Czytając, pewnie zauważyłeś coś poruszającego się na górze tej karty. To animowany favicon — ta sama sztuczka, której Gmail używa do liczenia nowych wiadomości, a Discord do kropek powiadomień, tylko że Twój może robić właściwie wszystko, co potrafisz narysować na canvasie.
Ten artykuł zawiera demo na żywo, w którym możesz pogrzebać. Kliknij przycisk i zobacz, jak prawdziwa karta Twojej przeglądarki naprawdę się zmienia. Żadnych zrzutów ekranu, żadnych wbudowanych filmów — favicon, na który teraz patrzysz, sam jest demem.
Po co w ogóle animować favicona?
Szczerze, większość stron nie powinna. Wirująca ikona w każdej karcie szybko zaczyna irytować i zjada CPU. Ale jest kilka przypadków, w których to naprawdę przydatne:
- Stany ładowania lub przetwarzania. Długie uploady, eksporty albo buildy. Użytkownicy przełączają karty podczas czekania, a animowany favicon mówi im, że robota wciąż trwa.
- Plakietki powiadomień. Nowe wiadomości, wzmianki, alerty. Czerwona kropka, która delikatnie pulsuje, jest szybciej zauważana niż statyczna.
- Strumienie danych na żywo. Pulpity tradingowe, narzędzia monitoringu, wyniki sportowe — wszędzie tam, gdzie sam tytuł karty nie wystarczy.
- Momenty brandowe. Świąteczny spinner, świętowanie dnia premiery. Używaj oszczędnie.
Jeżeli Twój przypadek nie pasuje do żadnego z powyższych, daruj sobie animację. Dobry statyczny favicon SVG i tak wygrywa pod kątem rozmiaru pliku, dark mode'u i baterii.
Demo na żywo: wypróbuj teraz
Wybierz animację. Potem spójrz na kartę przeglądarki — ta malutka ikona u góry to właśnie to, co jest przerysowywane.
Prawdziwy favicon ma 16×16 pikseli. W tym rozmiarze trudno dostrzec detale, więc kafelek po lewej odbija ten sam canvas w skali 8× ze skalowaniem nearest-neighbor.
Stan: bezczynny
Pętla animacji działa teraz w całości wewnątrz Web Workera, dokładnie jak favicon_worker.js w bibliotece Aymkdn. Co 20 ms (50 fps) worker rysuje na swoim OffscreenCanvas, eksportuje go przez convertToBlob + FileReader i wysyła powstały data URL z powrotem na stronę. Główny wątek robi tylko jedno: przypisuje ten string do faviconLink.href. Dlatego ikona porusza się teraz tak samo płynnie jak demo z GitHuba.
Chcesz zobaczyć ten pattern w prawdziwym produkcie? Random Picker Wheel wykorzystuje animowaną faviconę zsynchronizowaną z obracającym się kołem — UI oparty na rotacji to jeden z niewielu przypadków, w których ruchoma ikona naprawdę pasuje do produktu. Otwórz stronę, zakręć kołem i zobacz, jak ikona karty kręci się razem z nim.
Jak to naprawdę działa
Trzy kroki. Cała technika sprowadza się do tego:
// 1. Pobierz lub stwórz element link favicona
let link = document.querySelector('link[rel~="icon"]');
if (!link) {
link = document.createElement('link');
link.rel = 'icon';
document.head.appendChild(link);
}
// 2. Narysuj klatkę na ukrytym canvasie
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. Wyeksportuj canvas do data URL i przypisz favicona
link.href = canvas.toDataURL('image/png');
requestAnimationFrame(drawFrame);
}
requestAnimationFrame(drawFrame);
Mniej więcej 15 linijek dla działającej pulsującej kropki. Wszystko bardziej fancy to po prostu rysowanie innych kształtów na canvasie.
Rzeczywistość obsługi przeglądarek
Tu robi się brzydko. Przeglądarki różnią się sporo w tym, jak agresywnie animują favicona:
- Firefox: animuje płynnie nawet wtedy, gdy karta nie ma fokusa. Złoty standard.
- Chrome / Edge: animują, dopóki karta jest aktywna. Po przełączeniu
requestAnimationFrameschodzi do mniej więcej raz na sekundę, więc animacja zwalnia albo pauzuje. - Safari: animuje przy fokusie, ale czasem aktualizuje ikonę tylko z dużymi odstępami. Nie licz na płynny ruch.
Tak naprawdę to wystarcza dla najczęstszych zastosowań — kropki powiadomień i stany postępu i tak muszą się odświeżać co najwyżej raz na sekundę. Płynne spinnery 60 fps to głównie kosmetyka.
Sztuczka z Web Workerem (dla kart w tle)
Przycisk "Obrót w stylu GitHub" powyżej to bezpośredni port autorskiej animacji z biblioteki Aymkdn/animated-favicon: trzymaj ikonę A przez 3 sekundy, zwężaj jej szerokość cosinusem do zera, zamień na ikonę B i rozszerz z powrotem. Matematyka pochodzi prosto z favicon_worker.js biblioteki — width = canvas.width * Math.abs(Math.cos(progress * Math.PI)), a drugi obrazek przejmuje stery, gdy progress przekracza 0,5.
Biblioteka Aymkdna idzie krok dalej niż my: uruchamia tę pętlę w Web Workerze. Workery nie są throttlowane, kiedy karta jest w tle, więc animacja idzie dalej, a OffscreenCanvas pozwala workerowi renderować klatki bez dotykania DOM-u.
Wzorzec wygląda mniej więcej tak:
// W Twojej stronie
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'] });
// W favicon-worker.js
const canvas = new OffscreenCanvas(16, 16);
const ctx = canvas.getContext('2d');
// ...narysuj klatkę...
const blob = await canvas.convertToBlob();
const reader = new FileReader();
reader.onloadend = () => self.postMessage({ type: 'updateFavicon', dataUrl: reader.result });
reader.readAsDataURL(blob);
Warto, jeśli Twoja apka jest typu, który użytkownicy zostawiają na karcie w tle — czaty, dashboardy buildów, narzędzia monitoringu. W innych przypadkach wersja na głównym wątku jest prostsza i wystarczająco dobra.
Kilka rzeczy, które warto wiedzieć
Używaj 16×16 albo 32×32, nie większych rozmiarów. Favicon i tak renderuje się malutki, a większy canvas to dłuższy data URL i większe zużycie CPU na klatkę. 32×32 z ostrymi pikselami to złoty środek.
Ustawiaj favicona jako PNG, nie ICO. canvas.toDataURL('image/png') to jedyna rzecz, która działa niezawodnie. Nie próbuj kodować ICO ręcznie.
Przywróć oryginalnego favicona po zatrzymaniu. Zapisz link.href przed startem animacji i przywróć w beforeunload albo gdy operacja się skończy. Karty, które po nawigacji nadal pokazują pourwaną animację, wyglądają na zbugowane.
Nie animuj w nieskończoność. Nawet delikatny puls drenuje baterię na komórce. Zatrzymaj animację, gdy stan ładowania się skończy, użytkownik przeczyta powiadomienie albo karta straci fokus.
Daruj sobie przy prostych przypadkach. Jeśli chcesz tylko pokazać "1 nieprzeczytana wiadomość", zmień favicona na statyczną wersję z czerwoną kropką. Animacja niepotrzebna. Większość zastosowań animowanych favicon-ów to przerost formy nad treścią.
Kiedy po nią sięgać
Animowane favicony pasują, gdy:
- Animacja oddaje realny stan, na którym użytkownikowi zależy (upload, przetwarzanie, nowa wiadomość)
- Strona to taka, która siedzi w karcie w tle
- Statyczna plakietka albo zwykła zmiana tytułu karty nie przekazałyby tego samego
Pasują źle, gdy:
- To tylko ozdoba
- Animacja chodzi cały czas, gdy karta jest otwarta
- Celujesz w użytkowników Safari i mobilnych, gdzie ledwo działa
Wbij demo powyżej do swojego projektu, podmień kolory i kształty na brand i wypuść. Pełen kod źródłowy jest tu, na tej stronie — view source, kopiuj, dostosuj.
Bibliografia
- Aymkdn/animated-favicon na GitHub — biblioteka animowanych faviconów oparta o Web Workery, która animuje też w nieaktywnych kartach
- The Making of an Animated Favicon — CSS-Tricks — przewodnik Chrisa Coyiera po technice canvas-to-favicon
- How to animate a favicon? — Stack Overflow — klasyczny wątek z różnymi podejściami i notatkami o wsparciu w przeglądarkach
- OffscreenCanvas — MDN — API, które umożliwia wzorzec animacji w Web Workerze
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.