Ein Social-Icons-Menü mit SVGs in WordPress umsetzen

Social-Icon-Menüs selbst gemacht mit WordPress
Keine Kommentare

Viele Websites zeigen – mal mehr und mal weniger prominent – ein Menü mit Icons zu verschiedenen Social-Media-Kanälen. Wenn Sie eine Website haben, gehören Sie vielleicht dazu. Häufig wird zur technischen Umsetzung für eine solche Liste noch zu einem Iconfont gegriffen, obwohl es mit SVGs eine bessere Lösung gibt. Wie Sie die in Ihre WordPress-Website implementieren können, zeige ich in diesem Artikel.

Zunächst beschäftigen wir uns kurz mit den Vor- und Nachteilen der jeweiligen Technik (Kasten: „Iconfonts“ und „SVGs“). Die Punkte sind aus dem Artikel „Inline SVG vs Icon Fonts [CAGEMATCH]“ von Chris Coyier. Mit dem Update auf iOS 9.1 scheinen UnicodeÄnderungen vorgenommen worden zu sein, mit denen der Iconfont auf www.espn.go.com nicht zurechtgekommen ist (Abb. 1). Sie sehen also: SVGs sollten die erste Wahl sein, wenn es darum geht, Icons anzuzeigen.

Unicode-Änderungen führen schnell zu Problemen (Screenshot: Jason Grigsby)

Unicode-Änderungen führen schnell zu Problemen (Screenshot: Jason Grigsby)

 Iconfonts

Vorteile

Guter Browsersupport (ab IE6)

Nachteile

  • Browser behandeln sie als Text. Das kann dazu führen, dass sie nicht ganz scharf dargestellt werden.
  • Eingeschränkte Stylingmöglichkeiten.
  • Viele Faktoren, die auf Positionierung einwirken (line-height, letter-spacing, et cetera), was die Positionierung nicht ganz einfach macht.
  • Semantisch fragwürdig, eine Schrift zur Darstellung von Bildern zu verwenden.
  • Anzeige kann aus verschiedenen Gründen fehlschlagen (beispielsweise, wenn der Nutzer einen eigenen Font eingestellt hat, der den Iconfont überschreibt). Ein paar Beispiele aus der Praxis gibt es im Artikel „Seriously, Don’t Use Icon Fonts“ von Tyler Sticka, in dem ich auch den unten gezeigten Fall gefunden habe.

SVGs

Vorteile

  • Immer scharf.
  • Viele Stylingmöglichkeiten, wenn als Inline SVG eingebunden (mehrfarbige Icons …).
  • Weniger Probleme bei der Positionierung.
  • Semantisch als Bild ausgezeichnet.
  • Bringt theoretisch gleich Funktionen für Barrierefreiheit mit. Hier ist die Unterstützung durch Screenreader aber noch nicht sehr gut.

Nachteile

  • Browsersupport: Ab IE9 Inline SVGs; externe Referenzierung einer SVG mit dem use-Element im IE nur mit Polyfill.

Vorbereitung der Icons

Bevor wir uns ansehen, wie das Ganze in WordPress eingebunden wird, müssen wir uns zunächst überlegen, wie wir die SVGs einsetzen möchten. Da wir nicht auf das Caching verzichten wollen, bietet es sich an, eine externe SVG-Datei einzubinden, die alle Icons enthält – ein SVG Sprite. Dafür muss eine SVG-Datei nach dem in Listing 1 gezeigten Schema angelegt werden.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="icon-twitter" viewBox="0 0 16 16">
    <path d="M15,[…]"/>
  </symbol>

  <symbol id="icon-feed" viewBox="0 0 16 16">
    <path d="M2,[…]"/>
  </symbol>
</svg>

Innerhalb des svg-Elements stehen symbol-Elemente, wobei jedes davon ein Icon repräsentiert. Über die ID kann ein Icon später einfach eingebunden werden. Die Icons können Sie beispielsweise von Fontastic bekommen. Dort können Sie aus einer großen Auswahl Icons auswählen, die Sie auch gleich als SVG Sprite herunterladen können. Wie ein bereits vorhandener Iconfont in SVGs umgewandelt werden kann, beschreibt Sara Soueidan in ihrem Blog.

Integration in WordPress

Um nun ein Icon anzeigen zu können, wird folgender Code benötigt, wobei der String nach dem # die ID des Icons darstellt:

<svg class="icon-twitter">
<use xlink:href="/pfad-zum-theme/svg/social-media-icons.svg#icon-twitter"/>
</svg>
<span class="screen-reader-text">Twitter</span>

In dem svg-Element wird mit dem use-Tag das SVG-Icon mit der ID icon-twitter aus der Datei /pfad-zum-theme/svg/social-media-icons.svg angezeigt. Das folgende span wird für Screenreader-Nutzer eingebunden und über das Theme vor allen anderen versteckt.

Das ist also der Code, der von WordPress innerhalb eines Links auf den jeweiligen Social-Media-Kanal ausgegeben werden muss. Für die Verwaltung durch den Nutzer bietet sich an, die WordPress-eigene Menüfunktion zu nutzen, deren Ausgabe durch eine angepasste Walker-Klasse verändert werden kann.

Um diesen Walker aufzurufen, muss er bei der Ausführung der wp_nav_menu()-Funktion angegeben werden. Davor müssen wir allerdings noch eine Theme-Position für das Menü registrieren, worauf wp_nav_menu() dann zugreifen kann (Listing 2). Unser Aufruf des Menüs von der Theme-Position social-media-menu sieht beispielsweise so aus wie in Listing 3 gezeigt.

/**
 * Register Theme Location
 */
function svg_social_menu_register_theme_location() {
  register_nav_menu( 'svg-social-menu', __( 'SVG Social Menu', 'svg-social-menu' ) );
}

add_action( 'after_setup_theme', 'svg_social_menu_register_theme_location' );
if ( has_nav_menu( 'social-media-menu' ) ) {
  wp_nav_menu(
    array(
      'theme_location' => 'social-media-menu',
      'menu_class'     => 'social-media-menu',
      'container'      => '',
      'walker'         => new Svg_Social_Menu_Walker(),
      'depth'          => 1
    )
  );
}

Zunächst prüfen wir mit has_nav_menu(), ob der gerade registrierten Theme-Position ein Menü zugewiesen ist. Wenn dem so ist, wird das Menü über wp_nav_menu() ausgegeben. Wichtig ist hier die Angabe der Theme-Position für den Arrayschlüssel theme_location, sowie der Wert für walker – diese Klasse verändert die Ausgabe des Menüs.

Um bei der Programmierung von Svg_Social_Menu_Walker() nicht bei null anfangen zu müssen, kann eine Kindklasse zu Walker_Nav_Menu() erstellt werden – diese Klasse steuert die Ausgabe von Menüs, wenn kein walker angegeben wird (Listing 4). In dieser Klasse muss lediglich die Methode start_el() überschrieben werden, die sich um die Ausgabe eines Menüelements kümmert. Dabei können auch in dieser Methode große Teile übernommen werden, weshalb hier nicht der komplette Code dargestellt ist, sondern nur die veränderten Teile mit einigen übernommenen Codestücken als Referenz, wo wir uns in der Klasse befinden.

class Svg_Social_Menu_Walker extends Walker_Nav_Menu {
  // […]
  public function start_el( &$output, $item, $depth = 0,
    $args = array(), $id = 0 ) {
    // […]
    $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );

    $social_media_channels = array(
      'plus.google.com' => array(
        'id'                 => 'icon-google-plus',
        'screen-reader-text' => __( 'Google Plus', 'text-domain' )
      ),
      'wordpress.org'   => array(
        'id'                 => 'icon-wordpress',
        'screen-reader-text' => __( 'WordPress.org', 'text-domain' )
       ),
       'twitter.com'        => array(
         'id'                 => 'icon-twitter',
         'screen-reader-text' => __( 'Twitter', 'text-domain' )
       ),
       '/feed'           => array(
         'id'                 => 'icon-feed',
         'screen-reader-text' => __( 'Feed', 'text-domain' )
       ),
    );

Selbst geschrieben ist in diesem Codeblock der Teil ab $social_media_channels = array(. Hier müssen die URLs zu den Kanälen mit den IDs in Verbindung gebracht werden, die in der SVG-Datei für die symbol-Elemente verwendet wurden. Darüber hinaus wird ein übersetzbarer Screenreader-Text angegeben. Wir erstellen also ein Array mit URLs als Schlüssel und einem weiteren Array mit der zur URL passenden ID und dem Screenreader-Text als Wert (Listing 5).

$svg_id = "";
foreach ( $social_media_channels as $key => $value ) {
  $pattern = "|$key|";
  preg_match( $pattern, $atts['href'], $matches );
  if ( ! empty( $matches[0] ) ) {
    $match                  = $matches[0];
    $svg_id                 = $social_media_channels[ $match ]['id'];
    $svg_screen_reader_text = $social_media_channels[ $match ]['screen-reader-text'];
    break;
  }
}

Im nächsten Schritt speichern wir einen leeren String in der Variable $svg_id und durchlaufen anschließend das $social_media_channels-Array mit einer foreach-Schleife, in der wir mit $key auf den aktuellen Arrayschlüssel und mit $value auf den zugehörigen Wert, also das Array mit ID und Screenreader-Text, zugreifen können. In $atts[‚href‘] ist der URL des aktuellen Menüelements gespeichert. Diesen Wert müssen wir auf Vorkommen des Array-Keys durchsuchen und legen als Pattern deshalb |$key| fest.

Anschließend übergeben wir das Pattern, den URL des Menüelements und eine Variable, in der der Treffer gespeichert wird, an preg_match(). Wenn $matches[0] nicht leer ist, wurde eine Übereinstimmung aus dem aktuellen Arrayschlüssel in dem URL des Menüelements gefunden. $matches[0] stimmt in diesem Fall dann mit $key überein – bei einem Link zu einem Twitterprofil wäre das beispielsweise twitter.com. Ist eine Übereinstimmung gefunden, wird der Wert in $match gespeichert und danach über $social_media_channels[ $match ][‚id‘]; auf den Wert zum URL zugegriffen, der der SVG-ID entspricht, und über $social_media_channels[ $match ][’screen-reader-text‘]; auf die Beschriftung. Danach wird die Schleife abgebrochen.

Abschließend muss das Markup zusammengesetzt werden (Listing 6). Wenn $svg_id nicht leer ist, kann eine SVG angezeigt werden. In der Variable $icon_url wird in dem Fall der URL zur SVG-Datei gespeichert – hinter # wird mit $svg_id die ID des SVG-Symbols eingesetzt.

if ( $svg_id != "" ) {
  $icon_url    = plugins_url( "svg/social-media-icons.svg#$svg_id", __DIR__ );
  $item_output = $args->before;
  $item_output .= '<a' . $attributes . '>';
  $item_output .= '<svg class="' . $svg_id . '"><use xlink:href="' . $icon_url . '"></use></svg><span class="screen-reader-text">' . $svg_screen_reader_text . '</span>';
  $item_output .= '</a>';
  $item_output .= $args->after;
} else {
  $item_output = $args->before;
  $item_output .= '<a' . $attributes . '>';
  $item_output .= $args->link_before . $title . $args->link_after;
  $item_output .= '</a>';
  $item_output .= $args->after;

Die folgenden zwei Zeilen sind aus der Oberklasse übernommen, interessant wird es in der Zeile mit <svg …. Hier wird als Klasse für das svgElement die ID eingefügt, damit das Icon via CSS angesprochen werden kann. Für das href-Attribut des use-Elements wird der URL eingefügt und danach alle Tags wieder geschlossen. Anschließend wird ein span mit der Klasse screen-reader-text eingefügt, in dem der Titel ausgegeben wird. Der Code aus dem else-Zweig entspricht der Standardausgabe aus der Walker_Nav_Menu()-Klasse.

Polyfill für ältere Browser

Wie anfangs angesprochen, ist der Browsersupport im Internet Explorer für den Einsatz des use-Elements nicht gerade herausragend. Da Sie vermutlich zumindest die neuen Versionen des IE unterstützen möchten, bietet sich die Verwendung des Polyfills SVG for Everybody [6] an. Damit wird die oben gezeigte Lösung bis zurück zum IE9 funktionieren. Falls noch bis zum IE6 unterstützt werden soll oder muss, müssen Sie zusätzlich zu der SVG-Version noch eine PNG-Version einbinden – wo und wie genau, wird im GitHub Repository des Polyfills erläutert.

WordPress-Plug-in

Für die einfache Anwendung habe ich ein WordPress-Plug-in geschrieben. Neben dem besprochenen Code und dem Polyfill wird ein Widget bereitgestellt, über das das Menü eingebunden werden kann. Um es zu nutzen, muss nach der Aktivierung des Plug-ins Folgendes gemacht werden:

  • Ein Menü mit Links zu sozialen Netzwerken erstellen.
  • Als Menü-Position SVG Social Menu auswählen.
  • Das Widget SVG Social Menu in einen der Widget-Bereiche ziehen.

Entwickler Magazin

Entwickler Magazin abonnierenDieser Artikel ist im Entwickler Magazin erschienen.

Natürlich können Sie das Entwickler Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

X
- Gib Deinen Standort ein -
- or -