Create a themed favicon for color modes
There are 2 types of people in this world. Those who use dark mode and the other people.
I'm not sure about you, but I am basically a 100% user of dark mode on everything I do. There is nothing worse then sitting down at my desk to do some work or reading, opening a website and being hit with a solar flare from the bright white screen in front of me. However, this has caused me some issues when it comes to favicons
on the web. A favicon is the small icon that you see in your browser tab that allows you to navigate the madness of your many tabs. If your like me and prefer to save your eyes from the blinding brightness of light mode, you may have noticed that some of these favicons
are kind of hard to see.
In this post we will go over how to toggle your favicon based on whether the user has their settings on dark mode
or light mode
.
Note: In this example I will be using a NextJS website, however this will work in any React application.
Lets start
Create our project
First thing we will do is create a new project.
npx create-next-app themeable-favicons
Create a custom hook
Next, we are going to create a custom hook called useSystemTheme
. For our custom hook we are going to simply wrap an already created npm package. So lets install the package.
npm install react-use-system-theme
Now let's create a new file called useSystemTheme.js
under a hooks
directory. Our directory structure should look something like this.
│ └── components
│ └── hooks
| ├── useSystemTheme.js
│ └── pages
| ├── index.js
Inside our useSystemTheme.js
file, we are going to import the useTheme
function from our react-use-system-theme
and return the value from it.
// useSystemTheme.js
import useTheme from 'react-use-system-theme';
export function useSystemTheme() {
const theme = useTheme();
return theme;
}
This is called "wrapping". The reason that we want to take this approach rather than just using the useTheme
function directly is that if in the future, we decide to re-write this hook or use a different package, we will only need to make the change in one place.
Create our favicons
Next we want to create our favicons. I like to use RealFaviconGenerator.net as I think that it gives you the most robust options for your favicons.
Once you have created your two favicon packages (one for your dark mode and one for your light mode), you will want to rename the files in them from favicon.ico
-> favicon-dark.ico
etc.
│ └── public
| ├── favicon-dark-16x16.png
| ├── favicon-dark-32x32.png
| ├── favicon-dark.ico
| ├── favicon-light-16x16.png
| ├── favicon-light-32x32.png
| ├── favicon-light.ico
Use our hook to toggle favicons
Note: This step will be very specific to how NextJS works. However, you can do the same thing in any project that has a favicon
.
By default, NextJS adds a favicon to our pages/index.js
file. We will want to go in and remove this, as we are going to move the favicon to our pages/_app.js
file.
Next, in our pages/_app.js
file we will want to include our favicon
. To do this, we are going to import the Head
component from next/head
. This will allow us to add to our html
head
tag.
Inside of our Head
component, we will want to add our favicon
that we removed from our pages/index.js
.
import Head from "next/head";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<link rel="icon" href={`/favicon-${theme}.ico`} />
</Head>
<Component {...pageProps} />
</>
);
}
export default MyApp;
Finally, we want to import and use our hook to toggle between the two favicons
.
import Head from "next/head";
import { useSystemTheme } from "../hooks/useSystemTheme";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
const theme = useSystemTheme();
return (
<>
<Head>
<link rel="icon" href={`/favicon-${theme}.ico`} />
</Head>
<Component {...pageProps} />
</>
);
}
export default MyApp;
You will see in the code above that I am including the favicon
with favicon-${theme}.ico
. This will use the dark favicon that we created earlier on.
Now, when we switch our system theme from light mode, to the more appropriate dark mode, we will be able to toggle our favicon with it.