For the past year, I’ve been experimenting with using SVG icons in my Genesis child themes.
Using a Plugin
When version 2.0 of the Genesis Simple Social Icons plugin came out and switched to SVG icons, it put that plugin back on my radar. Unfortunately, it is not easy for clients to reorder the icons without having to add a filter to change the sorting order of the SVG icons. So while I was happy about the SVG addition, it still was not an ideal solution for my clients.
SVG Icon support built into TwentySeventeen
When the WordPress Twentyseventeen theme was released, their solution was updated from the TwentyFifteen theme to use SVG icons for the social menu. Very slick.
Using a menu for social icons makes sense.
This is a very easy solution for a client to implement. All you need to do is create a menu, add your social media links with the menu text and voila – it magically displays the corresponding SVG icons instead.
Are these Magical SVG Icons?
You might be asking yourself just that. How does the menu know which icon to use?
Well, there is an SVG sprite (fancy way to say one big SVG file that contains lots of individual SVG graphics) – one element for each social media icon it supports. There are also some other SVG icons in there for the theme, unrelated to social icons. Nice. All of your SVG icons are in one place.
<symbol id="icon-folder-open" viewBox="0 0 34 32"> | |
<path class="path1" d="M33.554 17q0 0.554-0.554 1.179l-6 7.071q-0.768 0.911-2.152 1.545t-2.563 0.634h-19.429q-0.607 0-1.080-0.232t-0.473-0.768q0-0.554 0.554-1.179l6-7.071q0.768-0.911 2.152-1.545t2.563-0.634h19.429q0.607 0 1.080 0.232t0.473 0.768zM27.429 10.857v2.857h-14.857q-1.679 0-3.518 0.848t-2.929 2.134l-6.107 7.179q0-0.071-0.009-0.223t-0.009-0.223v-17.143q0-1.643 1.179-2.821t2.821-1.179h5.714q1.643 0 2.821 1.179t1.179 2.821v0.571h9.714q1.643 0 2.821 1.179t1.179 2.821z"></path> | |
</symbol> | |
<symbol id="icon-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="icon-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> | |
<symbol id="icon-github" viewBox="0 0 27 32"> | |
<path class="path1" d="M13.714 2.286q3.732 0 6.884 1.839t4.991 4.991 1.839 6.884q0 4.482-2.616 8.063t-6.759 4.955q-0.482 0.089-0.714-0.125t-0.232-0.536q0-0.054 0.009-1.366t0.009-2.402q0-1.732-0.929-2.536 1.018-0.107 1.83-0.321t1.679-0.696 1.446-1.188 0.946-1.875 0.366-2.688q0-2.125-1.411-3.679 0.661-1.625-0.143-3.643-0.5-0.161-1.446 0.196t-1.643 0.786l-0.679 0.429q-1.661-0.464-3.429-0.464t-3.429 0.464q-0.286-0.196-0.759-0.482t-1.491-0.688-1.518-0.241q-0.804 2.018-0.143 3.643-1.411 1.554-1.411 3.679 0 1.518 0.366 2.679t0.938 1.875 1.438 1.196 1.679 0.696 1.83 0.321q-0.696 0.643-0.875 1.839-0.375 0.179-0.804 0.268t-1.018 0.089-1.17-0.384-0.991-1.116q-0.339-0.571-0.866-0.929t-0.884-0.429l-0.357-0.054q-0.375 0-0.518 0.080t-0.089 0.205 0.161 0.25 0.232 0.214l0.125 0.089q0.393 0.179 0.777 0.679t0.563 0.911l0.179 0.411q0.232 0.679 0.786 1.098t1.196 0.536 1.241 0.125 0.991-0.063l0.411-0.071q0 0.679 0.009 1.58t0.009 0.973q0 0.321-0.232 0.536t-0.714 0.125q-4.143-1.375-6.759-4.955t-2.616-8.063q0-3.732 1.839-6.884t4.991-4.991 6.884-1.839zM5.196 21.982q0.054-0.125-0.125-0.214-0.179-0.054-0.232 0.036-0.054 0.125 0.125 0.214 0.161 0.107 0.232-0.036zM5.75 22.589q0.125-0.089-0.036-0.286-0.179-0.161-0.286-0.054-0.125 0.089 0.036 0.286 0.179 0.179 0.286 0.054zM6.286 23.393q0.161-0.125 0-0.339-0.143-0.232-0.304-0.107-0.161 0.089 0 0.321t0.304 0.125zM7.036 24.143q0.143-0.143-0.071-0.339-0.214-0.214-0.357-0.054-0.161 0.143 0.071 0.339 0.214 0.214 0.357 0.054zM8.054 24.589q0.054-0.196-0.232-0.286-0.268-0.071-0.339 0.125t0.232 0.268q0.268 0.107 0.339-0.107zM9.179 24.679q0-0.232-0.304-0.196-0.286 0-0.286 0.196 0 0.232 0.304 0.196 0.286 0 0.286-0.196zM10.214 24.5q-0.036-0.196-0.321-0.161-0.286 0.054-0.25 0.268t0.321 0.143 0.25-0.25z"></path> | |
</symbol> |
Okay, so how does it work?
It parses the URL of each menu item and compares it to an associative array of URLs it supports with corresponding symbol IDs. If it finds a match it dynamically swaps out the menu text for the matching SVG icon. For accessibility, it wraps that menu text in a <span>
with a screen reader class. Screen readers will then read out the menu text. Brilliant!
The code below is from the Twentyseventeen theme inc/icon-functions.php
. I’ve highlighted a few lines to note. First, it checks if we are on the social menu. Then if it finds a match for the URL, it swaps out the text for the SVG. Finally, this is all done by hooking into the filter walker_nav_menu_start_el
.
/** | |
* Display SVG icons in social links menu. | |
* | |
* @param string $item_output The menu item output. | |
* @param WP_Post $item Menu item object. | |
* @param int $depth Depth of the menu. | |
* @param array $args wp_nav_menu() arguments. | |
* @return string $item_output The menu item output with social icon. | |
*/ | |
function twentyseventeen_nav_menu_social_icons( $item_output, $item, $depth, $args ) { | |
// Get supported social icons. | |
$social_icons = twentyseventeen_social_links_icons(); | |
// Change SVG icon inside social links menu if there is supported URL. | |
if ( 'social' === $args->theme_location ) { | |
foreach ( $social_icons as $attr => $value ) { | |
if ( false !== strpos( $item_output, $attr ) ) { | |
$item_output = str_replace( $args->link_after, '</span>' . twentyseventeen_get_svg( array( 'icon' => esc_attr( $value ) ) ), $item_output ); | |
} | |
} | |
} | |
return $item_output; | |
} | |
add_filter( 'walker_nav_menu_start_el', 'twentyseventeen_nav_menu_social_icons', 10, 4 ); | |
There is one caveat though.
There is a limitation on where you can use this menu in the theme. It must be assigned to the Social Links Menu location to work.

Wouldn’t it be nice if you could use this menu in the Custom Menu widget? Then it could be displayed in a sidebar, footer widget or even in a page builder widget?
First Challenge: Make it work in Twentyseventeen.
That was my first challenge – to adapt the code to work on a child theme of Twentyseventeen. Here is how I did it. I’ll walk you through step by step.
1. Created a child theme of Twentyseventeen. Not sure how to do that? Here is the information found in WordPress Codex. I’ve included the child theme I created in this tutorial. You can download it here from Github. Click on Clone or Download and then Download Zip.

2. I added the following code to the functions.php file:
<?php | |
/** | |
* The functions file for Child of Twentyseventeen theme. | |
* | |
* @package WordPress | |
* @subpackage child_of_twentyseventeen | |
* @since 1.0 | |
* @version 1.0 | |
*/ | |
/** | |
* Since 1.0. | |
*/ | |
function my_theme_enqueue_styles() { | |
$parent_style = 'parent-twentyseventeen-style'; // This is 'twentyseventeen-style' for the Twenty Seventeen theme. | |
wp_enqueue_style( $parent_style, get_template_directory_uri() . '/style.css' ); | |
wp_enqueue_style( 'child-twentyseventeen-style', | |
get_stylesheet_directory_uri() . '/style.css', | |
array( $parent_style ), | |
wp_get_theme()->get( 'Version' ) | |
); | |
} | |
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' ); | |
/** | |
* SVG icons functions and filters. | |
*/ | |
include_once( get_stylesheet_directory() . '/inc/social-menu-links.php' ); |
3. I created a folder in the child theme named inc
. Added the file namedsocial-menu-functions.php
in that folder with the following code:
First thing is to remove the filter from the parent theme.
Then, add the replacement code to run.
How to check if the Social Links Menu is being used in a widget?
My solution was to assign the menu a specific name, so I could then target the menu-slug
in my code. The slug is generated automatically based on the menu name and each menu must have a unique name. I assigned the menu Social Links Menu, so the slug that is automatically generated is social-media-menu
.
So the logic goes like this. If we are displaying the social links in the default location, run the default code, else test to see if my menu slug social-media-menu
matches. If it does, swap out the icons as we did for the default menu location.
But something was not working correctly in the Customizer.
The icons in the Custom Menu section do not refresh properly when you edit the menu in the Customizer.

Identifying the source of problem
This happens because when you edit a Custom Menu in the Customizer, the filter for 'walker_nav_menu_start_el'
no longer returns the WP_Term object for $args->menu
and instead returns the integer of the menu ID.
Using the very handy Kint PHP Debugger, I can easily output values on the front end to see when and how values change.

$args->menu
was an object before editing, but after reordering the icons, it returns an integer.So by adding this extra code shown from line 39-44, I need to test if $args->menu
is an object. If it is, we get the term_id (id of the menu). If not, then $args->menu
just returns the id of the menu as an integer.
This solved the issue with the Customizer and refreshing the icons.
The remaining code wraps the menu text in a screen reader class. The Social Footer Menu does that in footer.php of the parent theme. I just needed to add similar code to do the same if a Custom Menu was using the Social Links Menu.

4. I added the following to the child theme style.css and activated the child theme.
/* | |
Theme Name: Child of Twenty Seventeen | |
Theme URI: https://wordpress.org/themes/twentyseventeen/ | |
Author: the WordPress team | |
Author URI: https://wordpress.org/ | |
Description: Twenty Seventeen brings your site to life with header video and immersive featured images. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device. | |
Version: 1.2.1 | |
License: GNU General Public License v2 or later | |
License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
Text Domain: child-twentyseventeen | |
Template: twentyseventeen | |
Tags: one-column, two-columns, right-sidebar, flexible-header, accessibility-ready, custom-colors, custom-header, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready | |
This theme, like WordPress, is licensed under the GPL. | |
Use it to make something cool, have fun, and share what you've learned with others. | |
*/ | |
.main-navigation .menu-social-links-menu-container .icon { | |
display: inline-block; | |
font-size: 36px; | |
} | |
.widget-area .menu-social-links-menu-container ul li { | |
display: inline-block; | |
font-size: 1rem; | |
border: none; | |
padding: 0; | |
} | |
.widget-area .menu-social-links-menu-container ul li a { | |
background-color: #767676; | |
border-radius: 40px; | |
color: #fff; | |
display: inline-block; | |
height: 40px; | |
margin: 0 1em 0.5em 0; | |
text-align: center; | |
width: 40px; | |
} | |
.widget-area .menu-social-links-menu-container ul li a:focus, | |
.widget-area .menu-social-links-menu-container ul li a:hover { | |
background-color: #333; | |
color: #fff; | |
border: none; | |
box-shadow: none; | |
} | |
.widget_search { | |
clear: both; | |
} | |
.widget-area .social-navigation { | |
width: 100%; | |
} |
Now I can use my social icon menu anywhere on the site.
That’s a wrap.

Second Challenage
Now with that working, my next challenge is to adapt this entire SVG icon system into my Genesis child themes.
[shared_counts location="shared-count-icons" style="fancy"]