Favicons,
every file explained.
A favicon stopped being one file a long time ago. Browsers, iOS, Android and installable web apps all want something slightly different, and most generators hand you thirty files without saying which ones matter. Here is the short list and the reason for each.
The set worth shipping
| File | Size | Who asks for it |
|---|---|---|
| favicon.ico | 16, 32, 48 | Older browsers, and any request to the site root |
| favicon.svg | Vector | Modern browsers, scales to any density |
| apple-touch-icon.png | 180 x 180 | iOS home screen |
| icon-192.png, icon-512.png | 192, 512 | Web app manifest, Android install |
Four files and a manifest. Anything beyond that is either legacy or vendor specific, and no current browser will notice its absence.
Why favicon.ico refuses to die
Browsers request /favicon.ico from the site root whether or not you declare it. That request happens for bookmarks, for history entries, and for any context that has a URL but has not parsed your HTML. If the file is missing you get a 404 in your logs on every visit.
ICO is a container: one file holds several sizes. Ship 16, 32 and 48 in a single .ico and the browser picks. This is the one case where the old format is still the right answer.
SVG favicons
A single vector file covers every display density, which is why it is now the preferred declaration. Two caveats. External references do not load, so the SVG must be self contained. And CSS inside it does work, which means you can respond to dark mode:
<style>
@media (prefers-color-scheme: dark) {
.mark { fill: #FFFFFF; }
}
</style>
That is worth doing. A dark navy mark on a dark browser tab is invisible, and the tab strip is exactly where a favicon has to work hardest.
Maskable icons, and the safe circle
Android does not show your icon as you drew it. It masks it to whatever shape the launcher uses, which might be a circle, a squircle or a rounded square. An icon with content near the corners loses that content.
The rule is the safe circle: keep the mark inside the middle 80 percent of the canvas, and let the outer 10 percent on each side be background you do not mind losing. Declare it with "purpose": "maskable" in the manifest.
An icon marked maskable but designed edge to edge will be cropped into nonsense. Test it as a circle before you ship it.
The HTML
Four lines, in the head:
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
Note there is no sizes on the apple-touch-icon. iOS ignores it and takes the 180px file regardless.
Why yours is not updating
Favicons are cached harder than almost anything else on the web, sometimes past a hard refresh and past a cache clear. The reliable fix is to change the filename, not the file. Ship favicon-v2.svg and update the link tag.