SVG Icons im WordPress Theme einbinden und anzeigen

In diesem Tutorial zeige ich, wie du SVG Icons anstelle eines Icon Fonts im WordPress Theme nutzen kannst. Die Beispiele zeigen die Einbindung mit externer SVG Datei sowie als Inline Markup. Nützliche Code Schnipsel zur Anzeige der SVG Icons runden den Beitrag ab.

Für mein neuestes WordPress Theme erwäge ich den Einsatz von SVG Icons anstelle eines Icon Fonts. Das Thema SVG stand spätestens mit dem Einsatz von SVG Icons in TwentySeventeen auf meiner ToDo List. Die letzten Tage war es dann endlich soweit, sich damit etwas näher zu beschäftigen.

Bis dato verwende ich den Genericons Icon Font von Automattic in fast allen meiner Themes. Im Gegensatz zu Font Awesome handelt es sich um einen wesentlich kleineren Font mit den wichtigsten Icons. Font Awesome war mir immer zu groß für meine Themes, in denen ich meist nur eine Handvoll Icons brauche.

Auf die Vorteile von SVG Icons gegenüber Icon Fonts möchte ich an dieser Stelle nicht erneut eingehen. Hier empfehle ich den Beitrag von Bernhard Kau über SVG Icons im neuen Default Theme sowie den T3N Artikel SVGs FTW von Florian Brinkmann.

In diesem Tutorial möchte ich mich auf die verschiedenen Möglichkeiten zur Einbindung von SVG Icons im WordPress Theme konzentrieren.

SVG Sprite

Zu Beginn benötigen wir ein SVG Sprite. Dabei handelt es sich um eine .svg-Datei, in der alle Icons definiert sind.

Wie bei Icon Fonts kann auch hier auf bestehende Icon Sets zurückzugegriffen werden.

Ich selbst verwende nun Genericons Neue von Automattic, dem Nachfolger der bereits erwähnten Genericons. Eine Übersicht und Vorschau der Icons ist unter genericons.com zu finden. Während Genericons Neue auch als Icon Font eingesetzt werden kann, enthält es außerdem eine SVG Sprite Datei.

Viele existierende Icon Fonts enthalten leider noch keine SVG Sprites, um die Icons als SVG einbinden zu können. Abhilfe schafft hier aber die Icomoon App. Dort können Icon Fonts importiert, die gewünschten Icons ausgewählt und anschließend ein neuer Icon Font generiert werden.

In der generierten .ZIP Datei für den eigenen Icon Font ist eine SVG Sprite Datei mit dem Namen symbol-defs.svg enthalten.

SVG Datei einbinden

Die SVG Datei sieht in etwa so aus:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <symbol id="twitter" viewBox="0 0 30 32">
        <path class="path1" d="M28.929 7.286q-1.196 1.75-2.893 2.982 0.018 0.25 0.018 0.75 0 2.321-0.679 4.634t-2.063 4.437-3.295 3.759-4.607 2.607-5.768 0.973q-4.839 0-8.857-2.589 0.625 0.071 1.393 0.071 4.018 0 7.161-2.464-1.875-0.036-3.357-1.152t-2.036-2.848q0.589 0.089 1.089 0.089 0.768 0 1.518-0.196-2-0.411-3.313-1.991t-1.313-3.67v-0.071q1.214 0.679 2.607 0.732-1.179-0.786-1.875-2.054t-0.696-2.75q0-1.571 0.786-2.911 2.161 2.661 5.259 4.259t6.634 1.777q-0.143-0.679-0.143-1.321 0-2.393 1.688-4.080t4.080-1.688q2.5 0 4.214 1.821 1.946-0.375 3.661-1.393-0.661 2.054-2.536 3.179 1.661-0.179 3.321-0.893z"></path>
    </symbol>
    <symbol id="facebook" viewBox="0 0 19 32">
        <path class="path1" d="M17.125 0.214v4.714h-2.804q-1.536 0-2.071 0.643t-0.536 1.929v3.375h5.232l-0.696 5.286h-4.536v13.554h-5.464v-13.554h-4.554v-5.286h4.554v-3.893q0-3.321 1.857-5.152t4.946-1.83q2.625 0 4.071 0.214z"></path>
    </symbol>
</svg>

Dieses Beispiel enthält nur zwei Icons mit den IDs twitter und facebook. Im Normalfall wird eure SVG Datei natürlich wesentlich größer sein und eine Vielzahl an Icons enthalten.

In den nachfolgenden Beispielen verwende ich Genericons Neue. Im Genericons Ordner finden wir im Unterordner /svg-sprite die Datei genericons-neue.svg.

Die SVG Datei platzieren wir nun im Theme Ordner, bestenfalls in einen extra Unterordner:
/assets/icons/genericons-neue.svg

Weitere Dateien werden nicht benötigt.

SVG Icons im WordPress Theme anzeigen

Bei der Ausgabe der SVG Icons verdeutlicht sich der Unterschied zu Icon Fonts.

SVGs sind Vektorgrafiken und werden daher als eigenständiges Element im HTML Markup eingefügt. Es sind Bilder, nur mit <svg> statt <img> eingefügt. Die Icons haben eine feste Breite und Höhe, die wir im Stylesheet mit width und height festlegen können.

Icon Fonts hingegen sind Schriftarten, welche mit mit font-family und content im CSS Code definiert werden. Dies geschieht meistens für Hilfs-Elemente wie z.B. leere span Tags oder Pseudo-Elementen wie :before und :after. Anstatt von Breite und Höhe wird die Größe der Icons durch font-size bestimmt.

Zur Anzeige des SVG Icons im WordPress Theme genügt dabei dieser HTML Code:

<svg class="icon icon-search" aria-hidden="true" role="img">
    <use xlink:href="path/to/icons.svg#search"></use>
</svg>

Das Icon wird hier mit dem URL-Pfad zu einer externen SVG Datei eingebunden. Mit #search wählen wir das Icon mit <symbol id="search"> der SVG Datei aus.

Neben der Anzeige von SVG Icons mit einer externen Datei kann das SVG Sprite auch als Inline Markup im HTML eingebunden werden.

Ich werde die Implementierung beider Methoden nun genauer vorstellen.

1. SVG Sprite als externe Datei nutzen

Zum Anzeigen eines SVG Icons empfiehlt sich die Erstellung einer eigenen Hilfsfunktion. Diese kann dann an verschiedenen Stellen im Theme einfach aufgerufen werden.

Die folgende Funktion orientiert sich an der Umsetzung der SVG Icons in Twenty Seventeen, wurde von mir aber etwas vereinfacht. Wir nutzen darin die recht neue Funktion get_parent_theme_file_uri(), um die URL zur externen SVG Datei zu erhalten.

/**
 * Return SVG markup.
 *
 * @param string $icon SVG icon id.
 * @return string $svg SVG markup.
 */
function theme_slug_get_svg( $icon = null ) {
	// Return early if no icon was defined.
	if ( empty( $icon ) ) {
		return;
	}

	// Create SVG markup.
	$svg = '<svg class="icon icon-' . esc_attr( $icon ) . '" aria-hidden="true" role="img">';
	$svg .= ' <use xlink:href="' . get_parent_theme_file_uri( '/assets/icons/genericons-neue.svg#' ) . esc_html( $icon ) . '"></use> ';
	$svg .= '</svg>';

	return $svg;
}

Als Parameter kann die ID des Icons übergeben werden:

echo theme_slug_get_svg( 'menu' );

Als Ausgabe erfolgt:

<svg class="icon icon-menu" aria-hidden="true" role="img">
    <use xlink:href="domain.com/wp-content/themes/theme-slug/assets/icons/genericons-neue.svg#menu">
</svg>

Ein Problem mit externen SVG Dateien in <use> ist, dass der Internet Explorer damit nicht umgehen kann. Deshalb erscheinen dort keine Icons. Als Lösung muss ein zusätzliches Polyfill Script eingebunden werden, wie zum Beispiel svgxuse.

function theme_slug_scripts() {

    // Enqueue svgxuse to support external SVG Sprites in Internet Explorer.
    wp_enqueue_script( 'svgxuse', get_theme_file_uri( '/assets/js/svgxuse.min.js' ), array(), '1.2.4' );

}
add_action( 'wp_enqueue_scripts', 'theme_slug_scripts' );

Eine weitere Alternative ist svg4everybody.

2. SVG Sprite inline im HTML Markup einbinden

Für den Einsatz des SVG Sprites als Inline Markup können wir die nahezu gleiche Hilfsfunktion zur Anzeige von Icons verwenden:

/**
 * Return SVG markup.
 *
 * @param string $icon SVG icon id.
 * @return string $svg SVG markup.
 */
function theme_slug_get_svg( $icon = null ) {
	// Return early if no icon was defined.
	if ( empty( $icon ) ) {
		return;
	}

	// Create SVG markup.
    $svg = '<svg class="icon icon-' . esc_attr( $icon ) . '" aria-hidden="true" role="img">';
	$svg .= ' <use xlink:href="#' . esc_html( $icon ) . '"></use> ';
	$svg .= '</svg>';

	return $svg;
}

Einziger Unterschied: Statt dem ganzen Pfad zur SVG Datei wird jetzt nur die Icon ID in <use> verwendet.

Als Ausgabe erfolgt:

<svg class="icon icon-menu" aria-hidden="true" role="img">
    <use xlink:href="#menu">
</svg>

Damit die Icons nun auch dargestellt werden können, muss das SVG Markup inline im HTML geladen werden. Das ist möglich, weil die SVG Datei grundsätzlich aus browserkonformen XML-Code besteht und deshalb ganz normal im Quellcode ausgegeben werden kann.

Die passende Funktion dafür finden wir in Twenty Seventeen, welche die SVG Icons inline einbindet:

/**
 * Add SVG definitions to the footer.
 */
function theme_slug_include_svg_icons() {
	// Define SVG sprite file.
	$svg_icons = get_parent_theme_file_path( '/assets/icons/genericons-neue.svg' );

	// If it exists, include it.
	if ( file_exists( $svg_icons ) ) {
		require_once( $svg_icons );
	}
}
add_action( 'wp_footer', 'theme_slug_include_svg_icons', 9999 );

Nun wird auf jeder Seite der WordPress Installation im Footer die komplette SVG Datei ausgegeben.

Aus diesem Grund sollte die SVG Datei auch noch bearbeitet werden, um mit extra Style Angaben zu sorgen, dass diese nicht im Frontend dargestellt wird.

<svg style="display: none; position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <!-- Icons -->
</svg>

Das Einbinden einer zusätzlichen JavaScript Datei wie svgxuse ist hier nicht notwendig, weil alle Browser mit Inline SVGs umgehen können.

Welche Methode ist besser?

Beide Methoden haben Vor- und Nachteile.

Eine externe SVG Datei wird vom Browser gecached und ist daher aus Performance-Sicht schneller. Ein Nachteil ist die extra benötigte JavaScript Datei, um SVG Icons auch im Internet Explorer darzustellen.

Mit den SVG Icons als Inline Markup spart man sich das JavaScript. Trotzdem ist die Inline-Methode wohl nur bei sehr kleinen Icon Sets wie in Twenty Seventeen sinnvoll, weil sonst der Quellcode unnötig aufgebläht wird. Ich rate dringend davon ab, ein großes Icon Set wie Font Awesome mit 470+ Icons auf jeder Seite im Quelltext zu laden.

Ich persönlich bevorzuge eine externe SVG Datei. Es ist wohl etwas Geschmackssache, aber die Ausgabe eines großen Blocks SVG Markup am Ende des Quelltexts auf jeder Seite fühlt sich für mich nicht richtig an.

Anwendungsbeispiele im Theme

Unsere neue Funktion theme_slug_get_svg() lässt sich nun an verschiedenen Stellen im Theme einsetzen.

Hier sind ein paar Beispiele:

Menü Button für mobile Navigation

Für ein mobiles Menü kann ein Menü Icon ausgegeben werden, welches mit CSS und Media Queries nur auf kleineren Geräten eingeblendet wird:

<button class="menu-toggle">
    <?php echo theme_slug_get_svg( 'menu' ); ?>
    <span class="screen-reader-text"><?php esc_html_e( 'Menu', 'theme-slug' ); ?></span>
</button>

Menüs mit Dropdown-Icons

Mit dieser Funktion lassen sich für die Theme Navigation zusätzliche SVG Icons für Dropdown-Menüs einfügen:

/**
 * Add dropdown icon if menu item has children.
 *
 * @param  string $title The menu item's title.
 * @param  object $item  The current menu item.
 * @param  array  $args  An array of wp_nav_menu() arguments.
 * @param  int    $depth Depth of menu item. Used for padding.
 * @return string $title The menu item's title with dropdown icon.
 */
function theme_slug_dropdown_icon_to_menu_link( $title, $item, $args, $depth ) {
	if ( 'primary' === $args->theme_location || 'secondary' === $args->theme_location ) {
		foreach ( $item->classes as $value ) {
			if ( 'menu-item-has-children' === $value || 'page_item_has_children' === $value ) {
				$title = $title . '<span class="sub-menu-icon">' . theme_slug_get_svg( 'expand' ) . '</span>';
			}
		}
	}

	return $title;
}
add_filter( 'nav_menu_item_title', 'theme_slug_dropdown_icon_to_menu_link', 10, 4 );

Pagination mit Pfeil-Icons

Um die Pagination bzw. Seitennummerierung im WordPress Theme mit Pfeilen für die Links zur vorherigen und nächsten Seite auszugeben, genügt folgender Code Schnipsel:

the_posts_pagination( array(
	'mid_size'  => 2,
	'prev_text' => theme_slug_get_svg( 'previous' ) . '<span class="screen-reader-text">' . esc_html__( 'Previous Posts', 'theme-slug' ) . '</span>',
	'next_text' => theme_slug_get_svg( 'next' ) . '<span class="screen-reader-text">' . esc_html__( 'Next Posts', 'theme-slug' ) . '</span>',
) );

Suchfeld mit Search-Icon

Die searchform.php im Theme könnte wie folgt aussehen:

<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
	<label>
		<span class="screen-reader-text"><?php echo esc_html_x( 'Search for:', 'label', 'theme-slug' ); ?></span>
		<input type="search" class="search-field"
			placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder', 'theme-slug' ); ?>"
			value="<?php echo get_search_query(); ?>" name="s"
			title="<?php echo esc_attr_x( 'Search for:', 'label', 'theme-slug' ); ?>" />
	</label>
	<button type="submit" class="search-submit">
		<?php echo theme_slug_get_svg( 'search' ); ?>
		<span class="screen-reader-text"><?php echo esc_html_x( 'Search', 'submit button', 'theme-slug' ); ?></span>
	</button>
</form>

Styling der SVG Icons mit CSS

Die Darstellung der SVG Icons kann mit etwas CSS angepasst werden. Wichtig ist vor allem das Festlegen einer Breite und Höhe für die Größe des Icons.

.icon-menu {
    width: 14px;
    height: 14px;
    vertical-align: top;
    fill: #303030;
}

Mit dem CSS Befehl fill kann die Farbe des Icons bestimmt werden.