こなさんみんばんわ。

半年くらいマークアップと CSS だけでがんばってきた新しいロゴを SVG 化したついでに、大昔のロゴのままアップデートせずに放置していたファビコンと Web クリップ・アイコンもちゃんと作り直すことにしたのですが、あと数ヶ月ほどで登場する(はずの)Safari v26 にもサポートが入ることですし、この機会にファビコンもロゴと同じく SVG 化してみることにしました。

そんな訳でさっそくファビコン用の SVG ファイル(と、古いブラウザ向けの ICO ファイル1)を作成し、Safari v26 の β 版をインストールしてローカル環境で表示を確認してみたところ、あれ、なんかちゃんと SVG の方を使ってくれてないような…ていうか、どう見ても ICO の方を使ってる(´・_・`)2
調べてみますと Google Chrome も ICO ファイルの内容によっては SVG ではなく ICO の方を表示に使う場合があるようで、Safari も似たような感じなのかもしれません。

そこで、さまざまなパターンで複数の ICO ファビコンを作成し、それぞれを SVG ファビコンと同時に <link> 要素で rel="icon" 指定してはその挙動を各ブラウザで確認する…という地道な手法で、すべてのブラウザで確実に SVG ファビコンが使用されるパターンを探ってみることにしました。お前暇か。涙

注: この記事では Web クリップ・アイコン (apple-touch-icon) や PWA 用のアイコン指定に関しては触れておりません。またファビコン画像の作成方法や SVG → ICO への変換方法などに関しても触れません。

まずは今回の成果物をご覧ください(デモ)

Firefox Developer Edition(ダークテーマ)による、デモサイトのスクリーンショット

最初に、今回行った全テスト内容をまとめたデモサイトを作成しておきました。こちらをご確認いただいてから記事を読み進めていただきますと話が早いと思われます。

各テストページには ICO ファビコンの内容3sizes 属性の指定、そして各 Web ブラウザごとにどちらのファビコンが使用されるかの結果を記しております。よろしければさまざまなブラウザで各ページのタブに表示されるファビコンを実際に確認してみてください。

…とかいってもおそらく「はぁ? 忙しぃてそんなん全部やってられへんわ! アホちゃう?」という方が大半かと思いますので😭 そんな方のために #18 を除く全テスト結果をまとめた表を作っておきました! せめてこちらだけでも目を通していただけるとありがたいです。

テスト内容 Firefox Chrome Safari
マルチ・16, 32, 48・属性なし SVG ICO ICO
マルチ・16, 32, 48・属性あり(全列挙) SVG ICO ICO
マルチ・16, 32・属性なし SVG ICO ICO
マルチ・16, 32・属性あり(全列挙) SVG ICO ICO
マルチ・16, 48・属性なし SVG SVG * SVG
マルチ・16, 48・属性あり(全列挙) SVG SVG * SVG
マルチ・32, 48・属性なし SVG SVG * ICO
マルチ・32, 48・属性あり(全列挙) SVG SVG ICO
シングル・16・属性なし SVG SVG * SVG
シングル・16・属性あり SVG SVG SVG
シングル・32・属性なし SVG SVG * SVG
シングル・32・属性あり SVG SVG SVG
シングル・48・属性なし SVG SVG * SVG
シングル・48・属性あり SVG SVG SVG
マルチ・16, 32, 48・属性あり(16 のみ) SVG SVG ICO
マルチ・16, 32, 48・属性あり(32 のみ) SVG SVG ICO
マルチ・16, 32, 48・属性あり(48 のみ) SVG SVG ICO
各テストページを Firefox, Google Chrome, Safari で確認し、どちらのファビコンが表示されたかの結果をまとめた表。Chrome 列 で「SVG」となってる横の * 印は、表示には SVG が使用されるが ICO への HTTP リクエストも発生したことを示す

なお、データ作成のために当方で表示確認に使ったブラウザは次のとおりです:

  • Firefox Developer Edition 最新版(記事執筆時点 v143.0b5)
  • Google Chrome 最新版(同 v139.0.7258.155)
  • Safari 26.0 for macOS Sequoia(同 beta 5)

加えて macOS 版 Microsoft Edge でもいちおうチェックしておりますが、当然ながら結果は Chrome と一緒なのでデータは掲載してないです。あと Safari v26 のβ版を入れてない人は現行バージョンで見られるかと思いますが、こちらは SVG ファビコン非対応なので全テスト ICO ファビコンで表示されるだけであることを、念のため付け加えておきます。

テスト結果から見えてくる、ブラウザ別注意ポイント

さすがに 10 年も前から実装が入っている分、その改善度合いは他と比較して格段に進んでいるであろう Firefox はいずれのパターンにおいても SVG ファビコンを優先してくれますが、Chrome と Safari v26 についてはそういう訳でもないことが、テスト結果から分かります。

でもこうやってあらためてチェックしてみましたところ、どちらにも一定のルールがありそうなことは見て取れましたので、次項からブラウザ別にそのあたりをまとめていきたいと思います。

Google Chrome

まずは Chrome から。まぁ僕が書かなくてもすでに Web 上にはこの件について書かれたリソースがたくさん(腐るほど)ある訳ですが、おかげで新旧の情報が交錯しており、中にはちょっと今としては不正確な内容も含まれているように感じます。なので今回の実験結果もふまえまして「実際のところはどうなのか」を整理しておきましょう。

ICO がマルチアイコンの場合 SVG よりも ICO を優先する場合がある

Chrome は HTML の rel="icon" 指定に SVG と ICO の両方があり、かつ ICO ファイルが複数のサイズを含むマルチアイコンである場合には、ICO ファイルの方を優先的に使おうとするようです。これは必ずしも「マルチアイコンなら ICO を使う」という訳ではなく、その内容によっては使わない場合もある、ということです。

そしてその条件分岐については、今回のテスト結果から判断する限りおそらく ICO ファイルが 16x16 と 32x32 のアイコンを共に含む場合は ICO 使用・そうでなければ SVG 使用…ではないかと思われます。もっと別のサイズも含めて追加でテストをすれば、もしかするとそれを外れた結果が出るかもしれないので、はっきりこうだと断言するのは避けておきますが…

まぁその辺どうなるにせよ、SVG ファビコンを導入する以上 SVG の方を優先的に使用したいのであれば、ICO ファイルの方はシングルアイコンにしておくのがよさそうだ…というのは確かな結論になると思います。

sizes 属性が未指定だと、不要な場合でも ICO をリクエストする

また ICO がシングルアイコンの場合でも、その指定をする <link> タグに sizes 属性が未指定だと、実際にそれを使用する・しないに関わらず ICO ファイルに対して HTTP リクエストを発生させることを確認しております4

余計なリクエストだといえば余計ですが、もっともこれは Chrome が ICO ファイルを優先使用する場合がある以上、考えれば当然の処理であるといえます。だって sizes 属性が提供されてなければ、実際にフェッチしてみない限りどのサイズのアイコンが含まれているかが判断できないですからね。

逆にいえば sizes 属性の指定内容から優先使用できないファイルっぽいことが判断できれば、その ICO ファイルはリクエストしないということでもあります。それが分かるのが追加テストとして置いてある #15〜#17 ですね。ファイル自体はテスト #1〜#2 と同じ 3 サイズのマルチアイコンですが、sizes 属性に単値を指定することで ICO に対するリクエストが回避されました4

SVG ファビコンについて検索すると「Chrome が ICO ファイルを優先してしまうバグを回避するために sizes 属性を書こう!」などと書かれた記事がいくつかあったのですが、あくまでも ICO を使うかどうかを決めているのはそのファイル内容であって、sizes の指定はどちらかというと不要な HTTP リクエストを回避させるという理由の方が強いですね。

ちなみに、先に書いた条件からするとテスト #6 で sizes 属性から SVG が優先となることは明白だし、実際にも SVG が使用されるというのに、なぜ ICO へのリクエストが発生しているのかの理由は分かりません! 涙

Safari v26

SVG ファビコンの実装としては主要ブラウザの中で最後発となる Safari v26 です。重ね重ねになりますがテストを行ったのはβ版 (beta 5) です。よって正式版のリリースまでにまだ修正が入る可能性はなきにしもあらず…ということを付け加えておきます。

Chrome 同様マルチアイコン ICO を優先する場合がある

Safari も Chrome と同じく、ICO ファイルがマルチアイコンである場合は SVG よりも ICO ファイルの方を優先するのですが、ICO ファイルが 32x32 サイズのアイコンを含む場合に限られる…ようです。こちらもテスト条件を外れた場合の結果が分からないので断言はしないでおきますが、Chrome よりはちょっと条件が分かりやすいですかね。

ICO ファイルがシングルアイコンの場合は SVG の方が使用されるのは Chrome と一緒です。

sizes 属性の値で使用されるファイルが変わることはない

また Chrome とは違って sizes 属性の値がファイルの選択に影響を与えることはないので、先のテスト #15〜#17 のようにマルチアイコンに対して単値を指定しても、Safari が使用するファビコンは ICO ファイルのままです。これは、ICO ファイルをマルチアイコンのまま保ちつつもブラウザには SVG を優先させるためのハックとして sizes 属性に単値を指定する方法は、今後は使用できなくなることを意味します

まぁ個人的には sizes 属性にはちゃんとそのファイルが持つサイズを列挙しておくべきものだと思うし、こういう一致しない属性を書くような手法は気持ち悪いのでやらないのですが😅 そういうの別に平気だし今まで普通にやってたよ…という方がいらっしゃいましたら、Safari v26 の登場以降は使えなくなりますのでご注意下さい。変更するとすれば、ここはもう素直にシングルアイコンにするしかないように思います。

prefers-color-scheme に応じた配色切り替えには非対応

もうひとつ、こちらは SVG ファビコンそのものに関するものですね。SVG には <style> 要素を含むことができるので、そこに prefers-color-scheme メディア特性を用いた CSS の @media ルールなどを書くことで、システムやブラウザのテーマに応じた配色切り替え、いわゆるダークモード対応が可能なことは、ある程度 Web コンテンツ制作に精通されている方ならご存じかと思います。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="…">
  <style>
  /* `prefers-color-scheme` を使う、よく説明される手法 */
  @media (prefers-color-scheme: dark) {
    path { fill: #fff }
  }
  /* 最近のブラウザだけが対象でいいなら、もう `light-dark()` 関数でもいいような */
  :root {
    color-scheme: light dark;
  }
  path {
    fill: light-dark(#000, #fff);
  }
  </style>
  <!-- 後方互換性のため `path` などのプレゼンテーション属性には通常時の値(ライトモードでの色)を書いておくとよい、と思う -->
  <path d="…" fill="#000">
</svg>

このデモサイトの SVG ファビコンにもこの配色切り替えのためのコードが入れてあり、Firefox と Chrome ではブラウザのテーマカラー(ライト or ダーク)に対応して塗りつぶし色(黒 or 白)が変わります。またサイトの CSS にもダークモード対応が入れてあるので、見本として埋め込まれている SVG ファビコンの画像も、ブラウザタブのファビコン色と同一に変化するはずです。

しかし残念ながら Safari の SVG ファビコンはこの手法にまだ非対応で、常に通常時(ライトモード)の配色で表示されてしまいます。これはバグというより Safari の SVG 実装が追いついてないことによるもので、おそらく埋め込み要素が親要素の color-scheme を継承するという、割と新しめのドラフト仕様5が v26 でもまだ未実装なことに起因するものです。

じゃあダークモードでのファビコンの視認性どうなるん? という話ですが、こと Safari においてはそこまで問題にならないはずです。次の画像はダークモードのシステム上で、デモサイトのテストページを複数開いた状態の Safari v26 タブバーのスクリーンショットですが、ファビコンのバックに白い角丸の背景色が敷かれているのがお分かりいただけるかと思います。

画像: Safari ではテーマがダークモードでファビコンが透過背景かつメインカラーが暗い色の場合、画像の種別に関わらず白い角丸の背景色が敷かれる

この背景色はファビコンに元から付いているものではなくて、その画像が SVG でも ICO でもはたまた PNG でも、透過背景の画像の場合に Safari が自動で付与するものです。基本的にメインカラーが暗い色のファビコンには付与されるようで、そのままでも十分なコントラストが確保されているものはそのままであることが多いです。また最初から明るい背景色が付いているような画像にも付与されません6

まぁ制作者として、せっかく書いたコードがブラウザで動作しないことに対して若干イラッとはくるでしょうが🤣 その対処がちゃんとブラウザ側に実装されているのであれば、とりあえず当面は問題ないんじゃないかと個人的には思いますね。

あっちなみにこれ僕はあくまでも「Safari のブラウザタブの表示に関しては今のところダークモード非対応でも問題は起こらない」と言ってるだけで「Safari の SVG 実装がこのままダークモード非対応でも構わない」と言ってる訳ではないのでお間違えなきよう。現状のままではいつまで経っても <img> 要素じゃなくて <object> 要素にする7かインライン SVG にしないといけないので、Markdown で書く文書に気軽に使えないんですよね…そりゃ親の color-scheme 尊重してくれた方が便利に決まってますやん。

その他、各ブラウザ共通の一般的な話

「ルートに favicon.ico を置いておくだけで SVG 非対応のブラウザはそちらを使ってくれる」は正解か

そう書いてる記事は今回下調べで検索してて見つかった中にもありましたし、それ以前に実は僕自身がそう思い込んでもいた訳ですが、今回実際に試してみたらそんなことはなくて、iPad の Safari(こちらは現行バージョンの v18.6)がデフォルトのファビコンしか表示してくれなくてあれ? ってなりました…(´・_・`)

確かに現在のブラウザはデフォルトの挙動として、rel="icon" 指定された <link> 要素が存在しない場合にはルートの favicon.ico をリクエストしますが、何かひとつでも指定がある場合にはそれが非対応のファイル形式であったとしてもそれ以上は何もしてくれないんですね。SVG や PNG のファビコンは基本的に HTML 内に指定がないと適用されないので、その場合は favicon.ico の指定も一緒に書いておかないと、フォールバックとしては使ってくれないのです。

で、その辺のことを Firefox や Chrome でも確認できるようにシミュレートしてみたのが、今回のデモにあるテスト #18 です。favicon.txt という、ファビコンとしては不適切(テキストなのでどのブラウザも表示はできますが、ファビコンとしては使えません)なファイルをあえて rel="icon" 指定することで、ルートに置いただけの favicon.ico がフォールバックとして機能しないことを確認できるようにしています。

rel="icon" 指定するのであれば、ICO ファイルの名前や場所はどこでもいいか

Web ブラウザのことだけを考えておけばいいのであれは半分正解ですが、残り半分はそうとも言い切れません。例えば HTML 内で階層の深くにあるファビコンが指定されており、そのページのコンテンツに埋め込まれた画像ファイルなどのリソースを「画像を新規タブで開く」から直接ブラウザで開くことを考えましょう。

その場合、新しく開いたタブでの表示に使われるファビコンは何でしょう? それはルートにある favicon.ico であって、HTML 内で指定されたファビコンではありません。もしルートに favicon.ico が置かれてない場合、このパターンではファビコンは表示されないということになります。

またユーザーエージェントはブラウザだけとは限りません。一部の検索エンジンやクローラー、RSS リーダーなどは HTML を解釈して <link rel="icon"> を探すようなことはせず、ただルートの favicon.ico へのリクエストを行うだけかもしれません。

そういったことを考えますと、ICO 形式のファビコンファイルに関してはやっぱり favicon.ico という名前でドキュメント・ルートに固定するというのが、一番問題も少なくベストなのではないかと思います…が、もちろんあなたが「そんな環境にまでファビコンの表示はいらん!」というのなら、好きにすればいいと思います。

以上から導かれる、SVG ファビコン最新ベスト? プラクティス

という訳で、ここまで各ブラウザごとの注意点などを挙げてきました。これらのポイントをふまえて考えた結果、Safari の次期バージョンも含めたすべての主要ブラウザで確実に SVG ファビコンを表示させるためのベスト・プラクティスは、現時点ではおおむね次のようなものになるかと思います:

<!--
サンプルの HTML コード(`<head>` 要素内に配置)
- favicon.ico の `sizes` 属性値は実際のアイコンサイズに合わせる
- favicon.svg の場所はルートでなくても問題なく、ファイル名も自由でよい
  また `sizes="any"` はなくても機能はする(ありなしで動作に違いはないことを確認済み)
-->
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml">
<!-- 以下、任意で apple-touch-icon や Web App Manifest の記述を… -->
  • ICO ファビコンは 32x32 もしくは 48x48 のシングルアイコンで作る(全ブラウザで SVG を優先しつつ、非対応ブラウザでは高解像度を保つ)
    • そのファイルへの <link> 要素タグには sizes 属性を指定する(Chrome での不要な HTTP リクエストを回避するため)
    • またそのファイル名は favicon.ico とし、ドキュメントルートに配置する(ブラウザ以外のユーザーエージェントへの配慮)
  • SVG ファビコンは Firefox や Chrome のためにダークモード対応しておく(現状 Safari では機能しないが、それが問題となることはほぼない)
  • どちらのファビコンも HTML 内で必ず rel="icon" 指定する(ICO ファイルが SVG ファビコン非対応ブラウザへのフォールバックとなるためには必要)

どうでしょう…はい、苦労してテストをやって結果をまとめてデモサイトまで作ってがんばった割には、得られた結論が現状一般的にこれがベストとして認識されてそうな内容と大差ないことに涙が出そうになりますが😭 まぁここはひとつ、こうやって実験してみることで各ブラウザの実際の挙動を詳しく知ることができたし、ブログのネタもできたしよかったじゃないですか…ということにしておきます。涙

そんな訳で

今回は SVG 化したファビコンがそのサポートが入ったはずの Safari v26 のβ版で表示させられなかったことを発端に、Safari を含むすべての主要ブラウザで確実に SVG ファビコンが表示されるパターンを探るべくテストを実施、その結果から得られた各ブラウザごとの問題点や、最終的に現時点ではこれがベストであろう…という各ファイルの形式とその指定方法をまとめてみました。

とりあえず今回のテストの何が大変だったかって、Safari 独自のファビコン・キャッシュですよ! ただ単にファイル差し替えて HTML 書き換えてリロードだけでは全然反映されんし! しかも通常のキャッシュとは別のところで管理しているので、普通に Web サイトデータの削除だけでは解決しないんですよ。消すためには Finder でライブラリ・フォルダ内のキャッシュを手作業でゴミ箱に入れないといかんのです…すると当然、全サイトのファビコン・キャッシュが消える。涙

さすがに書き直すたびにそんな作業はやってられんので、まずはテスト内容をリストにして全部のファビコンと HTML ファイルを作ってから一気にまとめて確認するというデモサイトのような手法に切り替えましたが、それでも一度テストをすると結果がキャッシュされてしまうので、あとはもうチェックごとにローカルサーバーのポート番号を変更するとかしてました…

という訳で最後は愚痴になってしまいましたが😭 まぁこういった苦労しながらやっとのことで作った記事でございますので、できましたら多くの方々に各テストを色々なブラウザで確認していただけたらいいなぁ…と少しだけ思いつつ、この記事がみなさまの今後のファビコン・ライフ(何)の参考になりましたら幸いでございます。

  1. SVG -> ICO の変換をやってくれる Web サービスは検索するとたくさん出てきますが、得体のしれないサイトにファイルを上げたり下げたりするのはちょっと躊躇するタイプの人間なので、ImageMagick を使って手元でやりました。ちなみに最初に作った favicon.ico は今までと同じく 3 サイズのマルチ・アイコンでした(だから表示されなかった訳ですが)。 

  2. SVG ファビコンの配色を一時的にゴールド + 青に変更して確認。こういう時に SVG はテキストエディタで開いて CSS で簡単に色を変えられるので便利ですね。 

  3. あまり多くのサイズでテストしてもたいして意味がなさそうに思ったので、一般的によく採用されていると思われる 16x16, 32x32, 48x48 各サイズのシングルアイコン 3 つと、それらを組み合わせたマルチアイコン 4 つをテストしました。 

  4. ちなみにこのあたりは Python 3 の http.server モジュールを使ったワンライナーで起動できる簡易サーバーを立てるとターミナルに簡単なアクセスログが吐き出されるので、それで確認しました。  2

  5. この論議があったのは 2022 年の春〜夏ごろのようで、その結論は仕様として Media Queries Level 5 Editor’s Draft の prefers-color-scheme の項 に反映されています。 

  6. 元から付いてる背景色が暗い色の場合には、その背景色をメインカラーだと勘違いして付与することがあります。例: MDN 

  7. color-scheme を尊重しないのはあくまでも <img> 要素で画像として埋め込まれた場合の話。<object> 要素では SVG は XML 文書として埋め込まれるので color-scheme の引き継ぎはもちろん JavaScript だって動きます。