Eigene Icons in WordPress 7.1

Bereits im Mai dieses Jahres brachte WordPress 7.0 einen neuen nativen Icon-Block, der es erlaubt SVG Icons im Block Editor einzusetzen. Leider waren diese jedoch auf die WordPress-eigene Icon-Bibliothek beschränkt und es gab bisher keine standardisierte Schnittstelle, um eigene Grafiken ohne weiteres hinzuzufügen.

Mit der letzte Woche erschienenen Version 7.1 lassen sich nun auch eigene Icons registrieren, die dann im Block-Editor zur Verfügung stehen.

Wir haben uns diese neuen Funktionen einmal angesehen und experimentiert, wie wir das Ganze einsetzen könnten und welche Einschränkungen es aktuell noch gibt.

Warum überhaupt Custom Icons?

Die mitgelieferte Bibliothek bietet eine grosse Anzahl an Icons, die aus dem offiziellen @wordpress/icons Package stammen, welches auch WP-intern verwendet wird. Diese sind zwar hübsch und für viele Anwendungen ganz praktisch, für Projekte die Wert auf ein eigenes Branding legen, kommen diese aber nicht in Frage. Häufig gibt es CI/CD Vorgaben, die definieren wie diese auszusehen haben, oder es bestehen sogar bereits eigene Icon-Bibliotheken. Diese zu verwenden war bisher nur auf Umwegen möglich, weil eine einfache Art den Icon Block zu erweitern bisher fehlte.

Icons Registrieren mit WP 7.1+

Die folgenden neuen Funktionen sind für die Registrierung der Icons verantwortlich:

Erstere erstellt eine «Sammlung» in der die Icons gruppiert werden können. Diese wird im Editor in der linken Spalte des Icon Blocks angezeigt.

Screenshot der geöffneten Icon library im Editor, wo die Icons ausgewählt werden.

Mit der zweiten Funktion werden dann die einzelnen Icons registriert. Der SVG Code dazu kann entweder direkt als inline SVG oder als Pfad zu einem SVG-File angegeben werden. Für die anschliessende Ausgabe spielt das keine Rolle und beide werden identisch (inlined) ausgegeben.

Ein Code Beispiel aus der offiziellen Dokumentation zeigt beide Optionen:

function my_plugin_register_icons() {
	// Register a custom collection first, then add icons to it.
	wp_register_icon_collection(
		'my-plugin',
		array(
			'label' => __( 'My Plugin Icons', 'my-plugin' ),
		)
	);

	// An icon from an inline SVG string.
	wp_register_icon(
		'my-plugin/star',
		array(
			'label'   => __( 'Star', 'my-plugin' ),
			'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
		)
	);

	// An icon from an .svg file shipped with the plugin.
	wp_register_icon(
		'my-plugin/heart',
		array(
			'label'     => __( 'Heart', 'my-plugin' ),
			'file_path' => plugin_dir_path( __FILE__ ) . 'icons/heart.svg',
		)
	);
}
add_action( 'init', 'my_plugin_register_icons' );Code language: PHP (php)

Eigene Icon-Bibliotheken

Bei Projekten mit Custom Icons können es schnell mal mehr als eine Handvoll Grafiken sein die verwendet werden sollen, weshalb wir uns die Registrierung der Icons so einfach wie möglich machen möchten.

Dazu haben wir uns zwei kleine experimentelle Helfer-Funktionen gebaut, die wir je nach Projekt und Anforderungen einsetzen können. Welche sich dann in der Praxis durchsetzt, wird sich noch zeigen, in unseren ersten Tests haben aber beide bereits ganz gut funktioniert.

Die beiden Funktionen hier sind für den Einsatz in einem Theme gedacht, könnten aber mit kleineren Anpassungen der Pfade auch in einem Plugin verwendet werden.

Variante 1: Vollautomatische Registrierung

Im einfachsten Fall geben wir die ganze Kontrolle ab und registrieren schlicht alle Icons, die sich in einem bestimmten Ordner befinden in einer eigenen Sammlung. Für die Bezeichnung des Icons wird dabei der Dateiname verwendet: aus arrow-left.svg wird automatisch «Arrow Left».

Möchten wir ein neues Icon hinzufügen, muss dieses nur noch in den richtigen Ordner platziert werden und steht ab da im Editor zur Verfügung, ohne dass weitere Änderungen im Code nötig wären.

Die Einfachheit dieser Quick & Dirty Variante hat allerdings auch ihren Preis: da die Beschriftungen der Icons dynamisch generiert werden, können diese nicht übersetzbar gemacht werden. Kann man darauf jedoch verzichten, erspart man sich die manuelle Registrierung der einzelnen Icons und hat damit einen sehr einfachen Weg, neue Grafiken hinzuzufügen.

/**
 * Register Custom Theme Icons automatically
 * 
 */
function haptiq_register_icons_automatically() {
	wp_register_icon_collection(
		'haptiq-theme',
		array(
			'label' => __( 'Haptiq Theme', 'my-theme' ),
		)
	);

	$icons_dir = get_theme_file_path( 'assets/icons/ );
	$svg_files = glob( $icons_dir . '*.svg' );

	if ( $svg_files ) {
		foreach ( $svg_files as $svg_file ) {
			// e.g. "heart.svg" → "heart"
			$name = basename( $svg_file, '.svg' );

			// Turn filename into a readable label: "arrow-left" → "Arrow Left"
			$label = ucwords( str_replace( array( '-', '_' ), ' ', $name ) );

			wp_register_icon(
				'haptiq-theme/' . $name,
				array(
					'label'     => $label,
					'file_path' => $svg_file,
				)
			);
		}
	}
}
add_action( 'init', 'haptiq_register_icons_automatically' );Code language: PHP (php)

Bitte beachte hier auch, dass das automatische Auslesen zu Performance-Einbussen führen kann. Der Code hier ist zur Inspiration gedacht, und sollte in der Praxis sicher noch optimiert und z. B. mit etwas Caching erweitert werden.

Variante 2: Icon Bibliothek als Arrays definieren

Wir versuchen grundsätzlich alle unsere Projekte so zu entwickeln, dass diese übersetzbar sind, selbst wenn vielleicht anfangs nur eine Sprache benötigt wird. Meist ist dies die günstigere Variante, als später alles umzubauen, wenn die Seite doch übersetzbar werden soll.

Damit die Labels der Icons ebenfalls übersetzt werden können, müssen die entsprechenden Strings zusammen mit den Icons registriert werden. Um uns auch hier die Arbeit etwas zu vereinfachen, definieren wir diesmal die Collections und Icons in verschachtelten Arrays, durch die wir dann durch iterieren können:

/**
 * Register Custom Theme Icons manually
 * 
 */
function haptiq_register_icons_manually() {
    $icons_dir = get_theme_file_path( 'assets/icons/' );

    $collections = array(
        'haptiq-ui' => array(
            'label' => __( 'UI Icons', 'my-theme' ),
            'icons' => array(
                'arrow-left'  => __( 'Arrow Left', 'my-theme' ),
                'arrow-right' => __( 'Arrow Right', 'my-theme' ),
                'close'       => __( 'Close', 'my-theme' ),
                'menu'        => __( 'Menu', 'my-theme' ),
                'search'      => __( 'Search', 'my-theme' ),
            ),
        ),
        'haptiq-social' => array(
            'label' => __( 'Social Icons', 'my-theme' ),
            'icons' => array(
                'github'   => __( 'GitHub', 'my-theme' ),
                'mastodon' => __( 'Mastodon', 'my-theme' ),
                'bluesky' => __( 'Bluesky', 'my-theme' ),
            ),
        ),
    );

    foreach ( $collections as $collection_slug => $collection ) {
        wp_register_icon_collection(
            $collection_slug,
            array(
                'label' => $collection['label'],
            )
        );

        foreach ( $collection['icons'] as $icon_slug => $icon_label ) {
            wp_register_icon(
                $collection_slug . '/' . $icon_slug,
                array(
                    'label'     => $icon_label,
                    'file_path' => $icons_dir . $icon_slug . '.svg',
                )
            );
        }
    }
}
add_action( 'init', 'haptiq_register_icons_manually' );Code language: PHP (php)

Dies ermöglicht die Übersetzung der Labels und gibt uns etwas mehr Kontrolle über die Registrierung, während die benötigten Anpassungen für neue Icons überschaubar bleiben.

Einschränkungen

Die Verwendung eigener Icons wurde mit diesen neuen Schnittstellen in WordPress 7.1 viel einfacher. Es gibt allerdings auch noch einige Einschränkungen und Besonderheiten die man kennen sollte, insbesondere was die Erstellung der SVGs betrifft.

Strenges SVG Escaping

Der Icon Block ist relativ streng, was das Escaping der SVG Files betrifft und lässt aktuell nur <svg><path>, und <polygon> Elemente zu, der Rest wird automatisch entfernt. Dies könnte sich aber schon bald ändern, am Support für weitere Elemente wie <circle><rect> und anderen wird bereits gearbeitet.

Stroke Attribut nicht unterstützt

Auch das stroke Attribut in SVG fällt aktuell noch dem strengen Escaping zum Opfer, es können also aktuell nur Icons verwendet werden, die mit fills aufgebaut sind. In der Regel lässt sich dies problemlos so umsetzen oder umwandeln, ist aber gut zu wissen falls die bestehende Icon-Library nicht funktionieren sollte.

CSS-Klassen + IDs

Ebenfalls werden CSS-Klassen oder ID’s innerhalb der SVG Files ersatzlos entfernt, nur das SVG Element selbst darf diese behalten. Wir verwenden diese gerne für Animationen wie z. B. einfache hover Effekte, was damit momentan leider noch erschwert wird.

Mehrfarbigkeit

Aktuell «verstehen» die Icons im Editor nur eine Farbe. Mehrfarbige SVGs können zwar problemlos verwendet werden, und sogar CSS Variablen lassen sich einsetzen und bleiben bestehen. Im Editor bearbeitbar ist allerdings immer nur eine Farbe. Ziemlich genial wäre es, wenn alle verwendeten Farben im Editor erkannt und dann angepasst werden könnten.

Fazit

Wir sitzen gerade an einem Relaunch-Projekt (mehr dazu in Kürze), bei dem eigene Icons zum Einsatz kommen werden, weshalb diese neuen Möglichkeiten für uns gerade zur rechten Zeit kamen. Vieles, was wir benötigen, lässt sich damit bereits abdecken, und wir sind zuversichtlich, dass einige der oben aufgeführten Einschränkungen ebenfalls bald behoben sein könnten. Wir werden die Entwicklung auf jeden Fall weiterverfolgen und den Icon Block in Zukunft vermehrt in Projekten einsetzen.

Hast du schon Erfahrungen mit dem neuen Icon Block gemacht oder Fragen zur Integration oder Migration deiner bestehenden Icon-Bibliothek?

Melde dich bei uns und wir beraten dich gerne persönlich.

Claudio Rimann ist einer der Gründer der Haptiq GmbH. Selbständig seit 2011. Background im Marketing und Print-Design. Autodidakt. Designer aus Leidenschaft. Unrehabilitierbarer Digital-Junkie. Twitter, LinkedIn, Blog