Search code examples
reactjsnext.jsnext.js13

How to Dynamically Change Favicon for Dark and Light Mode in Next.js 13 or 14?


I am working on a Next.js 14 application using App Router and I'd like to dynamically change the favicon based on the user's color scheme preference (dark or light mode). Currently, I have a black-colored favicon and a white-colored favicon. How can I set up my Next.js 14 app to automatically switch the favicon to the appropriate version when dark mode is activated and revert to the black version in light or default mode?

In previous versions, this could be achieved using the <Head/> component. However, in Next.js version 14, the new Metadata interface has been introduced to describe all the metadata fields. But, now I'm not sure how to achieve the favicon change based on color modes.

My Expectation:
  • In my Next.js version 14 application, I want to dynamically change the favicon based on color modes.

  • I am expecting that I could programmatically/automatically switch between the black and white favicon versions according to the user's color scheme preference (dark or light mode).


Solution

  • Since there were no immediate answer when I posted the question, I was searching in the internet and did not find any solution. So, I have read the official docs about icons and I find the solution myself. Though there were no direct solution in docs but got a hint and it's solved my issue.

    I am sharing the code because if anyone encountered into the same issue in future it would help them,

    // app/layout.tsx
    export const metadata: Metadata = {
      title: 'Website Title',
      description: 'Website description',
      icons: {
        icon: [
          {
            media: '(prefers-color-scheme: light)',
            url: '/images/icon-light.png',
            href: '/images/icon-light.png',
          },
          {
            media: '(prefers-color-scheme: dark)',
            url: '/images/icon.png',
            href: '/images/icon-dark.png',
          },
        ],
      },
    };
    

    I have to delete app/icon.png or any files that by default map the favicon in order to active the Metadata interface's icon. And, my favicon or icon images stored in public/images/icon-light.png and public/images/icon-dark.png. And, now its working dynamically based on color modes.

    Quick Procedure:

    • Delete any favicon or icon images from app/ directory.
    • Store favicon or icon images to public/images/ directory.
    • In app/Layout.tsx metadata.icons.icon add url and href path to the stored images relative path. ✅
    • If you find it difficult to understand; a video from YouTube made it practical, YouTube Video Link: https://youtu.be/fcUE498s4x0