SVG favicons: support, dark mode and fallbacks
How to ship an SVG favicon with dark mode support, which fallbacks to keep for browsers and home screens, and why favicon updates can take a while to show.
5 min read
An SVG favicon is one small file that stays sharp on every screen density and can even switch colors for dark mode. It does not replace the older formats yet, though. A complete setup is an SVG for browsers that support it, an ICO for those that do not, a PNG for phone home screens, and optionally a web app manifest. Four lines in your <head> cover it.
The markup
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">
What each line does:
favicon.icois the fallback for browsers without SVG favicon support, and for tools that request/favicon.icodirectly without reading your HTML. Declaringsizes="32x32"tells browsers what the file contains, which helps those that support SVG choose the SVG instead.icon.svgwithtype="image/svg+xml"is the modern favicon. Thetypelets browsers that cannot use it skip the download.apple-touch-icon.pngis used when someone adds your site to an iPhone or iPad home screen. It should be a 180 × 180 PNG.- The manifest lists larger PNG icons (commonly 192 × 192 and 512 × 512) for installed web apps and Android home screens.
This combination is a widely used pattern, but browsers choose between icons with their own logic. After deploying, check which file each of your target browsers actually requests in the network panel of its developer tools.
Browser support
Chromium-based browsers (Chrome, Edge, Brave, Opera and others) and Firefox support SVG favicons. Safari's support has lagged behind and changed between versions, so do not assume it; check a current compatibility table for the versions your users run. This is the main reason the ICO fallback is not optional.
Some contexts never use your favicon link at all. Bookmark sync, link preview cards and search results may fetch /favicon.ico or pick their own icon, so make sure the ICO is a faithful version of the SVG.
Dark mode inside the SVG
An SVG favicon can contain a <style> element with media queries. That allows a dark mark on light tab bars and a light mark on dark ones:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
.mark { fill: #18181b; }
@media (prefers-color-scheme: dark) {
.mark { fill: #f4f4f5; }
}
</style>
<path class="mark" d="M16 3l10 13-10 13L6 16z"/>
</svg>
Three caveats are worth knowing before you rely on it:
- It follows the user's color scheme preference as the browser reports it, not your site's own light/dark toggle, and not necessarily the color of the tab strip. A browser theme can be dark while the system preference is light.
- Browsers may not update the icon immediately when the preference changes while a tab is open.
- The ICO and PNG fallbacks cannot switch. Pick colors for them that work on both light and dark backgrounds.
The alternative that avoids all three: put the mark on its own solid tile, such as a rounded square in your brand color with the mark knocked out in white. A tile reads on any tab color, in every format, with no media queries, much like an app icon. Designing a favicon for a crypto project covers the design choices in detail.
Small sizes
A favicon is shown at 16 × 16 CSS pixels in most tab strips, which is 32 × 32 physical pixels on a high-density screen. Fine detail disappears at that size.
Because an SVG used as an image has its own viewport, media queries on width can, in principle, swap in a simpler drawing at small sizes:
<style>
@media (max-width: 24px) {
.detail { display: none; }
}
</style>
In practice, browsers decide for themselves at what resolution they rasterize a favicon, so a width query may not trigger when you expect it to. Treat it as an enhancement, and test it in real tabs. The dependable approach is a mark that is simple enough to work at 16 px to begin with: one or two solid shapes, no thin lines, no text.
Making the fallbacks
Export the PNG fallbacks from the same SVG so every version matches:
| File | Size | Notes |
|---|---|---|
favicon.ico |
16, 32 and optionally 48 px inside one file | Transparent background is fine |
apple-touch-icon.png |
180 × 180 | Use a solid background and leave some padding; iOS does not keep transparency the way a browser tab does |
| Manifest icons | 192 × 192 and 512 × 512 | Add a separate maskable icon with extra padding if you want Android to crop it into its own shape |
An ICO file can hold several PNG images at different sizes. With ImageMagick, for example, you can combine PNGs exported from your design tool:
magick favicon-16.png favicon-32.png favicon-48.png favicon.ico
Many design tools and online generators produce the same result. Whatever you use, open the finished ICO and check the 16 px version: it should be a hand-checked export, not a blurry downscale of the 48 px one. Converting SVG to PNG at the right size covers exporting crisp PNGs.
Keep the SVG itself small and self-contained. It should not reference external fonts, images or stylesheets; SVG used as an image cannot load them anyway.
Why your new favicon does not show up
Browsers cache favicons aggressively, sometimes in a store separate from the normal page cache. A hard reload of the page often does not refresh it. When you change your favicon:
- Change the URL. Rename the file (
icon-v2.svg) or add a version query (/icon.svg?v=2) in the<link>tag. A new URL is fetched fresh. - Test in a private window or a fresh browser profile, which starts without the cached icon.
- Remember the ICO. Clients that request
/favicon.icoby its fixed path cannot see a version query, so expect those to update on their own schedule.
On the server side, the usual cache headers for static assets apply; caching SVG files with HTTP headers explains how long-lived caching and versioned file names work together.
Checklist
- SVG favicon with a viewBox, a simple mark and no external references.
- Works on light and dark tab strips, either with a media query or a solid tile.
favicon.icowith 16 and 32 px images, linked withsizes="32x32".- 180 × 180
apple-touch-icon.pngwith a solid background. - Manifest icons at 192 and 512 px if the site can be installed.
- Checked in real tabs in each target browser, in both color schemes.
- A versioned URL ready for the next time it changes.