How to create favicons for darkmode (English) š
Jolution
Posted on March 15, 2022
This article is also available in German š©šŖ
Motives
šš¼ Hello World,
my name is Julian. 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 (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:
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. 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 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 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 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, or images.
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 (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,
and the online services for this, emojicon.dev and 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, then it is best to check in increments of 10 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
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
, 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 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 or other tools for Optimizing SVG.
Important: Make a backup of the original file before.
My developer logo 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:
Fallback
Safari
Safari unfortunately does not yet support the automatically detectable darkmode.
The normal toggle functions would of course be no problem 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 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 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 at github in English.
PWA / Maskable Icons
At web.dev 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.
And also to Houssein Djirdeh (Software Engineer at @GoogleChrome) who also uses these specifications with 512x512.
Good luck and have fun with the implementation.
Posted on March 15, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.