How to create favicons for darkmode (English) 🌚
Tags: darkmode, wordpress, favicon, translated
Published: 2022-03-15 15:24:27

---
title: How to create favicons for darkmode (English) 🌚
published: true
description: How to create favicons for darkmode (English) 🌚
tags: darkmode, wordpress, favicon, translated
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxotqr0f4ce6zqdlaiqh.jpg
---

> This article is also available in [German](https://dev.to/jolution/wie-man-favicons-fur-den-darkmode-erstellt-de-1nn2) 🇩🇪

<!-- TOC -->

- [Motives](#motives)
- [Requirement](#requirement)
- [Create basics](#create-basics)
- [Integration](#integration)
    - [Path](#path)
    - [Files](#files)
    - [WordPress](#wordpress)
        - [Optional: Admin Favicon](#optional-admin-favicon)
        - [Fun: Emoji Favicon](#fun-emoji-favicon)
    - [Typo3](#typo3)
    - [Static](#static)
- [Darkmode](#darkmode)
- [Fallback](#fallback)
    - [Safari](#safari)
    - [Other browsers](#other-browsers)
    - [Future Prospects](#future-prospects)
        - [Manifest color definition](#manifest-color-definition)
        - [PWA / Maskable Icons](#pwa--maskable-icons)
- [Credits](#credits)

<!-- /TOC -->

## Motives

👋🏼 Hello World,

my name is [Julian](https://www.linkedin.com/in/julian-kasimir/). I'm a web developer, and I'm currently working more and more with darkmode.

The topic is about the adaptation of favicons.
Since I work a lot with WordPress, the integration is also thematized.

## Requirement

Since Firefox version 41 (2015) and [Chrome version 80](https://chromestatus.com/feature/5180316371124224) (2019), we can use SVG favicons.
However, there is no support in Safari yet.

For requirements, see Caniuse.com's browser support on the following topics:

1. [SVG favicons in the browser](https://caniuse.com/?search=SVG%20favicons)
2. [CSS Media Querie prefers-color-scheme](https://caniuse.com/?search=prefers-color-scheme)

![Caniuse: https://caniuse.com/?search=SVG%20favicons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv51umhpnz3zq9mbnd63.jpg)

## Create basics

As source file I have my developer logo as SVG for maximum scalability and optimal performance.

Otherwise, an image (PNG, JPG) with the size of 260x260 pixels for best results.

From this we now export the following five formats and sizes:

| Filename             | Size    |
|----------------------|---------|
| favicon.ico          | 32×32   |
| favicon.svg          | -       |
| apple-touch-icon.png | 180×180 |
| icon-192.png         | 192x192 |
| icon-512.png         | 512x512 |


I generate most of the files via the online service [RealFaviconGenerator](https://realfavicongenerator.net). I have left settings for this on the default.

But of course you can use other graphic programs and export the formats like .ico with the help of extensions.
_If an icon does not come along or needs to be readjusted, you can of course export it separately as a file from Illustrator._
_If you have Inkscape at hand, you can also just [generate](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs) it directly from the Console.:_

    inkscape ./icon.svg --export-width=512 --export-filename="./icon-512.png"


Now the following files should be available, which we load (e.g. via sFTP) into the [document root](#path) of the page:

    │   └── public
    |       ├── favicon.ico
    |       ├── favicon.svg
    |       ├── apple-touch-icon.png
    |       ├── icon-192.png
    |       ├── icon-512.png

    |       ├── manifest.webmanifest    (see next paragraph)
    |       ├── favicon_admin.svg       (optional: see next paragraph)


_The specification sizes="any" is currently important, because in Chrome [instead of the svg the ico file](https://bugs.chromium.org/p/chromium/issues/detail?id=1162276) is dragged._

## Integration

### Path

**The documentroot is suitable as the storage path for the icons.**

This has the advantage that favicon.ico can also be used, even if no HTML is used: Example for this, would be files, like [a PDF file that is opened in the browser](https://stackoverflow.com/questions/4886423/display-favicon-for-pdf-files), or [images](https://stackoverflow.com/questions/21359342/is-putting-your-favicon-ico-file-in-a-non-root-path-a-bad-idea).
If this is not possible, you could provide a redirect.

### Files

Manifest file to upload:

Filename: manifest.webmanifest

    {
        "name": "Jolution",
        "short_name": "Jolution",
        "icons": [
            { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
            { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
        ],
        "theme_color": "#292c2f",
        "background_color": "#292c2f",
        "display": "standalone"
    }

Alternative with the minimum specifications:

    {
        "icons": [
            { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
            { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
        ]
    }

### WordPress

    // favicon frontend
    add_action('wp_head', 'custom_favicon');
    function custom_favicon() {
        echo '<link rel="icon" href="/favicon.ico" sizes="any">';
        echo '<link rel="icon" href="/favicon.svg" type="image/svg+xml">';
        echo '<link rel="apple-touch-icon" href="/apple-touch-icon.png">';
        echo '<link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials">';
        echo '<meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)">';
        echo '<meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">';
    }

_Alternatively, we can make it a line here or [concatenate](https://www.php.net/manual/en/language.operators.string.php) (concatenation):_

    add_action('wp_head', 'custom_favicon');
    function custom_favicon() {
        echo '<link rel="icon" href="/favicon.ico" sizes="any"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="manifest" href="/manifest.webmanifest"><meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)"><meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">';
    }

#### Optional: Admin Favicon

As a little goodie to make it easier to differentiate between frontend and backend tabs in Chrome, i have a separate favicon located in the theme.

    // favicon backend
    add_action('login_head', 'custom_favicon_admin');
    add_action('admin_head', 'custom_favicon_admin');
    function custom_favicon_admin() {
        printf('<link rel="icon" href="%s/favicon_admin.svg" type="image/svg+xml">', get_stylesheet_directory_uri());
        echo '<meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)">';
        echo '<meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">';
    }

_If you don't have write-access to the document root and need to put the files in the theme, then you can use the printf statement above instead of echo._

_If you also have the admin-icon in the document root, then you don't need `get_stylesheet_directory_uri()` and can work directly with /favicon_admin.svg:_

    echo '<link rel="icon" href="/favicon_admin.svg" type="image/svg+xml">';

#### Fun: Emoji Favicon

If you like emojis, you can alternatively work with these, see the tweet by [LeaVerou](https://twitter.com/LeaVerou/status/1241619866475474946),
and the online services for this, [emojicon.dev](https://emojicon.dev/) and [fav.farm](https://fav.farm/).

    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><text x='0' y='14'>🌶</text></svg>

### Typo3

Important: Before including the following code, check that the number (=position) 20 is not already assigned and will thus be overwritten.

_If there is already position 20 in your [TypoScript](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/UsingSetting/Index.html), then it is best to check in [increments of 10](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Setup/Page/Index.html#setup-page-1-2-3-4) if 10 or 30 is free._

    headerData {
        20 = TEXT
        20 {
            value (
                <link rel="icon" href="/favicon.ico" sizes="any">
                <link rel="icon" href="/favicon.svg" type="image/svg+xml">
                <link rel="apple-touch-icon" href="/apple-touch-icon.png">
                <link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials">
                <meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)">
                <meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">
            )
        }
    }

Currently, the **alternative embedding option** [`shortcutIcon`](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Setup/Page/Index.html#shortcuticon) allows only one icon:

    page.shortcutIcon = fileadmin/Icons/favicon.ico

The meta information theme-color in the upper part, can not (currently) be included via [`page.meta`](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Setup/Page/Index.html#meta), because no media query can be integrated here.

### Static

In the head of the web page we put the following HTML code:

    <head>

      <link rel="icon" href="/favicon.ico" sizes="any">
      <link rel="icon" href="/favicon.svg" type="image/svg+xml">
      <link rel="apple-touch-icon" href="/apple-touch-icon.png">
      <link rel="manifest" href="/manifest.webmanifest">

      <title>Example</title>
    </head>

_Optionally, the theme-color can also be included above the title:_

    <meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)">
    <meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">

Instead of content="#fff", [CSS-variables](https://css-tricks.com/meta-theme-color-and-trickery/) can also be used here.
_The variables in this example are from TailwindCSS._

    echo '<meta name="theme-color" content="var(--teal-800)" media="(prefers-color-scheme: light)">';
    echo '<meta name="theme-color" content="var(--white)" media="(prefers-color-scheme: dark)">';

## Darkmode

Since SVG is now well-supported by the major browsers, I'll focus only on the SVG file.

With a text program we open it and look at it.
An SVG file can get very large depending on the logo.
You could try to reduce this already in the vector program.
Additionally, you can compress the file with [SVGOMG](https://jakearchibald.github.io/svgomg/) or other [tools for Optimizing SVG](https://css-tricks.com/tools-for-optimizing-svg/).

__Important: Make a backup of the original file before.__

My [developer logo](https://jolution.de/) is a J in a circle.
I exported this as one path, but this is of course not a must. Of course, multiple paths can be addressed.
I have assigned a dark color to the path by default.
If the darkmode is detected, the same path is defined with a white color.

**Expected result:**

Darkmode: Ⓙ

Lightmode: 🅙

    <svg version="1.1" baseProfile="full" width="400" height="400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
	<path d="M200 0A200 200 0 0 0 0 200a200 200 0 0 0 200 200 200 200 0 0 0 200-200 200 200 0 0 0-76.736-157.21l-.028 156.01c0 4.268-.214 8.484-.636 12.64-.422 4.155-1.05 8.25-1.873 12.273-.824 4.023-1.843 7.975-3.047 11.846-1.204 3.87-2.593 7.66-4.157 11.356-1.563 3.697-3.302 7.302-5.205 10.805-1.903 3.504-3.97 6.904-6.19 10.192-2.222 3.288-4.6 6.463-7.118 9.516-2.52 3.052-5.18 5.98-7.977 8.777-2.796 2.796-5.727 5.46-8.78 7.98-3.052 2.518-6.227 4.892-9.515 7.114-3.288 2.22-6.688 4.29-10.19 6.192-3.504 1.903-7.11 3.642-10.806 5.205-3.697 1.564-7.487 2.953-11.357 4.157-3.87 1.203-7.823 2.22-11.846 3.044-4.024.824-8.12 1.45-12.274 1.873-4.156.423-8.372.64-12.64.64-3.914-.005-7.81-.195-11.677-.566-3.867-.372-7.703-.924-11.497-1.653-3.794-.727-7.545-1.633-11.242-2.71-3.696-1.076-7.34-2.324-10.917-3.74-3.577-1.415-7.088-2.997-10.52-4.742-3.435-1.744-6.79-3.65-10.054-5.715-3.267-2.064-6.443-4.285-9.517-6.66s-6.046-4.903-8.904-7.578l28.102-38.64s1.317 1.547 3.84 3.868c1.262 1.16 2.824 2.516 4.676 3.967 1.852 1.452 3.993 3 6.408 4.55 2.415 1.548 5.104 3.096 8.055 4.548 2.952 1.452 6.164 2.808 9.624 3.97 3.46 1.163 7.167 2.133 11.11 2.813 1.97.34 4 .61 6.087.792 2.088.183 4.23.28 6.43.283 2.636 0 5.24-.128 7.81-.38 2.568-.25 5.097-.622 7.583-1.112 2.487-.49 4.93-1.095 7.323-1.812 2.392-.716 4.732-1.545 7.017-2.478 2.285-.933 4.513-1.97 6.678-3.11 2.166-1.137 4.268-2.375 6.3-3.706 2.032-1.332 3.994-2.758 5.88-4.272 1.887-1.513 3.698-3.113 5.427-4.797 1.728-1.684 3.372-3.452 4.93-5.295 1.556-1.843 3.025-3.76 4.398-5.752 1.372-1.99 2.65-4.052 3.826-6.18 1.177-2.126 2.25-4.318 3.218-6.57.966-2.25 1.824-4.562 2.568-6.927.744-2.365 1.374-4.785 1.883-7.252.508-2.466.896-4.983 1.157-7.54.26-2.558.395-5.156.395-7.793l.015-147.084-.045-38.035A200 200 0 0 0 200 0z">
	</path>
	<style>
		path {
			fill: #22343b
		}
		@media (prefers-color-scheme: dark) {
			path{
				fill: #fff
			}
		}
	</style>
    </svg>


Alternatively, instead of changing the color, you can also change the brightness.
Depending on the effort (amount of path adjustments) this can also be a solution.
_Personally, however, I prefer the simple color adjustment._

    @media (prefers-color-scheme: dark) {
      :root {
        filter: brightness(4);
      }
    }

https://codepen.io/jolution/pen/bGadeQY


If you now want to add as meta theme-color, this is also easily [doable](https://css-tricks.com/meta-theme-color-and-trickery/):
    <meta name="theme-color" content="#22343b" media="(prefers-color-scheme: light)">
    <meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)">

## Fallback

### Safari 

Safari unfortunately does not yet support the automatically detectable darkmode.
The normal toggle functions would of course be [no problem](https://www.w3schools.com/howto/howto_js_toggle_dark_mode.asp) here.
_When I have found a solution, I will of course update the article._

    <link rel="mask-icon" href="favicon.svg" color="#22343b">

Feel free to write me in the comments if you have a good and easy approach to this.

### Other browsers

Since not all browsers support the media query features in the link tag, this [polyfill](https://github.com/rumkin/favicon-switcher) fixes that.
However, JS is used here, so I would weigh the use and if in doubt, do without it.

_You can use the favicon checker from realfavicongenerator to [check](https://realfavicongenerator.net/favicon_checker?protocol=https&site=jolution.de#.Yi9ZJrgxlzV) the usage afterwards._
If a browser is missing for your taste, add the meta information from the generator and load the appropriate files.

### Future Prospects

#### Manifest color definition
For some cases it would be ideal to already specify colors for both modes in the manifest.
If you are already interested in this, you can find [further information as well as the exchange](https://github.com/w3c/manifest/issues?q=is%3Aissue+is%3Aopen+%22dark+mode%22) at github in English.

#### PWA / Maskable Icons
At [web.dev](https://web.dev/maskable-icon/?utm_source=devtools) there is a 2019 approach to the topic of PWA on the topic of "maskable icons".

## Credits

Thanks to Andrey Sitnik (author of PostCSS and Autoprefixer) who gathered the above measurements as [optimal set](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).
And also to Houssein Djirdeh (Software Engineer at @GoogleChrome) who also [uses](https://web.dev/add-manifest-react/) these specifications with 512x512.

Good luck and have fun with the implementation.