How to Add Icons to WordPress Menus (SVG Friendly)

December 19, 2025
How to Add Icons to WordPress Menus (SVG Friendly)

Adding icons to navigation menus can improve usability, especially on mobile. But doing it the wrong way can cause accessibility issues, inconsistent styling, and SVG problems.

This guide shows clean, SVG-friendly ways to add icons to WordPress menus without a plugin, including:

  • Adding icons via menu item CSS classes (recommended)
  • Outputting inline SVG safely (SVG-friendly)
  • Adding icons via a custom field on menu items (advanced)

Approach 1 (Recommended): Add Icon Classes to Menu Items

This method is fast, stable, and works with inline SVG via CSS masks or background images. It also avoids modifying menu HTML output.

Step 1: Enable “CSS Classes” in the Menu Screen

Go to:

  • Appearance → Menus
  • Open Screen Options (top right)
  • Enable CSS Classes

Now each menu item has a “CSS Classes” field.


Step 2: Add Icon Classes to Menu Items

Example classes:

  • has-icon icon-home
  • has-icon icon-blog
  • has-icon icon-contact

Step 3: Add CSS to Render Icons

This example uses a pseudo-element and SVG as a mask (great for SVG color control).

.menu a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.menu .has-icon > a::before {
  content: "";
  width: 1em;
  height: 1em;
  display: inline-block;
  background-color: currentColor;
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: contain;
}

.menu .icon-home > a::before {
  mask-image: url("/wp-content/themes/your-theme/assets/icons/home.svg");
}

.menu .icon-blog > a::before {
  mask-image: url("/wp-content/themes/your-theme/assets/icons/blog.svg");
}

.menu .icon-contact > a::before {
  mask-image: url("/wp-content/themes/your-theme/assets/icons/contact.svg");
}

Why this is SVG-friendly: using mask-image with background-color: currentColor means the icon automatically matches your text color.


Approach 2: Inline SVG Icons in Menu Markup (SVG-Friendly)

If you want maximum control (hover transitions, no external requests, full styling), inline SVG is best.

The cleanest method is to inject SVG into menu item output using the nav_menu_item_title filter.


Step 1: Add Icon Classes (Same as Approach 1)

Use menu item classes like:

  • icon-home
  • icon-blog

Step 2: Add a Function That Returns SVG by Key

Place the SVG files in your theme directory (example: /assets/icons/).

function wpcodetips_get_menu_svg_icon( $key ) {

  $map = array(
    'home'    => 'home.svg',
    'blog'    => 'blog.svg',
    'contact' => 'contact.svg',
  );

  if ( ! isset( $map[ $key ] ) ) {
    return '';
  }

  $file = get_stylesheet_directory() . '/assets/icons/' . $map[ $key ];
  if ( ! file_exists( $file ) ) {
    return '';
  }

  $svg = file_get_contents( $file );
  if ( ! is_string( $svg ) || $svg === '' ) {
    return '';
  }

  return $svg;
}

Step 3: Inject Inline SVG into the Menu Title

This checks menu item classes for icon-*, loads the matching SVG, and prepends it to the link text.

add_filter( 'nav_menu_item_title', function( $title, $item, $args, $depth ) {

  if ( empty( $item->classes ) || ! is_array( $item->classes ) ) {
    return $title;
  }

  $icon_key = '';

  foreach ( $item->classes as $class ) {
    if ( strpos( $class, 'icon-' ) === 0 ) {
      $icon_key = substr( $class, 5 );
      break;
    }
  }

  if ( $icon_key === '' ) {
    return $title;
  }

  $svg = wpcodetips_get_menu_svg_icon( $icon_key );
  if ( $svg === '' ) {
    return $title;
  }

  $svg = preg_replace( '/<svg\b/', '<svg class="menu-icon" aria-hidden="true" focusable="false"', $svg, 1 );

  return $svg . '<span class="menu-label">' . esc_html( wp_strip_all_tags( $title ) ) . '</span>';

}, 10, 4 );

Step 4: Style the Inline SVG

.menu a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.menu .menu-icon {
  width: 1em;
  height: 1em;
  display: inline-block;
  fill: currentColor;
}

Accessibility note: We set aria-hidden="true" so screen readers don’t announce decorative icons.


Approach 3: Add Icons via a Custom Field on Menu Items (Advanced)

If you want to select icons in the admin UI (instead of typing classes), you can add a custom field to menu items and store an icon key.

High-level idea:

  • Add a menu item meta field for icon key
  • Save it with wp_update_nav_menu_item
  • Inject SVG in nav_menu_item_title

This is more work, but scales well for non-technical editors.


Common Pitfalls (And How to Avoid Them)

  • Using icon fonts: extra requests, FOIT/FOUT, and often heavier than SVG
  • Putting icons inside the label text: messy and hard to maintain
  • Forgetting accessibility: decorative icons should be aria-hidden
  • Inlining untrusted SVG: only load SVG files you control

Best Practice Summary

  • Use menu item CSS classes to assign icons
  • Use CSS masks for simple, color-adaptive icons
  • Use inline SVG injection for maximum control
  • Keep icons decorative unless they carry meaning

Conclusion

Adding SVG-friendly icons to WordPress menus is easiest with CSS classes + masks, and most flexible with inline SVG injection. Both approaches keep your menu system clean, scalable, and easy to maintain — without relying on plugins.

Key takeaway:
Assign icons via menu item classes, then render them using CSS masks or safe inline SVG injection for a modern, lightweight solution.

Avatar

Written by

satoshi

I’ve been building and customizing WordPress themes for over 10 years. In my free time, you’ll probably find me enjoying a good football match.