Normalerweise wird für eine ganze Domain ein einziges Favicon verwendet. Aber manchmal möchte man mehr und unterschiedliche Favicons je nach Kontext einsetzen. Eine Website könnte das Favicon ändern, um den angezeigten Inhalten zu entsprechen. Oder eine Seite könnte es Benutzern ermöglichen, ihre Theme-Farben zu personalisieren, und diese Präferenzen werden im Favicon widergespiegelt. Vielleicht haben Sie Favicons gesehen, die versuchen, den Benutzer auf ein bestimmtes Ereignis aufmerksam zu machen.
Mehrere Favicons können technisch von Hand verwaltet werden – Chris hat uns gezeigt, wie er zwei verschiedene Favicons für Entwicklung und Produktion verwendet. Aber wenn Sie Hunderte von Variationen benötigen, ist es Zeit, sie dynamisch zu generieren.
Das war die Situation, mit der ich bei einem kürzlichen WordPress-Projekt für ein Verzeichnis von Colleges und Universitäten konfrontiert war. (Ich habe zuvor über Abfragen von Standorten in der Nähe für dasselbe Projekt geschrieben.) Beim Aufrufen des Profils einer Schule sollte das Favicon die Farben der Schule und nicht unser Standardblau verwenden, um ihm das gewisse Etwas zu verleihen.
Bei über 200 Schulen im Verzeichnis und steigender Zahl mussten wir auf dynamische Lösungen umsteigen. Glücklicherweise hatten wir bereits benutzerdefinierte Metafelder, die Daten zur visuellen Identität jeder Schule speicherten. Dazu gehörten Schulfarben, die im Stylesheet verwendet wurden. Wir brauchten nur einen Weg, diese benutzerdefinierten Metafarben auf ein dynamisches Favicon anzuwenden.
In diesem Artikel führe ich Sie durch unseren Ansatz und einige Dinge, auf die Sie achten sollten. Sie können die Ergebnisse in Aktion sehen, indem Sie verschiedene Schulen aufrufen.

SVG ist der Schlüssel
Dank der verbesserten Browserunterstützung für SVG-Favicons ist die Implementierung dynamischer Favicons viel einfacher als früher. Im Gegensatz zu PNG (oder dem veralteten ICO-Format) basiert SVG auf Markup zur Definition von Vektorgrafiken. Das macht sie leichtgewichtig, skalierbar und vor allem empfänglich für alle möglichen Spielereien.
Der erste Schritt ist die Erstellung Ihres Favicons im SVG-Format. Es schadet nicht, es danach auch durch einen SVG-Optimizer laufen zu lassen, um unnötigen Ballast zu entfernen. Dies haben wir im Schulverzeichnis verwendet.
In WordPress einhängen
Als Nächstes möchten wir die Favicon-Link-Markup im HTML-Head hinzufügen. Wie Sie das tun, ist Ihnen überlassen. Im Fall von WordPress könnte es zum Header-Template eines Child-Themes hinzugefügt oder über eine wp_head()-Aktion echo-ed werden.
function ca_favicon() {
if ( is_singular( 'school' ) ) {
$post_id = get_the_ID();
$color = get_post_meta( $post_id, 'color', true );
if ( isset( $color ) ) {
$color = ltrim( $color, '#' ); // remove the hash
echo '<link rel="icon" href="' . plugins_url( 'images/favicon.php?color=' . $color, __FILE__ ) . '" type="image/svg+xml" sizes="any">';
}
}
}
add_filter( 'wp_head' , 'ca_favicon' );
Hier prüfen wir, ob der Post-Typ school ist, und holen die color-Metadaten der Schule, die wir zuvor mit get_post_meta() gespeichert haben. Wenn wir eine Farbe haben, übergeben wir sie über die Query-String an favicon.php.
Von PHP zu SVG
In einer Datei namens favicon.php beginnen wir damit, den Content-Type auf SVG zu setzen. Als Nächstes speichern wir den übergebenen Farbwert oder verwenden die Standardfarbe, wenn keine vorhanden ist.
Dann geben wir den großen, mehrzeiligen SVG-Markup mit Herdoc-Syntax von PHP aus (nützlich für Templating). Variablen wie $color werden bei Verwendung dieser Syntax erweitert.
Schließlich nehmen wir ein paar Änderungen am SVG-Markup vor. Erstens werden Klassen den farbwechselnden Elementen zugewiesen. Zweitens wird ein Style-Element direkt im SVG-Element hinzugefügt, das die entsprechenden CSS-Regeln deklariert und $color ausgibt.
Anstelle eines <style>-Elements könnten wir alternativ die Standardfarbe durch $color ersetzen, wo immer sie erscheint, wenn sie nicht an zu vielen Stellen verwendet wird.
<?php
header( 'Content-Type: image/svg+xml' );
$color = $_GET[ 'color' ] ?? '065281';
$color = sanitize_hex_color_no_hash( $color );
echo <<<EOL
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
<style type="text/css">
<![CDATA[
.primary {
fill: #$color;
}
.shield {
stroke: #$color;
}
]]>
</style>
<defs>
<path id="a" d="M0 34L318 0l316 34v417.196a97 97 0 01-14.433 50.909C483.553 722.702 382.697 833 317 833S150.447 722.702 14.433 502.105A97 97 0 010 451.196V34z"/>
</defs>
<g fill="none" fill-rule="evenodd">
<g transform="translate(183 65)">
<mask id="b" fill="#fff">
<use xlink:href="#a"/>
</mask>
<use fill="#FFF" xlink:href="#a"/>
<path class="primary" mask="url(#b)" d="M317-37h317v871H317z"/>
<path class="primary" mask="url(#b)" d="M0 480l317 30 317-30v157l-317-90L0 517z"/>
<path fill="#FFF" mask="url(#b)" d="M317 510l317-30v37l-317 30z"/>
</g>
<g fill-rule="nonzero">
<path class="primary" d="M358.2 455.2c11.9 0 22.633-.992 32.2-2.975 9.567-1.983 18.375-4.9 26.425-8.75 8.05-3.85 15.458-8.458 22.225-13.825 6.767-5.367 13.3-11.433 19.6-18.2l-34.3-34.65c-9.567 8.867-19.192 15.867-28.875 21-9.683 5.133-21.525 7.7-35.525 7.7-10.5 0-20.125-2.042-28.875-6.125s-16.217-9.625-22.4-16.625-11.025-15.167-14.525-24.5-5.25-19.25-5.25-29.75v-.7c0-10.5 1.75-20.358 5.25-29.575 3.5-9.217 8.4-17.325 14.7-24.325 6.3-7 13.825-12.483 22.575-16.45 8.75-3.967 18.258-5.95 28.525-5.95 12.367 0 23.508 2.45 33.425 7.35 9.917 4.9 19.658 11.667 29.225 20.3l34.3-39.55a144.285 144.285 0 00-18.2-15.4c-6.533-4.667-13.65-8.633-21.35-11.9-7.7-3.267-16.275-5.833-25.725-7.7-9.45-1.867-19.892-2.8-31.325-2.8-18.9 0-36.167 3.325-51.8 9.975-15.633 6.65-29.05 15.75-40.25 27.3s-19.95 24.967-26.25 40.25c-6.3 15.283-9.45 31.675-9.45 49.175v.7c0 17.5 3.15 33.95 9.45 49.35 6.3 15.4 15.05 28.758 26.25 40.075 11.2 11.317 24.5 20.242 39.9 26.775 15.4 6.533 32.083 9.8 50.05 9.8z"/>
<path fill="#FFF" d="M582.35 451l22.4-54.95h103.6l22.4 54.95h56.35l-105-246.75h-49.7L527.4 451h54.95zM689.1 348.45H624L656.55 269l32.55 79.45z"/>
</g>
<path class="shield" stroke-width="30" d="M183 99l318-34 316 34v417.196a97 97 0 01-14.433 50.909C666.553 787.702 565.697 898 500 898S333.447 787.702 197.433 567.105A97 97 0 01183 516.196V99h0z"/>
</g>
</svg>
EOL;
?>
Damit haben Sie ein dynamisches Favicon auf Ihrer Website zum Laufen gebracht.
Sicherheitsüberlegungen
Natürlich öffnet das blinde echo von URL-Parametern Tür und Tor für Hacking. Um dies zu mindern, sollten wir alle unsere Eingaben bereinigen.
In diesem Fall interessieren wir uns nur für Werte, die dem 3- oder 6-stelligen Hex-Farbformat entsprechen. Wir können eine Funktion wie die eigene sanitize_hex_color_no_hash() von WordPress einfügen, um sicherzustellen, dass nur Farben übergeben werden.
function sanitize_hex_color( $color ) {
if ( '' === $color ) {
return '';
}
// 3 or 6 hex digits, or the empty string.
if ( preg_match( '|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) {
return $color;
}
}
function sanitize_hex_color_no_hash( $color ) {
$color = ltrim( $color, '#' );
if ( '' === $color ) {
return '';
}
return sanitize_hex_color( '#' . $color ) ? $color : null;
}
Sie sollten Ihre eigenen Prüfungen basierend auf den Werten hinzufügen, die Sie übergeben möchten.
Caching für bessere Leistung
Browser cachen SVGs, aber dieser Vorteil geht bei PHP-Dateien standardmäßig verloren. Das bedeutet, dass jedes Mal, wenn das Favicon geladen wird, Ihr Server beansprucht wird.
Um die Serverbelastung zu reduzieren und die Leistung zu verbessern, ist es unerlässlich, diese Datei explizit zu cachen. Sie können Ihren Server konfigurieren, eine Seitenregel über Ihr CDN einrichten oder einen Cache-Control-Header ganz oben in favicon.php hinzufügen, wie hier:
header( 'Cache-Control: public, max-age=604800' ); // 604,800 seconds or 1 week
In unseren Tests dauerte unsere 1,5 KB große SVG-Datei ohne Caching beim ersten Laden etwa 300 Millisekunden und bei nachfolgenden Läufen etwa 100 Millisekunden. Das ist ziemlich schlecht. Aber mit Caching brachten wir dies von 25 ms vom CDN beim ersten Laden und 1 ms vom Browser-Cache bei späteren Läufen auf – so gut wie ein einfaches altes SVG.
Browser-Unterstützung
Wenn wir dort fertig wären, wäre das keine Webentwicklung. Wir müssen immer noch über die Browserunterstützung sprechen.
Wie bereits erwähnt, ist die moderne Browserunterstützung für SVG-Favicons solide und in aktuellen Versionen von Chrome, Firefox und Edge vollständig unterstützt.

Eine Einschränkung ist, dass Firefox das Attribut type="image/svg+xml" in der Favicon-Deklaration benötigt, damit es funktioniert. Die anderen Browser sind nachsichtiger, aber es ist einfach eine gute Praxis. Sie sollten dabei auch sizes="any" einfügen.
<link rel="icon" href="path/to/favicon.svg" type="image/svg+xml" sizes="any">
Safari
Safari unterstützt SVG-Favicons derzeit nicht, abgesehen von der Mask-Icon-Funktion für angeheftete Tabs. In meinen Experimenten war dies fehlerhaft und inkonsistent. Es verarbeitete komplexe Formen oder Farben schlecht und cach-te dasselbe Icon für die gesamte Domain. Letztendlich entschieden wir uns, uns nicht darum zu kümmern und einfach einen Fallback mit der Standard-Blaufüllung zu verwenden, bis Safari die Unterstützung verbessert.
Fallback-Optionen
So gut die SVG-Favicon-Unterstützung auch ist, sie ist immer noch nicht 100%. Stellen Sie also sicher, dass Sie Fallbacks hinzufügen. Wir können ein zusätzliches Favicon für den Fall einstellen, dass SVG-Icons nicht unterstützt werden, mit dem Attribut rel="alternative icon".
<link rel="icon" href="path/to/favicon.svg" type="image/svg+xml" sizes="any">
<link rel="alternate icon" href="path/to/favicon.png" type="image/png">
Um die Website noch robuster zu machen, können Sie auch die ewige favicon.ico in Ihrem Root-Verzeichnis ablegen.
Weiter geht's
Wir haben ein relativ einfaches Favicon genommen und eine Farbe durch eine andere ersetzt. Aber dieser dynamische Ansatz öffnet die Tür zu viel mehr: Modifizieren von mehreren Farben, anderen Eigenschaften wie position, völlig anderen Formen und Animationen.
Zum Beispiel hier eine Demo, die ich Favicoin getauft habe. Sie stellt Kryptowährungspreise als Sparkline im Favicon dar.

Die Implementierung dynamischer Favicons wie dieser ist nicht auf WordPress oder PHP beschränkt; was auch immer Ihr Stack ist, die gleichen Prinzipien gelten. Sie könnten dies sogar clientseitig mit Data-URLs und JavaScript erreichen... ich empfehle es aber nicht für den Produktionseinsatz.
Eines ist jedoch sicher: Wir werden in Zukunft kreative Anwendungen von SVG-Favicons sehen. Haben Sie dynamische Favicons gesehen oder erstellt? Haben Sie Tipps oder Tricks zu teilen?
Großartige Arbeit! (In dem Sinne, dass alles klar ist, aber für den Neuling nichts klar ist :). Das wäre toll für ein WP-Plugin. Außerdem haben Sie es im Grunde bereits erstellt. Ist ein fertiges Produkt zu erwarten?