Favicon does not react to theme toggle (light/dark) without page reload #191054
Replies: 4 comments
-
|
💬 Your Product Feedback Has Been Submitted 🎉 Thank you for taking the time to share your insights with us! Your feedback is invaluable as we build a better GitHub experience for all our users. Here's what you can expect moving forward ⏩
Where to look to see what's shipping 👀
What you can do in the meantime 💻
As a member of the GitHub community, your participation is essential. While we can't promise that every suggestion will be implemented, we want to emphasize that your feedback is instrumental in guiding our decisions and priorities. Thank you once again for your contribution to making GitHub even better! We're grateful for your ongoing support and collaboration in shaping the future of our platform. ⭐ |
Beta Was this translation helpful? Give feedback.
-
|
What you're seeing is expected browser behavior, not something specific to GitHub's implementation. When a favicon is loaded (including SVG favicons that use prefers-color-scheme), the browser evaluates it once at fetch time and caches the result. Unlike regular page styles, the favicon resource isn't re-evaluated when the system theme changes. That's why the rest of the UI responds to prefers-color-scheme dynamically, but the favicon doesn't follow along. This is also why you only see it update after a full page reload, since the browser fetches and re-processes the favicon again under the new theme. The only reliable way to make a favicon react to runtime theme changes today is to handle it in JavaScript. That usually means listening for changes via matchMedia('(prefers-color-scheme: dark)') and swapping the to point to a different asset. Without that kind of manual update, the browser simply won't refresh the favicon on its own. It's just browser, it's behavior doesn't support dynamic re-evaluation of favicon SVGs based on theme changes. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for confirming. That's exactly the point of this feedback, GitHub could implement the JavaScript-based matchMedia listener you described to dynamically swap the favicon href on theme change. The fix is straightforward and other web apps already do this. Would be a nice UX improvement, especially for users with multiple GitHub tabs open who use auto dark mode. |
Beta Was this translation helpful? Give feedback.
-
Solution: Dynamic Favicon Updates on Theme ChangeProblem AnalysisThe issue occurs because GitHub's current favicon implementation uses a single SVG file with internal
Proposed SolutionImplement dynamic favicon swapping by:
Step-by-Step Implementation1. Prepare Separate Favicon FilesCreate two optimized SVG files:
Store them in GitHub's asset pipeline (e.g., 2. Initial Page LoadEnsure the correct favicon loads initially based on the user's theme preference. GitHub already detects the theme on load—reuse that logic: // Example: Set initial favicon based on current theme
function setInitialFavicon() {
const isDark = document.documentElement.classList.contains('dark') ||
window.matchMedia('(prefers-color-scheme: dark)').matches;
const faviconHref = isDark
? '/favicons/favicon-dark.svg'
: '/favicons/favicon-light.svg';
updateFaviconHref(faviconHref);
}3. Theme Change ListenerHook into GitHub's existing theme change mechanism. GitHub likely uses a // Option A: Listen for class changes (if GitHub toggles 'dark' class)
const observer = new MutationObserver((mutations) => {
if (document.documentElement.classList.contains('dark')) {
updateFaviconHref('/favicons/favicon-dark.svg');
} else {
updateFaviconHref('/favicons/favicon-light.svg');
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
});
// Option B: Listen for custom theme event (if GitHub dispatches one)
document.addEventListener('themechange', (event) => {
const isDark = event.detail?.theme === 'dark';
updateFaviconHref(isDark
? '/favicons/favicon-dark.svg'
: '/favicons/favicon-light.svg');
});4. Favicon Update Functionfunction updateFaviconHref(href) {
let link = document.querySelector("link[rel='icon']") ||
document.querySelector("link[rel='shortcut icon']");
if (!link) {
link = document.createElement('link');
link.rel = 'icon';
document.head.appendChild(link);
}
// Only update if different (prevents unnecessary network requests)
if (link.href !== href && !link.href.endsWith(href)) {
link.href = href;
}
}Integration Notes
Why This Works
Expected OutcomeAfter implementation:
References:
This solution requires minimal changes to GitHub's frontend while solving the core issue of favicon staleness during runtime theme changes. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
🏷️ Discussion Type
Product Feedback
💬 Feature/Topic Area
Other
Body
What are you trying to do?
Have GitHub's favicon update when my system theme changes between light and dark mode (e.g. via Windows Auto Dark Mode which switches OS theme by time of day).
What did you expect to happen?
When the OS theme switches (and GitHub is set to "System" theme), the favicon in the browser tab should update to match - dark icon on light background, light icon on dark background - just like the rest of the UI does.
What happened instead?
Everything on the GitHub page adapts to the new theme, but the favicon in the browser tab stays in the old color scheme. It only updates after manually reloading the page. With multiple GitHub tabs open, all favicons remain in the wrong color until each tab is individually reloaded.
Why this matters
The favicon uses
prefers-color-schemeinside the SVG, which the browser evaluates only once when loading the resource. When the OS theme changes at runtime, the browser does not re-evaluate the SVG's media query for the already-loaded favicon. A JavaScript-based approach that dynamically swaps the favicon href on theme change would fix this.Beta Was this translation helpful? Give feedback.
All reactions