Wie man Favicons für den Darkmode erstellt (German) 🌚

jolution

Jolution

Posted on March 15, 2022

Wie man Favicons für den Darkmode erstellt (German) 🌚

Dieser Artikel ist auch in Englisch verfügbar 🇬🇧

Beweggründe

👋🏼 Hello World,

mein Name ist Julian. Ich bin Webentwickler und setze mich beruflich aktuell vermehrt mit dem Darkmode auseinander.

Das Thema handelt über die Anpassung der Favicons.
Da ich viel mit Wordpress arbeite, wird auch die Einbindung thematisiert.

Voraussetzung

Seit der Firefox Version 41 (2015) und der Chrome Version 80 (2019) können wir SVG-Favicons nutzen.
In Safari gibt es allerdings noch keinen Support.

Zu den Voraussetzungen siehe hierzu den Browser-Support von Caniuse.com zu folgenden Themen:

  1. SVG Favicons im Browser
  2. CSS Media Querie prefers-color-scheme

Caniuse: https://caniuse.com/?search=SVG%20favicons

Grundlagen erstellen

Als Ausgangsdatei habe ich für maximale Skalierbarkeit und optimale Performance mein Entwickler-Logo als SVG vorliegen.

Andernfalls ein Bild (PNG, JPG) mit der Größe von 260x260 Pixeln für optimale Ergebnisse.

Daraus exportieren wir nun folgende fünf Formate und Größen:

Datei Größe
favicon.ico 32×32
favicon.svg -
apple-touch-icon.png 180×180
icon-192.png 192x192
icon-512.png 512x512

Die Dateien generiere ich über den Onlinedienst RealFaviconGenerator. Einstellungen habe ich hierfür auf der Standardausführung gelassen.

Du kannst natürlich aber auch andere Grafikprogramme nutzen und mithilfe von Erweiterungen die Formate wie .ico exportieren.
Sollte ein Icon nicht mitkommen oder nachjustiert werden müssen, kann man es natürlich auch gesondert als Datei aus Illustrator exportieren.
Wenn du Inkscape zur Hand hast, kannst du es auch einfach direkt über die Console generieren:

inkscape ./icon.svg --export-width=512 --export-filename="./icon-512.png"
Enter fullscreen mode Exit fullscreen mode

Nun sollten folgende Dateien vorliegen, welche wir (bspw. per sFTP) in den Dokument Root der Seite laden:

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

|       ├── manifest.webmanifest    (Siehe hierzu nächster Abschnitt)
|       ├── favicon_admin.svg       (Optional: Siehe hierzu nächster Abschnitt)
Enter fullscreen mode Exit fullscreen mode

Die Angabe sizes="any" ist aktuell wichtig, da in Chrome statt dem svg die ico Datei gezogen wird.

Einbindung

Pfad

Als Ablagepfad für die Icons eignet sich der Documentroot.

Dies hat den Vorteil das, dass favicon.ico ebenfalls zum Einsatz kommen kann, wenn auch kein HTML verwendet wird: Beispiel hierfür, wären Dateien, wie eine PDF Datei die im Browser geöffnet wird, oder Bilder.
Falls dies nicht möglich ist, könnte man hier einen Redirect vorsehen.

Dateien

Manifest-Datei zum Hochladen:

Dateiname: 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"
}
Enter fullscreen mode Exit fullscreen mode

Alternative mit den Minimum-Angaben:

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

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)">';
}
Enter fullscreen mode Exit fullscreen mode

Alternativ können wir hier auch eine Zeile daraus machen oder verketten (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)">';
}
Enter fullscreen mode Exit fullscreen mode

Optional: Admin Favicon

Als kleines Goodie, um einfacher zwischen Frontend und Backend Tabs in Chrome zu unterscheiden, habe ich im Theme eine gesonderte Favicon liegen:

// 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)">';
}
Enter fullscreen mode Exit fullscreen mode

Solltest du kein Schreibzugriff auf den Documentroot haben und die Dateien in das Theme legen müssen, dann kannst du statt echo die printf Anweisung oben verwenden.

Wenn du das Admin-Icon ebenfalls im Document Root liegen hast, dann benötigst du get_stylesheet_directory_uri() nicht und kannst direkt mit /favicon_admin.svg arbeiten:

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

Fun: Emoji Favicon

Wer Emojis mag, kann alternativ auch mit diesen arbeiten, siehe hierzu den Tweet von LeaVerou,
sowie die Online-Dienste hierzu, emojicon.dev und fav.farm.

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

Typo3

Wichtig: Vor dem Einbinden des folgenden Codes prüfen, dass die Zahl (=Position) 20 nicht schon vergeben ist und somit überschrieben wird.

Falls es bereits die Position 20 in Ihrem TypoScript gibt, dann prüfen Sie am besten in 10er Schritten, ob die 10 oder 30 frei ist.

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)">
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

Aktuell lässt die alternative Einbindungsmöglichkeit shortcutIcon nur ein Icon zu:

page.shortcutIcon = fileadmin/Icons/favicon.ico
Enter fullscreen mode Exit fullscreen mode

Die Meta-Angaben theme-color im oberen Teil, lässt sich (aktuell) leider nicht über page.meta einbinden, da hier kein media Abfrage integriert werden kann.

Static

In den Head der Webseite packen wir nun folgenden 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>
Enter fullscreen mode Exit fullscreen mode

Optional kann auch zusätzlich, oberhalb des title, die theme-color eingebunden werden:

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

Statt content="#fff" kann hier auch auf CSS-Variablen gesetzt werden.
Die Variablen in diesem Beispiel stammen von 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)">';
Enter fullscreen mode Exit fullscreen mode

Darkmode

Da SVG mittlerweile von den großen Browsern gut unterstützt wird, konzentriere ich mich nur auf die SVG-Datei.

Mit einem Textprogramm öffnen wir diese und schauen uns diese an.
Eine SVG-Datei kann je nach Logo sehr groß werden.
Du könntest versuchen dies bereits im Vektorenprogramm zu reduzieren.
Zusätzlich kannst du mit SVGOMG oder anderen Diensten zur Optimierung die SVG-Datei komprimieren.

Wichtig: Vorher ein Backup der Originaldatei erstellen.

Mein Entwickler-Logo ist ein J in einem Kreis.
Dies habe ich als ein Pfad exportiert, dass ist aber natürlich kein Muss. Natürlich können auch mehrere Pfade angesprochen werden.
Dem Pfad habe ich nun standardmäßig eine dunkle Farbe zugewiesen.
Wird der Darkmode erkannt, wird der gleiche Pfad mit einer weißen Farbe definiert.

Erwartetes Resultat:

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>
Enter fullscreen mode Exit fullscreen mode

Alternativ kannst du statt einer Farbänderung auch die Helligkeit verändern.
Das kann je nach Aufwand (Menge der Pfadanpassungen) auch eine Lösung sein.
Ich persönlich bevorzuge allerdings die einfache Farbanpassung.

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

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

Wenn du nun noch als Meta theme-color hinzufügen möchtest, ist dies auch einfach machbar:

Fallback

Safari

Safari unterstützt den automatisch erkennbaren Darkmode leider noch nicht.
Die normalen Toggle-Funktionen wären hier natürlich kein Problem.
Wenn ich eine Lösung gefunden habe, aktualisiere ich den Artikel natürlich.

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

Schreibt mir gerne in die Kommentare, wenn Ihr einen guten und leichten Ansatz dafür habt.

Andere Browser

Da nicht alle Browser die Medienabfragefunktionen im Link-Tag unterstützen, behebt dieses Polyfill dies.
Hier wird allerdings JS verwendet, daher würde ich den Einsatz abwiegen und im Zweifelsfall darauf verzichten.

Mit dem Favicon checker von realfavicongenerator kann man den Einsatz anschließend prüfen.
Sollte für euren Geschmack noch ein Browser fehlen, ergänzt die Meta Angaben durch die von dem Generator und ladet die entsprechenden Dateien dazu.

Aussichten

Manifest Farbdefinition

Für manche Fälle wäre es ideal im Manifest bereits Farben für beide Modes anzugeben.
Wer sich dafür jetzt schon interessiert, findet bei github auf Englisch weiterführende Informationen sowie den Austausch.

PWA / Maskable Icons

Bei web.dev gibt es zu dem Thema PWA einen Ansatz von 2019 zum Thema "maskable icons".

Credits

Danke an Andrey Sitnik (Autor von PostCSS und Autoprefixer) der die oben aufgeführten Maße als optimales Set zusammengetragen hat.
Und auch an Houssein Djirdeh (Software Engineer bei @GoogleChrome) der diese Angaben mit 512x512 ebenfalls verwendet.

Viel Erfolg und Spaß bei der Umsetzung.

P.s. Wenn dich das Thema Darkmode, ganz allgemein, interessiert, ist mein Artikel bei Medium vielleicht Interessant für dich.

💖 💪 🙅 🚩
jolution
Jolution

Posted on March 15, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related