Home › Forums › Front-end Issues › 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);
}
}
Hi @liqid,
What does ‘social_icon_static’ return?
If you hard code that line (so do away with the get_field part), does it still display outside the tag? If not, then it’s how the include is working.
I’m sure I had similar once before with something. If you declare the get_field above, then include the $var, does that work:
if ( $depth == 0 ) {
$social_icon_static = get_field('social_icon_static', $item);
$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', $social_icon_static) .' </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>';
}
If hard coding still blows it out, then it must be non ACF related. Sometimes, using the browser inspect tool can help as you can play about with it, then adjust the code accordingly.
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.
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.
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.
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.
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.