Os selos são usados para transmitir informações não urgentes ao usuário. Por exemplo, eles são usados para indicar o status de um app ou o número de itens não lidos. A maneira clássica de criar um selo de app é adicionar um número ao favicon. Em navegadores modernos, depois que um app é instalado, há uma maneira integrada de adicionar um selo ao ícone do app na barra de tarefas do sistema operacional.
A maneira moderna
Como usar o método navigator.setAppBadge()
O método navigator.setAppBadge() define um selo no ícone associado ao app instalado. O método usa um único argumento opcional, que é um número inteiro usado como o valor do selo. Definir o número como 0 limpa o selo do app. Não fornecer um argumento resulta em um selo genérico, geralmente exibido como um ponto colorido.
![]()
A maneira clássica
Como adicionar um número ao favicon
Se o app ainda não estiver instalado, você poderá adicionar um número ao favicon. Há muitas maneiras de fazer isso, por exemplo, desenhando o favicon dinamicamente em uma tela com as informações do selo adicionadas e exibindo-o como um URL de blob ou criando uma imagem SVG com as informações do selo como um URL de dados.
![]()
Aprimoramento progressivo
O snippet abaixo usa um elemento personalizado
<favicon-badge></favicon-badge>
que permite ao desenvolvedor definir declarativamente um selo no favicon especificado pelo atributo src
transmitindo um número inteiro ao atributo badge. Quando o usuário instala o aplicativo, o selo é "atualizado" para um selo nativo do sistema operacional.
import 'https://unpkg.com/favicon-badge@2.0.0/dist/FavIconBadge.js';
// DOM references.
const favicon = document.querySelector('favicon-badge');
const installButton = document.querySelector('button');
// Feature detection.
const supportsAppBadge = 'setAppBadge' in navigator;
let setAppBadge;
// For the demo simply set the badge between [0, 9].
let i = 0;
const getAppBadgeValue = () => {
if (i > 9) {
i = 0;
}
return i++;
};
// Set the badge on the favicon.
const setAppBadgeFavicon = (value) => {
favicon.badge = value;
};
// Set the native operating system badge.
const setAppBadgeNative = (value) => {
navigator.setAppBadge(value);
}
// If the app is installed and the Badging API is supported,
// set the badge on the native operating system. Else, fall
// back to the favicon.
if (
matchMedia('(display-mode: standalone)').matches &&
supportsAppBadge
) {
setAppBadge = setAppBadgeNative;
} else {
setAppBadge = setAppBadgeFavicon;
}
// Set a new badge every second.
setInterval(() => {
setAppBadge(getAppBadgeValue());
}, 1000);
// If installation is supported…
if ('BeforeInstallPromptEvent' in window) {
let installEvent = null;
const onInstall = () => {
// After installation, "upgrade" to the native operating system badge.
installButton.disabled = true;
installEvent = null;
if (supportsAppBadge) {
favicon.badge = false;
setAppBadge = setAppBadgeNative;
}
};
// …listen for the `beforeinstallprompt` event.
window.addEventListener('beforeinstallprompt', (event) => {
event.preventDefault();
installEvent = event;
installButton.disabled = false;
});
// Deal with installation.
installButton.addEventListener('click', async () => {
if (!installEvent) {
return;
}
installEvent.prompt();
const result = await installEvent.userChoice;
if (result.outcome === 'accepted') {
onInstall();
}
});
// Listen for the `appinstalled` in case the user installs the app manually.
window.addEventListener('appinstalled', (event) => {
onInstall();
});
}
Leitura adicional
Demonstração
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="manifest" href="manifest.json" />
<title>How to create an app badge</title>
<link rel="stylesheet" href="style.css" />
<!-- TODO: Devsite - Removed inline handlers -->
<!-- <script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
const registration = await navigator.serviceWorker.register(
'sw.js',
);
console.log(
'Service worker registered for scope',
registration.scope,
);
});
}
</script>
<script src="script.js" type="module"></script> -->
</head>
<body>
<h1>How to create an app badge</h1>
<ol>
<li>
Watch the favicon. You should see a counter that updates each second
integrated into the favicon.
<img
src="../favicon.png"
style="width: 250px; height: auto"
width="528"
height="74"
alt="Favicon with counter."
/>
</li>
<li>
Install the app by clicking the button below. After the installation,
the button is disabled.
<p>
<button disabled type="button">Install</button>
</p>
</li>
<li>
Watch the app icon in your operating system's task bar. You should see a
counter that updates each second as an app badge.
<img
src="../app-badge.png"
style="width: 80px; height: auto"
width="282"
height="388"
alt="App badge with counter."
/>
</li>
</ol>
<favicon-badge src="../favicon.svg" textColor="#fff" badge="" />
</body>
</html>CSS
html {
box-sizing: border-box;
font-family: system-ui, sans-serif;
color-scheme: dark light;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin: 1rem;
}
img {
height: auto;
max-width: 100%;
display: block;
}
JS
import 'https://unpkg.com/favicon-badge@2.0.0/dist/FavIconBadge.js';
// The `` custom element.
const favicon = document.querySelector('favicon-badge');
// The install button.
const installButton = document.querySelector('button');
// Feature detection.
const supportsAppBadge = 'setAppBadge' in navigator;
// This function will either set the favicon or the native
// app badge. The implementation is dynamically changed at runtime.
let setAppBadge;
// Variable for the counter.
let i = 0;
// Returns a value between 0 and 9.
const getAppBadgeValue = () => {
if (i > 9) {
i = 0;
}
return i++;
};
// Function to set a favicon badge.
const setAppBadgeFavicon = (value) => {
favicon.badge = value;
};
// Function to set a native app badge.
const setAppBadgeNative = (value) => {
navigator.setAppBadge(value);
}
// If the app is installed and native app badges are supported,
// use the native app badge.
if (
matchMedia('(display-mode: standalone)').matches &&
supportsAppBadge
) {
setAppBadge = setAppBadgeNative;
// In all other cases (i.e., if the app is not installed or native
// app badges are not supported), use the favicon badge.
} else {
setAppBadge = setAppBadgeFavicon;
}
// Update the badge every second.
setInterval(() => {
setAppBadge(getAppBadgeValue());
}, 1000);
// Only relevant for browsers that support installation.
if ('BeforeInstallPromptEvent' in window) {
// Variable to stash the `BeforeInstallPromptEvent`.
let installEvent = null;
// Function that will be run when the app is installed.
const onInstall = () => {
// Disable the install button.
installButton.disabled = true;
// No longer needed.
installEvent = null;
if (supportsAppBadge) {
// Remove the favicon badge.
favicon.badge = false;
// Switch the implementation so it uses the native
// app badge.
setAppBadge = setAppBadgeNative;
}
};
window.addEventListener('beforeinstallprompt', (event) => {
// Do not show the install prompt quite yet.
event.preventDefault();
// Stash the `BeforeInstallPromptEvent` for later.
installEvent = event;
// Enable the install button.
installButton.disabled = false;
});
installButton.addEventListener('click', async () => {
// If there is no stashed `BeforeInstallPromptEvent`, return.
if (!installEvent) {
return;
}
// Use the stashed `BeforeInstallPromptEvent` to prompt the user.
installEvent.prompt();
const result = await installEvent.userChoice;
// If the user installs the app, run `onInstall()`.
if (result.outcome === 'accepted') {
onInstall();
}
});
// The user can decide to ignore the install button
// and just use the browser prompt directly. In this case
// likewise run `onInstall()`.
window.addEventListener('appinstalled', (event) => {
onInstall();
});
}