The Menu Icons plugin is the easy approach to navigation icons. If you prefer to avoid the plugin dependency or want more precise control, here is how to add icons without a plugin.
Method 1: CSS Class with Background Image
In WordPress Menus (Appearance, then Menus), enable the CSS Classes option under Screen Options. Each menu item then has a CSS Class field. Add a descriptive class to each menu item you want an icon on — for example: nav-home, nav-about, nav-contact.
In your child theme stylesheet or Additional CSS:
.nav-home a::before {
content: '';
display: inline-block;
width: 18px;
height: 18px;
background-image: url('/wp-content/themes/your-child-theme/images/icon-home.svg');
background-size: contain;
background-repeat: no-repeat;
margin-right: 6px;
vertical-align: middle;
}
.nav-about a::before {
content: '';
display: inline-block;
width: 18px;
height: 18px;
background-image: url('/wp-content/themes/your-child-theme/images/icon-about.svg');
background-size: contain;
background-repeat: no-repeat;
margin-right: 6px;
vertical-align: middle;
}
Place your SVG icon files in a directory within your child theme and reference them with the correct path.
Method 2: Custom Menu Walker with Inline SVG
For more control, use a custom menu walker that injects inline SVG based on the menu item slug or CSS class. Add this to your child theme functions.php:
class WPWizzy_Menu_Walker extends Walker_Nav_Menu {
public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
$icon = '';
$classes = implode( ' ', $item->classes );
if ( strpos( $classes, 'nav-home' ) !== false ) {
$icon = '<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg> ';
} elseif ( strpos( $classes, 'nav-cart' ) !== false ) {
$icon = '<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M7 18c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM5.2 5H2V3H0v2h2l3.6 7.6L4.2 15c-.1.3-.2.6-.2.9 0 1.1.9 2 2 2h14v-2H6.4c-.1 0-.2-.1-.2-.2l.1-.3.9-1.5H19c.75 0 1.41-.41 1.75-1.03l3.58-6.49A1 1 0 0 0 23.46 5H5.2z"/></svg> ';
}
$output .= '<li class="' . esc_attr( $classes ) . '">';
$output .= '<a href="' . esc_url( $item->url ) . '">' . $icon . esc_html( $item->title ) . '</a>';
}
}
// Use the custom walker in wp_nav_menu calls
add_filter( 'wp_nav_menu_args', function( $args ) {
if ( $args['theme_location'] === 'primary' ) {
$args['walker'] = new WPWizzy_Menu_Walker();
}
return $args;
} );
Advantages of the No-Plugin Approach
- No additional plugin loading on every page.
- Full control over SVG paths and styling.
- Icons are part of the theme, not dependent on a plugin remaining active.
- Inline SVGs can be styled with CSS (fill: currentColor inherits the link colour).
When to Use the Plugin Instead
The plugin is faster to implement for non-developers, easier to update when icons change, and does not require child theme access. If you are on a site where editing theme files is not practical, Menu Icons is the more accessible solution. If you need precise control and are comfortable with CSS and PHP, the code approach is cleaner.
For full custom navigation development including mega menus, animated dropdowns, and accessibility-compliant navigation with ARIA attributes, a WordPress developer can build a complete custom navigation solution.