Favicon & App Icon Tools検証作成
基礎
デザイン

動的 favicon: バッジやリアルタイムのステータスを表示する

· 6 min read

ブラウザのタブに表示されるあの赤いバッジは、favicon が再描画されているだけです。ビルドステップなしで実現する方法を紹介します。

なぜ GIF をそのまま使わないのか?

アニメーション GIF を favicon に設定することはできますが、サポートはまちまちです。Firefox はアニメーションさせます。Safari は最初のフレームだけを表示します。Chrome の挙動はバージョンによって変わってきました。装飾には十分ですが、実行時に GIF の表示内容を変えられないため、リアルタイムのバッジには不向きなツールです。

タブが開いている間に更新される件数やステータスには、JavaScript で画像を再描画する必要があります。canvas なら実際のピクセルバッファが手に入り、そこに描画して data URI として favicon のリンクに渡せます。

仕組み

  1. 1

    ベースとなるアイコンを読み込む

    通常の favicon 画像を小さな canvas、たいていは 32x32 に描画します。これはバッジを付けるものが何もないときにユーザーが目にするアイコンです。

  2. 2

    上からバッジを描画する

    件数があるときは、隅に小さな塗りつぶしの円を描き、その中に数字を描画します。32 ピクセルでも読めるように高コントラストを保ちましょう。

  3. 3

    favicon の href を差し替える

    favicon リンクの href を canvas の出力に設定します。ブラウザは新しい画像でタブをすぐに再描画します。

  4. 4

    変化のたびに更新する

    件数が変わるたびに描画と差し替えを再実行し、ゼロになったらプレーンなアイコンを描き直します。

差し替えを素の JavaScript で

function setFaviconBadge(count) {
  const canvas = document.createElement("canvas");
  canvas.width = 32;
  canvas.height = 32;
  const ctx = canvas.getContext("2d");

  // draw your base icon first (an <img> you preloaded)
  ctx.drawImage(baseIcon, 0, 0, 32, 32);

  if (count > 0) {
    ctx.fillStyle = "#e5484d";
    ctx.beginPath();
    ctx.arc(23, 9, 9, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#ffffff";
    ctx.font = "bold 12px sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(count > 9 ? "9+" : String(count), 23, 10);
  }

  let link = document.querySelector("link[rel~='icon']");
  if (!link) {
    link = document.createElement("link");
    link.rel = "icon";
    document.head.appendChild(link);
  }
  link.href = canvas.toDataURL("image/png");
}

baseIcon は一度読み込んだ Image です。数字が変わるたびに setFaviconBadge(unread) を呼び出します。2 桁でも読めるよう、表示は 9+ で頭打ちにします。

よくある質問

ブラウザのタブに未読件数を表示するには?

アイコンと、数字入りのバッジを canvas に描画し、favicon リンクの href を canvas.toDataURL() に設定します。件数が変わるたびに再実行してください。通常の Web ページ向けに、タブ用の専用バッジ API はありません。

アニメーション GIF を favicon に使えますか?

使えますが、サポートは一貫していません。Firefox はアニメーションさせ、Safari は最初のフレームを表示し、Chrome はまちまちです。更新されるリアルタイムのバッジには、canvas を使って href を差し替えてください。

動的 favicon はパフォーマンスを損ないますか?

いいえ。32x32 の canvas への描画と data URI の設定は軽い処理です。タイマーではなく値が変わったときだけ描き直せば、コストは気になりません。

Keep reading