In the previous post, I shared how I modified the SVG Social Icons functionality in the Twentyseventeen theme to display the social menu using the Custom menu widget.
Since that time, I’ve come across a plugin in the WordPress repository called SVG Social Menu that adds that functionality to any WordPress theme, including Genesis.
So if you are looking just to add SVG icons for social media and prefer to use a menu this would be a great place to start. Another option is the Simple Social Icons plugin which does use SVG icons through a widget — not a menu, but has some limitations as you can not easily reorder them. In my opinion, a menu makes better sense, semantically and programmatically.
Now if you are interested in creating an icon system to use SVG not only in your menu but throughout your theme for design elements, within content areas, and inline them programmatically — a custom solution is in order.
Adding SVG elements to your theme
While I am writing and testing this solution for the Genesis Sample child theme, this can easily be adapted to work with any WordPress theme.
Adding SVG icons and graphics to your Genesis child theme can be done by copying the code from the icon-functions.php and including the SVG sprite from the Twentyseventeen theme. I’ve made a few modifications to the code to tailor it for my theme.
Step 1. Add the SVG sprite.
First thing is to add an SVG sprite to the child theme. An SVG sprite is a file that contains a collection of individual graphical elements.
<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> |
The one I am using for this tutorial is the one included with the Twentyseventeen theme. I have the included the original and a minified version so you can download and add to your images folder.

I added both of these to my images
folder.
Step 2. Add icon-functions.php in your child theme /lib/
folder
<?php | |
/** | |
* Icon functions for Genesis Child theme. | |
* Adapted from the TwentySeventeen theme. | |
* | |
* @since 1.1.0 | |
* @package Genesis Sample | |
* @author WordPress | |
* @license GPL-2.0+ | |
*/ | |
/** | |
* Adds custom SVG icon sprite to theme footer. | |
* | |
* @author Jackie D'Elia | |
* @package Genesis Theme code | |
* @since 1.0.0 | |
* @license GPL-2.0+ | |
* @link https://jackiedelia.com/ | |
*/ | |
function jdd_include_svg_icons() { | |
// Define SVG sprite file. | |
$svg_icons = get_stylesheet_directory() . '/images/svg-icons.min.svg'; | |
// If it exists, include it. | |
if ( file_exists( $svg_icons ) ) { | |
require_once( $svg_icons ); | |
} | |
} | |
add_action( 'wp_footer', 'jdd_include_svg_icons', 9999 ); | |
/** | |
* Return SVG markup. | |
* | |
* @param array $args { | |
* Parameters needed to display an SVG. | |
* | |
* @type string $icon Required SVG icon filename. | |
* @type string $title Optional SVG title. | |
* @type string $desc Optional SVG description. | |
* } | |
* @return string SVG markup. | |
*/ | |
function jdd_get_svg( $args = array() ) { | |
// Make sure $args are an array. | |
if ( empty( $args ) ) { | |
return __( 'Please define default parameters in the form of an array.', 'genesis-sample' ); | |
} | |
// Define an icon. | |
if ( false === array_key_exists( 'icon', $args ) ) { | |
return __( 'Please define an SVG icon filename.', 'genesis-sample' ); | |
} | |
// Set defaults. | |
$defaults = array( | |
'icon' => '', | |
'title' => '', | |
'desc' => '', | |
'fallback' => false, | |
'class' => '', | |
); | |
// Parse args. | |
$args = wp_parse_args( $args, $defaults ); | |
// Set aria hidden. | |
$aria_hidden = ' aria-hidden="true"'; | |
// Set ARIA. | |
$aria_labelledby = ''; | |
/* | |
* Theme doesn't use the SVG title or description attributes; non-decorative icons are described with .screen-reader-text. | |
* | |
* However, child themes can use the title and description to add information to non-decorative SVG icons to improve accessibility. | |
* | |
* Example 1 with title: <?php echo jdd_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ) ) ); ?> | |
* | |
* Example 2 with title and description: <?php echo jdd_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ), 'desc' => __( 'This is the description', 'textdomain' ) ) ); ?> | |
* | |
* See https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/. | |
*/ | |
if ( $args['title'] ) { | |
$aria_hidden = ''; | |
$unique_id = uniqid(); | |
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . '"'; | |
if ( $args['desc'] ) { | |
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . ' desc-' . $unique_id . '"'; | |
} | |
} | |
// Begin SVG markup. | |
$svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . ' ' . esc_attr( $args['class'] ) .'"' . $aria_hidden . $aria_labelledby . ' role="img">'; | |
// Display the title. | |
if ( $args['title'] ) { | |
$svg .= '<title id="title-' . $unique_id . '">' . esc_html( $args['title'] ) . '</title>'; | |
// Display the desc only if the title is already set. | |
if ( $args['desc'] ) { | |
$svg .= '<desc id="desc-' . $unique_id . '">' . esc_html( $args['desc'] ) . '</desc>'; | |
} | |
} | |
/* | |
* Display the icon. | |
* | |
* The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10. | |
* | |
* See https://core.trac.wordpress.org/ticket/38387. | |
*/ | |
$svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> '; | |
// Add some markup to use as a fallback for browsers that do not support SVGs. | |
if ( $args['fallback'] ) { | |
$svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>'; | |
} | |
$svg .= '</svg>'; | |
return $svg; | |
} | |
/** | |
* 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 jdd_nav_menu_social_icons( $item_output, $item, $depth, $args ) { | |
$menu_object = wp_get_nav_menu_object( 'social-links-menu' ); | |
$made_replacement = false; | |
if ( $menu_object ) { | |
$social_menu_id = $menu_object->term_id; | |
if ( is_object( $args->menu ) ) { | |
$cur_obj = $args->menu; | |
$cur_menu = $cur_obj->term_id; | |
} else { | |
$cur_menu = $args->menu; | |
} | |
// Change SVG icon inside social links menu if there is supported URL. | |
if ( $social_menu_id === $cur_menu ) { | |
// Load the social icons. | |
$social_icons = jdd_social_links_icons(); | |
$is_menu_assigned = $args->theme_location; | |
$item_output = str_replace( 'itemprop="url">', 'itemprop="url"><span class="screen-reader-text">' , $item_output ); | |
$item_output = str_replace( '</a>', '</span></a>' , $item_output ); | |
foreach ( $social_icons as $attr => $value ) { | |
if ( false !== strpos( $item_output, $attr ) ) { | |
$made_replacement = true; | |
if ( $is_menu_assigned ) { | |
$item_output = str_replace( '</span></span>', '</span></span>' . jdd_get_svg( array( 'icon' => esc_attr( $value ) ) ), $item_output ); | |
} else { | |
$item_output = str_replace( '</span>', '</span>' . jdd_get_svg( array( 'icon' => esc_attr( $value ) ) ), $item_output ); | |
} | |
} | |
} | |
if ( ! $made_replacement ) { | |
if ( $is_menu_assigned ) { | |
$item_output = str_replace( '</span></span>', '</span></span>' . jdd_get_svg( array( 'icon' => esc_attr( 'chain' ) ) ), $item_output ); | |
} else { | |
$item_output = str_replace( '</span>', '</span>' . jdd_get_svg( array( 'icon' => esc_attr( 'chain' ) ) ), $item_output ); | |
} | |
} | |
} | |
} | |
return $item_output; | |
} | |
add_filter( 'walker_nav_menu_start_el', 'jdd_nav_menu_social_icons', 10, 4 ); | |
/** | |
* Returns an array of supported social links (URL and icon name). | |
* | |
* @return array $social_links_icons | |
*/ | |
function jdd_social_links_icons() { | |
// Supported social links icons. | |
$social_links_icons = array( | |
'behance.net' => 'behance', | |
'codepen.io' => 'codepen', | |
'deviantart.com' => 'deviantart', | |
'digg.com' => 'digg', | |
'dribbble.com' => 'dribbble', | |
'dropbox.com' => 'dropbox', | |
'facebook.com' => 'facebook', | |
'flickr.com' => 'flickr', | |
'foursquare.com' => 'foursquare', | |
'plus.google.com' => 'google-plus', | |
'github.com' => 'github', | |
'instagram.com' => 'instagram', | |
'linkedin.com' => 'linkedin', | |
'mailto:' => 'envelope-o', | |
'medium.com' => 'medium', | |
'pinterest.com' => 'pinterest-p', | |
'getpocket.com' => 'get-pocket', | |
'reddit.com' => 'reddit-alien', | |
'skype.com' => 'skype', | |
'skype:' => 'skype', | |
'slideshare.net' => 'slideshare', | |
'snapchat.com' => 'snapchat-ghost', | |
'soundcloud.com' => 'soundcloud', | |
'spotify.com' => 'spotify', | |
'stumbleupon.com' => 'stumbleupon', | |
'tumblr.com' => 'tumblr', | |
'twitch.tv' => 'twitch', | |
'twitter.com' => 'twitter', | |
'vimeo.com' => 'vimeo', | |
'vine.co' => 'vine', | |
'vk.com' => 'vk', | |
'wordpress.org' => 'wordpress', | |
'wordpress.com' => 'wordpress', | |
'yelp.com' => 'yelp', | |
'youtube.com' => 'youtube', | |
); | |
/** | |
* Filter JDD Starter Themesocial links icons. | |
* | |
* @since JDD Starter Theme1.0 | |
* | |
* @param array $social_links_icons | |
*/ | |
return apply_filters( 'jdd_social_links_icons', $social_links_icons ); | |
} |

Step 3. Include icon-functions.php in your functions.php
Add this snippet of code to your function.php file.
// Add the SVG icons functions. | |
include_once( get_stylesheet_directory() . '/lib/icon-functions.php' ); |
Step 4. Inline the SVG sprite.
The icon-functions.php handles inlining the SVG sprite for us just before the closing body tag. With all of the icons inline, we can display them anywhere on the page without a separate HTTP request — and that shortens page load time.
With all the code in place, all we need to do is create a social icon menu and choose where to display it.
The name of the menu is very important as it must match the generated slug I am using in the code.
* @param array $args wp_nav_menu() arguments. | |
* @return string $item_output The menu item output with social icon. | |
*/ | |
function jdd_nav_menu_social_icons( $item_output, $item, $depth, $args ) { | |
$menu_object = wp_get_nav_menu_object( 'social-links-menu' ); | |



Wrapping Up
So there you have it. A simple social menu icon system that you can assign to a menu location and also use in a Custom Menu widget. The beauty of this method is that it opens the door to using the icons and graphics in lots of other ways within your content or design.
One simple way is to reference it directly within the text editor of your post with something like this:
<svg class="icon icon-content"><use xlink:href="#icon-play"></use></svg><svg class="icon icon-content"><use xlink:href="#icon-pause"></use></svg> |
I’ve wrapped an SVG element within a element that references the SVG with an
href
attribute for a specific icon ID. I’ve included some classes and a simple hover animation to the icons below to produce this:
.icon-content { | |
display: inline-block; | |
width: 100px; | |
height: 100px; | |
fill: rgb(48, 160, 210); | |
background-color: transparent; | |
border-radius: 0; | |
transition: all .3s ease-in; | |
margin: 10px 20px; | |
} | |
.icon-content:hover { | |
fill: tomato; | |
transform: scale(1.1); | |
} |