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.
Hi! Schöner ausführlicher Artikel!
Fallen eigentlich bei HTTP2 viele kleine (SVG-)Dateien immer noch sehr ins Gewicht?
Danke!
Soweit ich weiß sind mit HTTP2 viele kleine Dateien gleich gut oder sogar besser als Image Sprites, aber ich habe keine Zahlen wie groß der Performance Unterschiede wirklich ist.
LG,
Thomas
Hallo Thomas,
leide komme ich nicht wirklich mit Deiner Erklärung klar 🙁
Ich habe mir die Icons über die ICON-Moon-App generiert und als ZIP Datei runtergeladen. Brauch ich dann weiterhin noch die von Dir genante genericons-neue.svg? Wenn ich diese einbinde wird gar nix als SVG im Browser angezeigt.
Kannst Du bitte nochmal ne Erläuterung geben? Vielen Dank
Hallo Steven,
In dem Tutorial verwende ich Genericons Neue und deshalb die genericons-neue.svg.
Es funktioniert aber auch mit SVG Sprites von ICO Moon. Siehe zweiter Abschnitt:
Der SVG Sprite sollte als symbol-defs.svg in der .ZIP enthalten sein. Diese Datei kann dann anstatt der genericons-neue.svg verwendet werden.
LG,
Thomas
Die Datei liegt mir vor. Wenn ich es so mache wie beschrieben funktioniert es dennoch nicht. Daher habe ich mich entschlossen von ICO Moon die png Dateien einzubinden
Alle Referenzen zur genericons-neue.svg müssen entsprechend angepasst werden, z.B. auch in der theme_slug_get_svg() Funktion.
get_parent_theme_file_uri( '/assets/icons/symbol-defs.svg#icon-' ) . esc_html( $icon )
Neben dem korrekten Pfad zur Datei ( /assets/icons/ ) ist auch die ID nach der Raute entscheidend. Dazu kann einfach die SVG Datei mit einem Editor geöffnet werden und die IDs der Icons beachtet werden. Genericons Neue verwendet einfach #menu, #expand usw, andere Icons Fonts unter Umständen aber #icon-menu, #icon-expand oder ähnliches.
LG,
Thomas
Kannst Du bitte nochmal kurz ne Erläuterung geben welcher PHP Schnipsel wo eingegeben werden muss? Irgendwie steh ich echt auf der Leitung. Danke 🙂
Wie immer bei WordPress Themes gehören alle Funktionen in die functions.php
Aus Gründen der Übersichtlichkeit können diese auch in mehrere Dateien ausgelagert werden. Ich packe die Funktionen für Icons alle in die Datei /inc/icons.php, nach dem Vorbild von TwentySeventeen.
Frage: Du schreibst einen Artikel über Icons, verwendest aber selber KEINE im Beitrag? Wäre doch spannend zu sehen, wie ein Text mit Icons aussieht?! Das hätte mich jetzt interessiert.
Das ist richtig, noch keine SVGs hier 😉 ThemeCoder verwendet mein Napoli Theme, welches noch auf herkömmliche Icon Fonts setzt.
Der Artikel ist parallel zur Entwicklung meines neuesten Themes Chronus enstanden, indem ich für alle Icons nun SVGs verwende. Im Einsatz zu sehen sind die SVG Icons in der Demo unter https://preview.themezee.com/?demo=chronus-pro
LG,
Thomas
Sehr informativ und nützlich für unser aktuelles Projekt, vielen Dank 🙂