How to change favicon based on color scheme?
Answered
P𝑠eudo posted this in #help-forum
P𝑠eudoOP
I want to change the icon of the tab depending on the color scheme (light or dark), is that possible in App Router like the following?
export const metadata: Metadata = {
title: 'Site',
icons: {
icon: isDark ? '/favicon-dark.svg' : 'favicon.svg',
},
}
Answered by P𝑠eudo
thank you i finally got it working!
export const metadata: Metadata = {
title: 'Site',
icons: [
{
rel: 'icon',
type: 'image/x-icon',
url: '/favicon.ico',
media: '(prefers-color-scheme: light)',
},
{
rel: 'icon',
type: 'image/png',
url: '/favicon-dark.png',
media: '(prefers-color-scheme: dark)',
},
],
}
42 Replies
You can't use head in app dir (that's a pages dir thing) because you meant to use the new metadata for that stuff...
P𝑠eudoOP
Sorry edited the post, i just learned it
Umm I dont think they have theme changing favicons
So I'd say create a feature request on GitHub and see how it goes
(they may tell you about an obscure way of doing it)
P𝑠eudoOP
I see thank you, i hope i can find the answer there and post it here
@P𝑠eudo I see thank you, i hope i can find the answer there and post it here
First check if it already exists, othwise post it there 🙂
@risky First check if it already exists, othwise post it there 🙂
P𝑠eudoOP
I see, so far there's none related to it
Yeah I couldn't either
You need to alter the head tag directly using some JS in a effect
like "useEffect(() => {document.querySelector("head") /* you need to figure the exact code */}, [isDark]
not sure it will work but that's the best lead
yeah but the original code was about the normal media select on favicons (so auto darkmode)
yeah I see OP changed to show metadata
I don't see any problem in this example if the theme is known during server render
that is going to break server rendering because it can't be cached and the dark had to be sent in the cookies or something because of hot metadata works
@P𝑠eudo I see, so far there's none related to it
just wondering did you end up creating a feature req or not? (its totally fine to not, i just wanted to upvote it)
I don't see where you need a Next.js specific feature$
you indeed need to send the information to your server so for instance a cookie will do
Or you could use the [dark mode favicon](https://joyofcode.xyz/dark-mode-favicon) option... but since nextjs app dir doesn't give us access to the head, and instead recommends us to use the metadata option, i was now hoping for a better way to do this natively (no weird js or cookies). The other reason against cookies is if the user changes theme, it still is going to be incorrect (you might as well make the image read headers and choose which to sent)....
@P𝑠eudo I want to change the icon of the tab depending on the color scheme (light or dark), is that possible in App Router like the following?
tsx
export const metadata: Metadata = {
title: 'Site',
icons: {
icon: isDark ? '/favicon-dark.svg' : 'favicon.svg',
},
}
another option that i just thought of is put the prefers color theme inside the actual svg: https://blog.tomayac.com/2019/09/21/prefers-color-scheme-in-svg-favicons-for-dark-mode-icons/
It seems that rendering <head> in a page works
I just add an unrelated issue with http-equiv meta tag which is unsupported, and just rendering it in the page seem to do the trick
not sure how reliable but I've opened an issue to ask if this is a valid pattern
anyway it's not weird JS but perfectly valid to alter the meta tags using JS when the user switch themes
@Eric Burel It seems that rendering <head> in a page works
ohh i thought they didn't want you to manualy add stuf there...
I think I get what you mean
the media thing is not supported by "metadata" right?
you can just pass a favicon?
@Eric Burel anyway it's not weird JS but perfectly valid to alter the meta tags using JS when the user switch themes
i think the reason that it might want to be independent is becacause browsers change background color for lightmode/darkmode
@risky i think the reason that it might want to be independent is becacause browsers change background color for lightmode/darkmode
in a pure CSS solution without JS you would indeed use "metadata" and set the "media"' as you need, this would prevent the need for client-side JS
you might want to send a feature request for that indeed if OP didn't, this seems to be a legitimate use case
and if it's actually possible something that would be worht mentionning in the doc
actually from the typings it seems supported
ohh it is a valid thing (i never actually tried this)
@risky ohh it is a valid thing (i never actually tried this)
I've learnt smth too with the "media" thing it's brilliant to customize CSS
ooo then it just could have a section on docs saying its existance
@risky just wondering did you end up creating a feature req or not? (its totally fine to not, i just wanted to upvote it)
P𝑠eudoOP
hello sorry i didn't but i created a discussion there https://github.com/vercel/next.js/discussions/54433
@Eric Burel Click to see attachment
P𝑠eudoOP
thank you i finally got it working!
export const metadata: Metadata = {
title: 'Site',
icons: [
{
rel: 'icon',
type: 'image/x-icon',
url: '/favicon.ico',
media: '(prefers-color-scheme: light)',
},
{
rel: 'icon',
type: 'image/png',
url: '/favicon-dark.png',
media: '(prefers-color-scheme: dark)',
},
],
}
Answer