Iconello
Technical2026-03-03· 5 min read

Dark Mode Favicons: How to Make Your Icon Adapt Automatically

SVG favicons can respond to prefers-color-scheme. Learn how to build favicons that look right in both light and dark browser themes.

Over 80% of smartphone users have dark mode enabled, and desktop adoption keeps climbing. When someone switches to dark mode, their browser chrome turns dark, and your favicon needs to survive that transition.

A dark-colored favicon that looked great on a white tab bar becomes invisible on a dark one. A light-colored icon that pops in dark mode looks washed out in light mode. Try it: open your browser with 15 tabs and toggle between themes. You will be surprised how many favicons just vanish.

Dark Mode Adoption by Browser

Dark mode is not a niche preference anymore. Here is the estimated percentage of users with dark mode enabled across major browsers in 2026.

Samsung Internet leads at 85% — driven by Android's system-wide dark mode that cascades to the browser. Safari is close behind at 82% because Apple pushed dark mode aggressively since macOS Mojave and iOS 13. Even Firefox, with the lowest adoption, has more than two-thirds of users in dark mode. The takeaway: designing favicons for light mode only means ignoring the majority of your audience.

The SVG Solution

SVG is the only favicon format that can adapt to dark mode on its own. The trick is CSS media queries embedded directly in the SVG file. When the browser detects prefers-color-scheme: dark, the SVG swaps its colors automatically. No JavaScript needed, and no extra files to manage.

favicon.svg (dark mode aware)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    .icon { fill: #DA7756; }
    .bg { fill: transparent; }

    @media (prefers-color-scheme: dark) {
      .icon { fill: #F0B08A; }
      .bg { fill: transparent; }
    }
  </style>
  <rect class="bg" width="32" height="32" rx="6"/>
  <path class="icon" d="M8 24 L16 6 L24 24 H8Z"/>
</svg>

Lighter in dark mode, darker in light

The general rule is to use a slightly lighter version of your brand color in dark mode. A full-saturation color that looks punchy on white can look garish on dark backgrounds. Reduce the saturation by about 20% and increase the lightness for dark mode variants.

The SVG Approach: A Complete Example

The basic example above uses a transparent background, which works when your icon color has enough contrast on both light and dark tab bars. But the safest approach is to include a background shape that also adapts to the theme. Here is a production-ready SVG favicon that handles both modes robustly.

favicon.svg (production-ready)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    /* Light mode: dark icon on light background */
    .bg { fill: #FFFFFF; }
    .icon-primary { fill: #1A1A2E; }
    .icon-accent { fill: #DA7756; }

    /* Dark mode: light icon on dark background */
    @media (prefers-color-scheme: dark) {
      .bg { fill: #1A1A2E; }
      .icon-primary { fill: #FFFFFF; }
      .icon-accent { fill: #F0B08A; }
    }
  </style>

  <!-- Background — provides contrast on any browser chrome -->
  <rect class="bg" width="32" height="32" rx="6" />

  <!-- Primary shape -->
  <path class="icon-primary" d="M7 25 L16 5 L25 25 Z" />

  <!-- Accent detail — visible at 32px+, may merge at 16px -->
  <circle class="icon-accent" cx="16" cy="20" r="3" />
</svg>

A few things to note in this example. The background rectangle has rx="6" for rounded corners, which looks polished in browser tabs. The icon uses two CSS classes (icon-primary and icon-accent) so you can adjust multiple colors independently. The accent detail (the small circle) will only be visible at larger sizes — at 16px it merges with the primary shape, which is fine. This is progressive simplification happening naturally.

This SVG file goes in your public/ directory and is referenced in your HTML head:

HTML head
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/favicon.ico" sizes="48x48" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

The Meta Theme-Color Approach

Beyond the favicon itself, you can control the color of the browser chrome — the address bar, the tab bar area, and the status bar on mobile. The meta name="theme-color" tag sets this color, and it supports media queries for dark mode adaptation.

Dynamic theme-color
<!-- Light mode: white browser chrome -->
<meta name="theme-color"
      content="#FFFFFF"
      media="(prefers-color-scheme: light)" />

<!-- Dark mode: dark browser chrome -->
<meta name="theme-color"
      content="#1A1A2E"
      media="(prefers-color-scheme: dark)" />

This makes the entire browser chrome adapt to the user's theme, not just the favicon. On Android Chrome, this colors the address bar. On Safari (both macOS and iOS), it influences the tab bar tint. The combination of a theme-adaptive SVG favicon and matching theme-color meta tags creates a fully cohesive dark mode experience.

Safari and theme-color

Safari 15+ on macOS uses the theme-color meta tag to tint the entire toolbar area. This means your theme-color choice directly affects how your favicon looks — a dark favicon on a dark theme-color can vanish. Always test the combination of your favicon and theme-color in both modes.

Browser Support

BrowserSVG faviconDark mode CSS in SVG
Chrome 80+
Firefox 41+
Edge 80+
Safari 15+ (macOS)
Safari (iOS)
Samsung Internet
Opera

Safari on iOS is the notable holdout. It does not support SVG favicons at all, relying instead on the Apple Touch Icon (a static 180x180 PNG). For iOS users, you need a separate approach if dark mode adaptation matters.

Framework-Specific Solutions

Next.js App Router

Next.js 13+ with the App Router supports dynamic metadata through the generateMetadata function. While you cannot use JavaScript media queries at build time, you can serve the SVG favicon (which handles dark mode internally) alongside platform-specific icons.

app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  icons: {
    // SVG handles dark mode automatically via CSS media queries
    icon: [
      { url: '/favicon.svg', type: 'image/svg+xml' },
      { url: '/favicon.ico', sizes: '48x48' },
    ],
    // Static PNG for iOS — no dark mode adaptation
    apple: '/apple-touch-icon.png',
  },
  // Theme color adapts the browser chrome
  other: {
    'theme-color-light': '#FFFFFF',
    'theme-color-dark': '#1A1A2E',
  },
}

// For dynamic theme-color with media queries,
// add these tags in your root layout's <head>:
// <meta name="theme-color" content="#FFFFFF"
//       media="(prefers-color-scheme: light)" />
// <meta name="theme-color" content="#1A1A2E"
//       media="(prefers-color-scheme: dark)" />

React (with React Helmet or similar)

In a React SPA, you can dynamically swap the favicon based on the user's color scheme preference. React Helmet (or react-helmet-async) lets you declaratively manage the document head.

components/FaviconManager.tsx
import { Helmet } from 'react-helmet-async'
import { useEffect, useState } from 'react'

export function FaviconManager() {
  const [isDark, setIsDark] = useState(false)

  useEffect(() => {
    const mq = window.matchMedia('(prefers-color-scheme: dark)')
    setIsDark(mq.matches)
    const handler = (e: MediaQueryListEvent) => setIsDark(e.matches)
    mq.addEventListener('change', handler)
    return () => mq.removeEventListener('change', handler)
  }, [])

  return (
    <Helmet>
      {/* SVG favicon handles dark mode via CSS, but use as primary */}
      <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
      {/* Fallback PNG — swap based on theme */}
      <link rel="icon" href={isDark ? '/icon-dark.png' : '/icon-light.png'}
            type="image/png" sizes="32x32" />
      <meta name="theme-color"
            content={isDark ? '#1A1A2E' : '#FFFFFF'} />
    </Helmet>
  )
}

Plain HTML

If you are not using a framework, the simplest approach is to declare the SVG favicon in your HTML (it handles dark mode automatically) and optionally add a small inline script for PNG fallback.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- SVG with embedded dark mode CSS — the primary approach -->
  <link rel="icon" href="/favicon.svg" type="image/svg+xml" />

  <!-- ICO fallback for browsers that don't support SVG -->
  <link rel="icon" href="/favicon.ico" sizes="48x48" />

  <!-- iOS -->
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" />

  <!-- Theme color with dark mode support -->
  <meta name="theme-color" content="#FFFFFF"
        media="(prefers-color-scheme: light)" />
  <meta name="theme-color" content="#1A1A2E"
        media="(prefers-color-scheme: dark)" />

  <!-- Optional: JS-based PNG swap for browsers
       that support PNG but not SVG favicons -->
  <script>
    (function() {
      var mq = window.matchMedia('(prefers-color-scheme: dark)');
      var link = document.querySelector('link[sizes="32x32"]');
      if (link) {
        function update(e) {
          link.href = e.matches ? '/icon-dark-32.png' : '/icon-light-32.png';
        }
        update(mq);
        mq.addEventListener('change', update);
      }
    })();
  </script>
</head>

Alternative Approaches

The contrast border method

If SVG support coverage is not sufficient for your audience, a simpler approach works everywhere: add a visible border or background shape to your favicon that provides contrast in both modes. A dark icon inside a light rounded square works on dark backgrounds. A light icon inside a dark rounded square works on light backgrounds. A mid-tone background works acceptably on both.

The dual-PNG method

Some developers serve different PNGs based on theme detection. This requires JavaScript to check matchMedia('(prefers-color-scheme: dark)') and swap the favicon link dynamically. It works but adds complexity and can flash the wrong icon during page load before the script runs.

Theme-aware favicon (JS approach)
// Swap favicon based on color scheme
const setFavicon = (isDark) => {
  const link = document.querySelector("link[rel='icon']")
  if (link) {
    link.href = isDark ? '/favicon-dark.png' : '/favicon-light.png'
  }
}

// Initial set
setFavicon(matchMedia('(prefers-color-scheme: dark)').matches)

// Listen for changes
matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => setFavicon(e.matches))

Flash of wrong icon

The JavaScript approach has a timing problem. During server-side rendering or the brief moment before your script executes, the browser shows the default favicon. If the user is in dark mode and your default is the light version, there is a visible flash. SVG avoids this entirely because the adaptation happens in the rendering engine, not in JavaScript.

Testing Dark Mode Favicons

You do not need to toggle your entire operating system between light and dark mode to test. Chrome DevTools has a built-in emulator for prefers-color-scheme that lets you switch instantly.

  1. Open Chrome DevTools (F12 or Cmd+Option+I).
  2. Press Cmd+Shift+P (or Ctrl+Shift+P on Windows) to open the command palette.
  3. Type "Rendering" and select "Show Rendering".
  4. Scroll down to "Emulate CSS media feature prefers-color-scheme".
  5. Toggle between prefers-color-scheme: light and prefers-color-scheme: dark.

Your SVG favicon will update in real time as you toggle. This is the fastest way to verify that your dark mode colors are correct without touching your OS settings.

For Firefox, go to about:config, search for ui.systemUsesDarkTheme, and set it to 1 for dark or 0 for light. In Safari, you can toggle dark mode via the Develop menu → WebKit Feature Flags, but the most reliable method is toggling macOS System Preferences → Appearance.

Test both transitions

Do not just test dark-on-dark and light-on-light. The most jarring experience is when a user switches themes while your tab is open. Toggle back and forth several times to make sure the favicon updates without a stale cache artifact or flicker.

iOS 18 Tinted Icons

Starting with iOS 18, Apple introduced automatic icon tinting on the home screen. Users can choose a tint color, and iOS applies it to all app icons — including web app shortcuts added via "Add to Home Screen." This means your carefully chosen brand colors might be overridden by the user's preferred tint.

iOS 18 tinting works by analyzing the luminance of your icon and applying the user's chosen tint color while preserving the relative light/dark areas. Icons with clear contrast and simple shapes survive tinting well — the shape remains recognizable even when the colors change. Icons that rely on specific colors for meaning (like a red notification badge or a multi-colored logo) lose information when tinted.

To prepare for tinting, focus on strong silhouettes rather than color. Make sure your apple-touch-icon has a clear shape with good contrast between the foreground and background. Test by converting your icon to grayscale — if it is still recognizable, it will survive tinting. If it becomes an indistinguishable gray blob, simplify the design.

Design choiceSurvives tinting?Why
Bold silhouette on solid backgroundYesClear luminance contrast is preserved
Thin line artPartiallyLines may become too subtle under some tint colors
Multi-color iconNoAll colors collapse to the single tint hue
Gradient fillPartiallyGradient direction preserved but colors shift
Photo-realistic iconNoDetail is lost when color information is removed
Dark icon on light backgroundYesHigh contrast translates well to any tint

Apple has also introduced a "dark mode" icon variant for iOS 18 that apps can provide via the asset catalog. For web apps, there is not yet an equivalent mechanism — the apple-touch-icon is always a single static PNG. Watch for changes to this in future Safari updates, as Apple may extend the web manifest or introduce a new link tag to support themed web app icons.

Practical Recommendations

For most sites in 2026, the best approach is to use an SVG favicon as the primary icon (covers all desktop browsers with automatic dark mode adaptation) alongside a static PNG Apple Touch Icon for iOS. The iOS icon does not need dark mode adaptation because iOS renders it against its own themed background on the home screen.

If you are generating favicons with Iconello, the download package includes an SVG that you can modify to add dark mode CSS. Start with the generated SVG, open it in a text editor, add the media query block shown above, and adjust the dark mode colors to complement your brand.

Ready to create your icon?

Generate a professional icon from a text prompt in seconds. Favicons, app icons, social media — all platforms.