How to add a favicon to your website
Tags: webdev, design
Published: 2021-07-12 12:29:21

A favicon is short for “favorite icon”. It is the small icon that represents your website. The most common place you see it is on browser tabs alongside the page title.

Often the favicon is just a scaled down version of a website's logo. It should look good at very small sizes - as small as 16 by 16 pixels - this may lead you to create a different design for your favicon.

For example, take IBM. They use their distinctive stylised text logo in their website header, but they use a bee icon as their favicon.

![IBM logo and favicon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve8pz4lfognfo3197l7m.png)

## What is required to add a favicon?

Over time, the requirements for favicons got out of hand. Favicons started to be used on home screens and on splash screens for progressive web apps. Different browsers and mobile platforms wanted different image resolutions and formats for different contexts. If you wanted to satisfy all of these scenarios, you would end up creating approxmiately 20 image files and have to reference these in metadata in different places. Some people wrote generators that would spit out the image files and related metadata based on an initial image you provided.

Thankfully, it has gotten saner and you can forgo a generator. You can now make a SVG favicon, so you can benefit from its scalable nature and cut out a large portion of the image files required. Andrey Sitnik researched this topic recently in his article - [How to Favicon in 2021: Six files that fit most needs](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs). His findings were that 6 files will cover most of the bases. Read through his article to get the full run-down, I will summarise the big points here and discuss some important design considerations when you create a favicon.

## What files do I need to create?

It's probably easiest to create your favicon as a SVG in your favourite vector graphics editor (Adobe Illustrator, Inkscape..etc). You can then export it as a PNG when it is finished.

The files you need to create are:

1. A SVG in a 1:1 aspect-ratio. We will discuss this more in the next section.
2. A 32 by 32 pixel ICO. This is for legacy browsers. You can open the SVG in [GIMP](https://www.gimp.org/) and export it to `favicon.ico` using the setting: *32 bpp, 8-bit alpha, no palette*.
3. A 180 by 180 pixel PNG. This is for Apple devices
4. A 192 by 192 pixel PNG. This is for the home screen for Android devices.
5. A 512 by 512 pixel PNG.  This is for the splash screen for Android devices.
6. A web app manifest file. This is typically used for creating Progressive Web Apps (PWAs), but it is used in other contexts such as the "add to home screen" context in browsers . The file is called `manifest.json` or `manifest.webmanifest`, and is typically placed in the root directory of your website.

What this set-up chooses to exclude is support for the following specifications:

- [Pinned tabs in Safari](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/pinnedTabs/pinnedTabs.html) specified with `<link rel='mask-icon'>`. Safari 12+ use a regular favicon for pinned tabs now.
- [Pinned site customisation for Windows](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/dn320426(v=vs.85)?redirectedfrom=MSDN), which is defined by the `browserconfig.xml` file.

## Creating the SVG - don't disregard dark mode

We want to create a square SVG, such that the aspect ratio is 1:1. You can omit the `width` and `height` attributes on the SVG, you can use `viewBox` to define the dimensions.

```html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
   <!-- stuff -->
</svg>
```

We want to ensure our favicon looks good on near-white and near-black colours, and looks reasonable on *any* background.

Why? Can't we just use a media query to use a different version of the favicon or change the colours when the theme is light or dark?

Yes, but you can't rely on this 100%. The `prefers-color-scheme` [CSS media feature](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) can be used to detect if the user has requested a light or dark color theme in the browser and will cover *most* scenarios. Scenarios that I found that this does not cover are:

- In Chromium-based browsers incognito windows use dark colours by default, they ignore the operating system's theme.
- In the history dropdown in browsers, the favicons used are probably cached and are not affected by the user’s theme. You can see in the screenshot below that the BBC and GitHub favicons are hard to identify.
![Browser history favicons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vwyr783iy2mdg9r84f0.png)

- On the traffic page on Github, favicons for referring sites are displayed inline alongside the web address. Even GitHub's favicon falls foul here if you have dark mode set in the GitHub settings, you can see this below! Or can you? 😑

  ![github traffic page in dark mode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkjevscf53uul9jmwi2y.png)

To look good on any background, you can do the following:

- Have an opaque background for your favicon. Amazon does this, they alway have a white background color.
  ![amazon favicon themes compared](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypa7m2n0d085o3reo96a.png)

- Choose a colour palette that has enough contrast with light and dark backgrounds. Microsoft do this well.

  ![MS favicon themes compared ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3x2to4qolsveln6lmjix.png)

If you don't want to follow the design approaches above, you can cover most scenarios by embedding a style block inside your SVG with the `prefers-color-scheme` media query. This will adapt the favicon to the user's chosen theme. Depending on the style of your favicon, you may want to change the colours used, or you could use a filter to adjust the existing colours.

- You can switch colors or use the invert [CSS filter](https://developer.mozilla.org/en-US/docs/Web/CSS/filter). You can see an example of this [here](https://css-tricks.com/dark-mode-favicons/).

```html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
  <style>
    @media (prefers-color-scheme: dark) {
      path {
        fill: white;
      }
    }
  </style>
    
  <!-- stuff -->
</svg>
```

- If you have a colourful favicon but it needs to be brighter for dark themes, you could use a brightness [CSS filter](https://developer.mozilla.org/en-US/docs/Web/CSS/filter).

```html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
  <style>
    @media (prefers-color-scheme: dark) {
      :root {
        filter: brightness(2);
      }
    }
  </style>

  <!-- stuff -->
</svg>
```

You can also consider adding a shadow to increase contrast of your favicon with the background. This is obviously less effective for dark themes.

## Where should I put the files?

The convention was to put your favicon files in the root directory of your website. You may want to place them in a sub-directory, for example in `/img/favicon/`, just to make things cleaner.  I would still put `favicon.ico` in the root directory, because some web services and older browsers still look here for this file. The rest is covered by what you specify in your meta-data.

Below is an example of how you can organise the files in your website, placing the majority of the image files in a sub-directory:

```
.
├── favicon.ico       // must be named this way and located at root
├── manifest.json     // the convention is to have this in the root dir    
├── img/             // you can choose where to put the rest of the images  
│   └── favicon/
│           └── favicon.svg   
│           └── favicon-180.png   
│           └── favicon-192.png
│           └── favicon-512.png  
```

## Meta-data

You need to add the following to the `head` of your website:

```css
<head>
  <link rel="icon" href="/favicon.ico">
  <link rel="icon" href="/img/favicon/favicon.svg" type="image/svg+xml" sizes="any">
  <link rel="apple-touch-icon" href="/img/favicon/favicon-180.png">
  <link rel="manifest" href="/manifest.json"> 
</head>
```

It is also a good idea to add `<meta name="theme-color" content="<color>"` for consistency. This suggests the color to be used by browsers and apps to style elements of the UI background. For example, browsers might use the color for the page’s title bar. You can specify a media query for the themes also.

```html
<meta name="theme-color" media="(prefers-color-scheme: light)"
content="antiquewhite">
<meta name="theme-color" media="(prefers-color-scheme: dark)"
content="silver">
```

This is what you put in your web app manifest:

```json
{
  "name": "My blog",
  "icons": [
    { "src": "/img/favicon/favicon-192.png", "type": "image/png", "sizes": "192x192" },
    { "src": "/img/favicon/favicon-512.png", "type": "image/png", "sizes": "512x512" }
  ]
}
```

## Optimization

Browsers download favicons in the background, so a bigger image file does not affect website performance, but it is still good practice to optimize the files and respect people's data quotas!

For the SVG, you can optimize the markup and strip out the editor data by using the tools: [SVGOMG (web GUI)](https://jakearchibald.github.io/svgomg/) or [SVGO (command-line)](https://www.npmjs.com/package/svgo).

You can use [tinypng (web GUI)](https://tinypng.com/) or any raster image app for optimizing the PNGs. Typically, the most impactful thing you can do is to reduce the color palette to the minimum required. You should verify the output to ensure it doesn't degrade the appearance.

## Conclusion

Adding a favicon to your website in 2021 is less painful than before, but it is still not a trivial task. You need to consider how your favicon will look in dark and light themes. You need to create 6 files and add the appropriate meta-data to your webpage. It is a bit of work! Hopefully, this article lightened the load for you!

***
**You can subscribe to my [RSS feed](https://www.roboleary.net/feed.xml) to get my latest posts.**