Jolution
Posted on March 15, 2022
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:
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"
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)
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"
}
Alternative mit den Minimum-Angaben:
{
"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)">';
}
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)">';
}
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)">';
}
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">';
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>
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)">
)
}
}
Aktuell lässt die alternative Einbindungsmöglichkeit shortcutIcon
nur ein Icon zu:
page.shortcutIcon = fileadmin/Icons/favicon.ico
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>
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)">
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)">';
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>
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);
}
}
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">
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.
Posted on March 15, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.