Custom Favicon Recipes

Published See discussion on Bluesky

The other day I was reminded of two neat tricks related to customizing your favicon to bring some delight to your website visitors and also to improve your development flow - all thanks to scottykaye!

If you want to skip right to the code, checkout both recipes in my hamlim/custom-favicon-recipes repo!

Customizing Favicons for Light and Dark Mode

The first recipe is a neat way to change the favicon of your site based on the preferred color scheme of the visitor. You can use the <link /> tag's media attribute to have the browser "choose" the preferred icon based on light or dark mode.

If you're writing plain old html (or using some framework that gives you control over the html), you can use the below snippet to accomplish this:

1<head>
2 <link rel="icon" href="./light-mode-favicon.ico" media="(prefers-color-scheme: light)" />
3 <link rel="icon" href="./dark-mode-favicon.ico" media="(prefers-color-scheme: dark)" />
4</head>
1<head>
2 <link rel="icon" href="./light-mode-favicon.ico" media="(prefers-color-scheme: light)" />
3 <link rel="icon" href="./dark-mode-favicon.ico" media="(prefers-color-scheme: dark)" />
4</head>

If you're using Next.js and it's metadata or generateMetadata exports, you can do the following:

1export const metadata: Metadata = {
2 title: "Custom light/dark mode favicons",
3 description: "Generated by create next app",
4 icons: [
5 {
6 rel: "icon",
7 url: "./sun-favicon.ico",
8 media: "(prefers-color-scheme: light)",
9 },
10 {
11 rel: "icon",
12 url: "./moon-favicon.ico",
13 media: "(prefers-color-scheme: dark)",
14 },
15 ],
16};
1export const metadata: Metadata = {
2 title: "Custom light/dark mode favicons",
3 description: "Generated by create next app",
4 icons: [
5 {
6 rel: "icon",
7 url: "./sun-favicon.ico",
8 media: "(prefers-color-scheme: light)",
9 },
10 {
11 rel: "icon",
12 url: "./moon-favicon.ico",
13 media: "(prefers-color-scheme: dark)",
14 },
15 ],
16};

You can see this recipe in action on this Next app!

Customizing Favicons for Development and Production

This is a pretty neat trick that makes it just a bit easier to determine if you're looking at the development version of your site or the production one.

We've all been there, we're about 45 minutes into trying to debug an issue, you keep making more basic and basic changes to the code, refreshing the page in the browser and still can't see your changes. Only to then realize that you've been madly refreshing the production site expecting to find your local changes.

With a custom icon for development, you'll no longer get stuck in that situation again!

If you're using Next.js and it's metadata or generateMetadata exports, you can do the following:

1export const metadata: Metadata = {
2 title: "Custom favicon per environment",
3 description: "Generated by create next app",
4 icons: [
5 {
6 rel: "icon",
7 url: process.env.NODE_ENV === "production"
8 ? "./env-favicon.ico"
9 : "./env-favicon-dev.ico",
10 },
11 ],
12};
1export const metadata: Metadata = {
2 title: "Custom favicon per environment",
3 description: "Generated by create next app",
4 icons: [
5 {
6 rel: "icon",
7 url: process.env.NODE_ENV === "production"
8 ? "./env-favicon.ico"
9 : "./env-favicon-dev.ico",
10 },
11 ],
12};

You can see this recipe in action on this other Next app!


Let me know if you know of other tips and tricks with customizing your site's favicon!