A dark favicon looks great on a light browser tab — and vanishes into a dark tab. The fix is an adaptive favicon: one icon for light mode, another for dark. This guide shows the SVG media-query technique, the theme-color meta tag, and a JS fallback for older browsers.
The SVG media-query technique (recommended)
SVG favicons can embed CSS that responds to prefers-color-scheme. The browser automatically picks the right colors based on the user's OS or browser theme — no JavaScript needed.
Create a favicon.svg like this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
@media (prefers-color-scheme: dark) {
.bg { fill: #1a1a1a; }
.logo { fill: #ffffff; }
}
.bg { fill: #ffffff; }
.logo { fill: #1a1a1a; }
</style>
<rect class="bg" width="32" height="32" rx="6" />
<path class="logo" d="M8 16 L16 8 L24 16 L16 24 Z" />
</svg>Then declare it in your HTML:
<link rel="icon" type="image/svg+xml" href="/favicon.svg">In a light tab the icon renders dark-on-white; in a dark tab it flips to light-on-dark. The browser handles the switch instantly.
Safari caveat: Safari 26 (2025) finally renders SVG favicons, but it ignores media queries inside them — your dark-mode variant won't switch there. This is tracked as WebKit bug #309949. See Dark Mode Favicon Not Working in Safari? → for diagnosis and workarounds. And as always, ship a PNG/ICO fallback — see the SVG vs PNG guide.
The theme-color meta tag
While you're adapting to dark mode, also set the browser-chrome color with two theme-color meta tags:
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1a1a1a">This colors the browser tab/toolbar background in mobile Safari and Chrome, complementing your adaptive favicon.
JS fallback for older browsers
If you need to support browsers that don't honor SVG media queries, you can swap between two PNG favicons using JavaScript and matchMedia:
function setFavicon() {
const dark = window.matchMedia('(prefers-color-scheme: dark)').matches
const icon = document.querySelector("link[rel='icon']") as HTMLLinkElement
if (icon) {
icon.href = dark ? '/favicon-dark.png' : '/favicon-light.png'
}
}
setFavicon()
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', setFavicon)This works everywhere but requires shipping two separate PNGs and a small script. Prefer the SVG approach when you can.
Design tips for adaptive favicons
- Use outlines, not fills. An outlined logo adapts better than a solid shape, because it reads on any background.
- Test both modes. Toggle your OS between light and dark and check both browser tabs.
- Avoid pure white or pure black fills — off-white (#f5f5f5) and near-black (#1a1a1a) look softer.
- Keep the SVG small. Inline CSS adds bytes; keep the path simple.
Browser support for SVG favicons
Updated for the September 2025 Baseline change — Safari 26 now renders SVG favicons, but not their media queries:
| Browser | SVG favicon | Media query inside SVG |
|---|---|---|
| Chrome (desktop & Android) | ✅ | ✅ |
| Firefox | ✅ | ✅ |
| Edge | ✅ | ✅ |
| Safari 26+ (desktop) | ✅ (new in 2025) | ❌ WebKit bug #309949 |
| iOS Safari | ❌ (use apple-touch-icon) | ❌ |
The takeaway: ship the SVG for modern browsers, plus a PNG/ICO fallback for everything else — and use the JS swap below if Safari's dark-mode support matters to your audience.
Complete dark-mode favicon setup
<!-- Adaptive SVG for modern browsers -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<!-- PNG fallbacks -->
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<!-- iOS -->
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<!-- Browser chrome color -->
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1a1a1a">Generate your favicon package (including SVG) at Favicon.one, then add the CSS above to make it dark-mode aware.