SVG favicon dark mode: setup, Safari limits and fallbacks
A dark navy logo can look perfect in a light browser tab and almost disappear in a dark one. The usual fix — make the logo lighter — then makes it washed out for everyone else. Favicons need a version of dark mode that switches with the visitor's theme, and they need it without giving up the older formats that half the web still relies on.
SVG gives you exactly that switching mechanism. This article shows the setup we recommend: one self-contained favicon.svg that adapts with prefers-color-scheme, backed by the PNG, ICO, Apple Touch and manifest icons that cover the places SVG favicons do not reach. It is progressive enhancement in the classic sense: modern browsers get the smarter icon, and nobody gets a broken one.
Updated for Safari 26 (November 2026): Safari 26 now displays SVG favicons, but does not yet apply the dark-mode switch inside them, so the Safari and fallback guidance below has been revised — the recommended setup itself is unchanged.
The mental model: a favicon is an image, not a page element
Everything about favicon dark mode follows from one fact: the browser loads your favicon as an image, in isolation from your page. Your stylesheet cannot reach into it, your JavaScript cannot run inside it, and a dark-mode toggle on your own site — a class on <html>, a localStorage setting — has no effect on it. The SVG cannot phone home, either: in image context, external resources such as web fonts or linked pictures are not fetched, so the file must be completely self-contained.
What the SVG can see is the environment the browser reports for the image itself: most importantly, whether the user's system or browser theme prefers a light or a dark color scheme. Inside an SVG favicon, you express that with the same media query you already know from CSS: @media (prefers-color-scheme: dark). The icon follows the browser and operating system theme — typically the OS setting, in some browsers the browser's own theme setting — never your page's toggle. That is not a limitation to work around; it is the right behavior, because the favicon sits in the browser's chrome, next to the browser's own UI, not inside your layout.
Option 1 (recommended): one SVG with the media query inside
The most robust technique is a single favicon.svg that contains both designs and shows one or the other. The light design is the default; a small <style> block hides it and reveals the dark design when the scheme is dark:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
.dark { display: none; }
@media (prefers-color-scheme: dark) {
.light { display: none; }
.dark { display: inline; }
}
</style>
<g class="light">
<rect width="32" height="32" rx="7" fill="#ffffff"/>
<path d="M10 23V9h9a5 5 0 0 1 0 10h-5" fill="none"
stroke="#1e3a8a" stroke-width="3.4" stroke-linecap="round"/>
</g>
<g class="dark">
<rect width="32" height="32" rx="7" fill="#172554"/>
<path d="M10 23V9h9a5 5 0 0 1 0 10h-5" fill="none"
stroke="#bfdbfe" stroke-width="3.4" stroke-linecap="round"/>
</g>
</svg>
A few details make this work reliably. Keep a single viewBox and draw both variants on the same canvas, so the browser never has to guess at sizes. Use classes rather than presentation attributes for anything that changes, because the style block can only override what CSS can reach. And keep the media query inside the SVG file itself — an external stylesheet referenced from the SVG will not be loaded in image context.
You do not have to hand-write this. In EasyFaviconGenerator, the "Classic and SVG favicons" section has a Dark icon panel: choose Start from the regular icon to reuse your design with its own adjustments (brightness, background, margins), or Use another icon to supply a dedicated dark artwork. The generated favicon.svg then embeds both designs with exactly this media-query switch, and the editor previews the result in light and dark browser tabs and in light and dark Google results before you download anything. Our earlier guide, How to create an SVG favicon, covers creating the base icon itself.
Designing the dark variant
Resist the urge to simply invert the colors. Inversion turns brand blues into odd oranges and makes subtle shadows look dirty. Instead, design the dark variant on its own terms:
- Keep the same silhouette. The icon should be recognizable as the same site when the theme flips. Change colors, brightness and background — not the shape or the concept.
- Raise the foreground brightness, not just the contrast slider. A mid-blue letterform on a near-black tab needs to become a pale blue, near-white or a brighter brand tint. Check it at the size it will actually be used: shrink it to 16x16 pixels and look at it, not at the 512-pixel master.
- Give the dark variant its own background if it needs one. A transparent icon floats directly on the tab color, which you do not control. Many marks work better in dark mode on a dark rounded square of their own — dark enough to read as a background, light enough to separate from the tab. The light variant can stay transparent at the same time; the two groups are independent.
- Thicken, don't thin. Fine strokes and small counters that survive in light mode clog up in dark mode, where light-on-dark shapes visually swell. If anything, the dark variant wants slightly bolder strokes and more open counters.
Option 2: separate files chosen with the media attribute
HTML also lets you put the media query on the <link> element and ship two separate files:
<link rel="icon" type="image/svg+xml" href="/favicon.svg"
media="(prefers-color-scheme: light)" />
<link rel="icon" type="image/svg+xml" href="/favicon-dark.svg"
media="(prefers-color-scheme: dark)" />
This is attractive when the two variants come from different source artwork that is hard to merge into one file, or when a framework's asset pipeline already produces them separately. Be honest about the trade-offs, though. Handling of media on icon links is less uniform than the in-SVG query, theme changes can be picked up less promptly, and you now have two files to keep in sync and to version. If you use this route, test it in every browser you care about — and still keep the unconditional fallbacks of the next section, because a browser that ignores the media attribute needs something sensible to fall back to. For most sites, Option 1 is simpler and behaves better; treat Option 2 as a tool for pipelines that genuinely need separate files.
One related trick is worth knowing: media also works on the theme-color meta tag, which tints the browser's own UI around your page:
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#172554" />
That does not change the icon itself, but pairing it with a dark-aware favicon makes the whole tab feel designed rather than accidental.
The fallback stack: what makes it work everywhere
An SVG favicon, however clever, is not the whole story. Safari supports SVG favicons only from version 26 (September 2025), so Safari 18 and earlier still use PNG and ICO for tab icons — and even Safari 26 does not yet apply prefers-color-scheme rules inside an SVG favicon (WebKit bug 309949, still open when we checked), so it shows the default design. iOS home screen shortcuts come from the Apple Touch icon, Android uses the Web App Manifest icons, and plenty of tools never read your HTML at all and simply request /favicon.ico. None of those formats can switch themes — each is a fixed picture — so the job of the fallback stack is to give every platform one good, theme-neutral icon. The complete <head> block looks like this:
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" sizes="32x32" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
This is the package EasyFaviconGenerator produces, and each line earns its place:
favicon.svgis the icon modern browsers (Chrome, Edge, Firefox, Opera and Safari 26+) prefer when it is declared, and the only one in the stack that can adapt to dark mode — in Chrome, Edge and Firefox; Safari 26 uses the SVG but ignores the dark-mode switch inside it.favicon-96x96.pngcovers browsers without SVG favicon support (Safari 18 and earlier, for instance) and Google's result pages: Google Search lists PNG, ICO and other raster formats as supported, not SVG, and recommends a square icon larger than 48x48 pixels. Because it is a fixed image, design it to survive both light and dark result pages: a mid-tone background of its own beats transparency.favicon.icoserves legacy browsers, RSS readers and other tools that request it blindly, and browsers displaying a PDF or image directly, where there is no HTML to read. Keep the file at the root of the site so those root-level requests find it.apple-touch-icon.png(180x180, opaque) is what iOS puts on the home screen. iOS fills any transparency with black, so give it a deliberate background rather than letting iOS choose one.- The manifest icons (192x192 and 512x512, declared in
site.webmanifest) do the same job for Android home screen shortcuts and splash screens, where the system may mask the icon into a circle or squircle — keep the important artwork in the central safe zone.
Notice what this means in practice: your dark-mode work lives entirely in the SVG, while the fallback design has to be the "any theme" version of the mark. If your logo only works on white, the answer is not to ship a white PNG and hope — add a background with margins to the raster icons (the generator's Add a plain background and margins option exists for exactly this) so every platform gets a legible icon, then let the SVG be the refined, theme-aware version on top.
Testing, caching and the traps that waste afternoons
The theme that counts is the system's, not your site's. If your website has its own light/dark toggle and the favicon does not follow it, that is expected behavior, not a bug: the SVG responds to the browser/OS color scheme. To test, change the operating system appearance (or the browser's theme setting where it offers one), then open a fresh tab; some browsers only evaluate the icon when a tab is created or the page is reloaded.
Favicons are cached aggressively — sometimes for weeks. When your new icon "does nothing", caching is the usual suspect. During development, open /favicon.svg directly in a tab and hard-refresh it (Ctrl+F5) while you toggle the system theme: you should see the artwork switch in the tab. For releases, change the file name or append a version such as ?v=2 to the URLs; the generator can add a version for you. Google refreshes favicons in search results on its own schedule, over days, so do not judge the search appearance on launch day.
Do not put anything interactive or external in the SVG. Scripts never run in favicon context, and external images or fonts are not fetched. If your SVG tool exports references to external files, outline the fonts, embed the images, or export a clean standalone file. Raster artwork is fine — EasyFaviconGenerator, for example, embeds it directly into the SVG — as long as it is embedded rather than linked.
Check the whole surface, not just your main browser. A short checklist covers almost everything:
- Toggle the system between light and dark with your site open in Chrome or Edge and in Firefox, and confirm the tab icon switches and stays legible at 16 pixels in both.
- Open the site in Safari and confirm the icon looks right on a light and a dark tab bar — Safari 26 and later show the SVG (with its default design, not the dark variant), while Safari 18 and earlier show the PNG/ICO fallback.
- Add the site to an iOS and an Android home screen and check the touch and manifest icons, including their backgrounds.
- Run the deployed site through the favicon checker: it verifies the declarations, fetches every icon and the manifest, and previews the icon in light and dark browser tabs and search results.
- Cross-check anything surprising against the compatibility matrix, which records which file each browser and platform actually uses.
New to SVG favicons? Start one step earlier
This post assumes you have a working SVG favicon and focuses on making it respond to dark mode. If you are still creating the file — simplifying artwork, cleaning a viewBox, outlining text or wrapping a PNG — follow how to create an SVG favicon first, then return here for the theme variant.
Which approach should you choose?
For almost every site: one SVG with the prefers-color-scheme switch inside it, plus the standard fallback stack. The SVG stays a single file to cache-bust and keep in sync, the switch works in the browsers that honour it (Chrome, Edge and Firefox today; Safari 26 shows the SVG but not its dark variant), and the PNG, ICO, Apple Touch and manifest icons quietly guarantee that Safari, phones, search engines and decades-old tools still get a good icon. Reach for separate light and dark files only when your build pipeline produces them naturally, and test that route harder when you do.
Start from your logo, define the dark variant, and look at both at real size before you ship. That five-minute preview — light tab, dark tab, light search result, dark search result — is the difference between an icon that merely exists and one that keeps working when your visitor's whole screen changes around it. Create your favicon and try toggling your system theme while you do.