Support

Account

Home Forums Front-end Issues Append Inline SVG to Menu item

Solving

Append Inline SVG to Menu item

  • Trying to setup an inline SVG custom icon to use for top menu links using walker script and acf text field. I can get the svg icons to render, but its outside the <a> tag of the menu link. Not sure why it’s not appending between the tags. Any help would be appreciated.

    class Top_Nav extends \Walker_Nav_Menu
    {
    
        function start_lvl(&$output, $depth = 0, $args = array())
        {
            $indent = str_repeat("\t", $depth);
    
            // Change sub-menu to dropdown menu
            $output .= "\n$indent<div class=\"\"><ul class=\"\">\n";
        }
    
        function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
        {
            // Most of this code is copied from original Walker_Nav_Menu
            global $wp_query, $wpdb;
            $indent = ($depth) ? str_repeat("\t", $depth) : '';
    
            $class_names = $value = '';
    
            $classes = empty($item->classes) ? array() : (array) $item->classes;
            $classes[] = 'menu-item-' . $item->ID;
    
            $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
            $class_names = ' class="' . esc_attr($class_names) . '"';
    
            $id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args);
            $id = strlen($id) ? ' id="' . esc_attr($id) . '"' : '';
    
            $has_children = $wpdb->get_var("SELECT COUNT(meta_id)
                                  FROM wp_postmeta
                                  WHERE meta_key='_menu_item_menu_item_parent'
                                  AND meta_value='" . $item->ID . "'");
    
            $output .= $indent . '<li' . $id . $value . $class_names . '>';
    
            $attributes  = !empty($item->attr_title) ? ' title="'  . esc_attr($item->attr_title) . '"' : '';
            $attributes .= !empty($item->target)     ? ' target="' . esc_attr($item->target) . '"' : '';
            $attributes .= !empty($item->xfn)        ? ' rel="'    . esc_attr($item->xfn) . '"' : '';
            $attributes .= !empty($item->url)        ? ' href="'   . esc_attr($item->url) . '"' : '';
    
            // Check if menu item is in main menu
            if ($depth == 0 && $has_children > 0) {
                // These lines adds your custom class and attribute
                $attributes .= ' class=""';
                $attributes .= '';
            }
    
            $item_output = $args->before;
            $item_output .= '<a' . $attributes . '>';
            $item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
            
    
          if ( $depth == 0 ) {
    
              $item_output .= '<div class="uk-inline-clip uk-transition-toggle uk-animation-toggle social-icon-container" tabindex="0">
    
                <svg class="uk-animation-slide-top uk-animation-reverse social-top" width="16px" height="16px"> '. get_template_part( 'assets/images/svg/inline', get_field('social_icon_static', $item)) .' </svg>
      
                <svg class="uk-transition-slide-bottom social-bottom" width="16px" height="16px"> '. get_template_part( 'assets/images/svg/inline', get_field('social_icon_hover', $item)) .' </svg>
      
              </div>';
          }
    
            $item_output .= '</a>';
            $item_output .= $args->after;
    
            $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
        }
    }
  • if I Hardcode it pulls in correctly. Your solution though renders the same result. Not sure why it would push it outside the tags of where I want it. Any other ideas? May have to use the svg plugin, but was hoping that wouldn’t be the case.

  • Hi @liqid

    Ok, so hardcoding works, which means it must be when outputting the field that additional code(?) is being added.

    If you hard code it and it works, copy the line into something like notepad

    Then, add your code back in, inspect it and copy the line into notepad

    If you compare them, does the latter one have anything different? If so, what is the difference?

  • the difference is that it has to pull the svg data from an external file as opposed to just hard coding the data in the function. At one point when testing I commented out the get_template_part and they were stilling rendering with just the variables, but I haven’t been able to replicate.

  • What does get_field(‘social_icon_static’); output?

    May help to then se what’s happening.

  • this get_field(‘social_icon_static’); on its own outputs nothing, but this get_field('social_icon_static', $item) outputs whatever is in the text field inside the correct tags.

    screenshot of output

    Is that what you’re asking?

    For some reason pulling in the svg renders it outside the tags of where I want it.

  • Sorry, can you show what you enter into the field of ‘social_icon_static’

    Ideally, it would be useful to see the code when it’s hardcoded

    Then copy and paste the source when you’re outputting the code with the ACF field

    Just trying to work out the difference as to why one works and one doesn’t!

  • Sorry, I think misunderstood what you were asking before.

    Here’s what the ACF field outputs:
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><path style="fill:#fff" d="M3.305 49.574v79.388h143.916V49.708L75.382 80.745 3.305 49.574z"></path><path style="fill:#fff" d="M3.305 21.777v13.846l72.077 31.172 71.839-31.068v-13.95H3.305z"></path></svg>

    Here’s the hardcode:
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><path style="fill:#fff" d="M3.305 49.574v79.388h143.916V49.708L75.382 80.745 3.305 49.574z"></path><path style="fill:#fff" d="M3.305 21.777v13.846l72.077 31.172 71.839-31.068v-13.95H3.305z"></path></svg>

    Look identical to me.

    Here’s a screenshot of the output. The top <svg> tag is the acf field rendering outside the <a> tag and the bottom is the hardcoded version. Disregard the <img> tag, I decided to use the SVG plugin till we resolve this.

    acf and hardcode output

    Hope this is what you were asking for.

  • I think I misunderstood what you were asking before, hope this is what your looking for.

    ACF output:
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><path style="fill:#fff" d="M3.305 49.574v79.388h143.916V49.708L75.382 80.745 3.305 49.574z"></path><path style="fill:#fff" d="M3.305 21.777v13.846l72.077 31.172 71.839-31.068v-13.95H3.305z"></path></svg>

    Hardcoded output:
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><path style="fill:#fff" d="M3.305 49.574v79.388h143.916V49.708L75.382 80.745 3.305 49.574z"></path><path style="fill:#fff" d="M3.305 21.777v13.846l72.077 31.172 71.839-31.068v-13.95H3.305z"></path></svg>

    Look identical to me.

    Below is a screenshot of the actual output. The top <svg> tag is the acf field and the bottom is the hardcode between the <a> tag. Disregard the <img> tag as I’m using the SVG plugin till this is resolved.

    ACF and hardcode output

    Here’s the code:

            $social_icon_static = get_field('social_icon_static', $item);
            //$social_icon_hover = get_field('social_icon_hover', $item);
    
          if ( $depth == 0 ) {
    
              $item_output .= '</span><div class="uk-inline-clip uk-transition-toggle uk-animation-toggle social-icon-container" tabindex="0">
    
                <img class="uk-animation-slide-top uk-animation-reverse social-top" width="16px" height="16px" src="">
                '. get_template_part( 'assets/images/svg/inline', $social_icon_static) .'
                <img class="uk-transition-slide-bottom social-bottom" width="16px" height="16px" src="">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><path style="fill:#fff" d="M3.305 49.574v79.388h143.916V49.708L75.382 80.745 3.305 49.574z"/><path style="fill:#fff" d="M3.305 21.777v13.846l72.077 31.172 71.839-31.068v-13.95H3.305z"/></svg>
      
              </div>';
          }
  • What happens if you change your if depth conditional from
    if ( $depth == 0 ) {
    to if ($depth == 0 && $has_children > 0) {

    As you say, the svg code is the same but the svg is called in the wrong place. So need to work out why.

  • Nothing shows when changing the conditional, since the menu-item must have children in-order to append the icons. And when I add sub-items to the menu to meet the conditional it does the same thing as before.

  • If I’m not mistaken, your code isn’t matching your output – I could be wrong!

    In the first post, you had two SVG’s referenced but they’re not showing, only 1 is in the screenshot. Although the second SVG reference is missing in your latest code

    In the last code snippet you supplied, you have a rogue closing span before the opening div

    But I can’t see this in the output?

  • Yes, in my first piece of code I was wrapping the output svg with <svg> tags, but I’ve since changed it because I’m utilizing the svg plugin with ACF image fields, which outputs correctly. That’s why I said disregard the <img> tags. Even if I take these <img> tags out the acf field still appends outside of the <div> wrappers.

    In the screenshot what your seeing is the hardcoded svg output between the div wrappers and the acf text field svg gets bumped outside of those. The <span> tag is wrapping the text of the <a> tag.

    screenshot output with graphic callouts

Viewing 14 posts - 1 through 14 (of 14 total)

You must be logged in to reply to this topic.