I am trying to alter Wordpress <?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?> default output. What I wish to do:
Pages that have a submenu looks like this:
<li class="menu-item-has-children">
Page with Submenu
<ul class="sub-menu">
<li class="menu-item-has-children">
Level 1 Submenu Page
<ul class="sub-menu">
<li>Level 2 Submenu Page</li>
</ul>
</li>
</ul>
</li>
What I need it to look like:
<li class="menu-item-has-children">
Page with Submenu <i class="fa fa-caret-down"></i>
<ul class="sub-menu">
<li class="menu-item-has-children">
Level 1 Submenu Page <i class="fa fa-angle-right"></i>
<ul class="sub-menu">
<li>Level 2 Submenu Page</li>
</ul>
</li>
</ul>
</li>
Any ideea on how can I achieve this by CSS, jQuery or PHP?
If you're adding the extra markup just to add a down arrow, why not do this with CSS:
.menu-item-has-children > a {
padding-right:20px;
position:relative;
}
.menu-item-has-children > a:after {
content:"";
border:5px solid transparent;
border-top-color:grey;
position:absolute;
right:0;
top:50%;
}
Here's a JSfiddle.
To answer your specific question: you'll need PHP. Then some CSS styling.
To be more specific, you'll need to use a Custom Walker. With a custom walker, you can tell WordPress to use different styling for a menu, then another style for a sub-menu and so on, which is your exact case. You even have an example code there, which I'm pasting below:
class themeslug_walker_nav_menu extends Walker_Nav_Menu {
// add classes to ul sub-menus
function start_lvl( &$output, $depth = 0, $args = array() ) {
// depth dependent classes
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
'sub-menu',
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// build html
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
}
// add main/sub classes to li's and links
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// depth dependent classes
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// passed classes
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
// build html
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
// link attributes
$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 ) .'"' : '';
$attributes .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';
$item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
// build html
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
it looks you know some coding, so I won't extend on this, but it's easy to see you only need to modify this:
$classes = array(
'sub-menu',
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
and/ or
// depth dependent classes
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
according to your needs. However, I STRONGLY RECOMMEND you read the page so you understand how it works, how you use it and when to use it.
Related
I've created a custom WordPress menu using the WordPress walker function. I've managed to do all the necessary HTML I need except adding the top-level menu title to just after one of the divs in the "start_lvl" section in the function.
Output should look like this:
<ul>
<li>Title
<div class="mega-menu">
<div class="mega-menu-inner">
<h2 class="fz-40">DISPLAY TOP MENU TITLE HERE</h2>
<ul class="mega-menu-accordion-wrap">
<li class="mega-menu-accordion">
<div class="mega-menu-accordion-inner">
<ul>
<li>
<div class="sub-mega-menu-wrap">
<ul>
<li></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</li>
</ul>
This is what I have so far for the WP nav walker:
wp_nav_menu( array(
'theme_location' => "header-menu",
'walker' => new WPDocs_Walker_Nav_Menu() ) );
/**
* Custom walker class.
*/
class WPDocs_Walker_Nav_Menu extends Walker_Nav_Menu {
/**
* Starts the list before the elements are added.
*
* Adds classes to the unordered list sub-menus.
*
* #param string $output Passed by reference. Used to append additional content.
* #param int $depth Depth of menu item. Used for padding.
* #param array $args An array of arguments. #see wp_nav_menu()
*/
function start_lvl( &$output, $depth = 0, $args = array() ) {
// Depth-dependent classes.
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
'sub-menu',
( $display_depth % 2 == 0 ? 'menu-odd' : 'mega-menu-accordion-wrap' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// Build HTML for output.
if( $display_depth === 1):
global $title;
$output .= '<div class="mega-menu">';
$output .= '<div class="mega-menu-container-wrap">';
$output .= '<div class="mega-menu-help-bar"><figure> <img src="'.get_template_directory_uri().'/svg/search-white.svg" alt=""></figure>Need some help?</div>';
$output .= '<div class="mega-menu-inner">';
$output .= '<h2 class="fz-40">Need the Title Here''</h2>';
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
elseif( $display_depth % 3 === 0):
$output .= "\n" . $indent . '<div class="sub-mega-menu-wrap">' . "\n";
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
elseif( $display_depth % 2 === 0):
$output .= "\n" . $indent . '<div class="mega-menu-accordion-inner">' . "\n";
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
else:
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
endif;
}
/**
* Start the element output.
*
* Adds main/sub-classes to the list items and links.
*
* #param string $output Passed by reference. Used to append additional content.
* #param object $item Menu item data object.
* #param int $depth Depth of menu item. Used for padding.
* #param array $args An array of arguments. #see wp_nav_menu()
* #param int $id Current item ID.
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// Depth-dependent classes.
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 == 0 ? 'menu-item-odd' : 'mega-menu-accordion' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// Passed classes.
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
// Build HTML.
if( $depth % 2 === 0):
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . ' ">';
else:
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
endif;
// Link attributes.
$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 ) .'"' : '';
$attributes .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';
// Build HTML output and pass through the proper filter.
$item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Solved this shortly after my post,
for anyone who requires this, I did the following:
Add this to the functions.php file:
function add_menu_title( $item_output, $item, $depth, $args ) {
global $menuTitle;
$menuTitle = $item->title;
return $item_output;
}
add_filter( 'walker_nav_menu_start_el', 'add_menu_title', 10, 4);
Then in your header template just add this to the section you would like it display. In my example I updated the depth===1 to the following:
if( $display_depth === 1):
global $menuTitle;
$output .= '<div class="mega-menu">';
$output .= '<div class="mega-menu-container-wrap">';
$output .= '<div class="mega-menu-help-bar"><figure> <img src="'.get_template_directory_uri().'/svg/search-white.svg" alt=""></figure>Need some help?</div>';
$output .= '<div class="mega-menu-inner">';
$output .= '<h2 class="fz-40">'.$menuTitle.'</h2>';
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
I am having issues with a design I have had back from the front end dev, I have created and set up a custom nav but due to the nature of the nav e.g its set in columns it requires me to add another div into the sub menu so the standard below wont work
<?php wp_nav_menu( array( 'theme_location' => 'my-custom-menu', 'container_class' => 'custom-menu-class' ) );
?>
Is there actually a way of doing this or is it impossible as I have tried lots of code I found but nothing seems to work I have posted the HTML i have to work with below so you get an idea, any help would be appreciated
<ul class="sf-menu">
<li>HOME</li>
<li>ABOUT
<div class="sf-mega" style="display: none">
<nav id="subNav">
<!-- container -->
<div class="container">
<div class="colFour menu first">
<ul>
<li>Page 1</li>
<li>Vision</li>
</ul>
</div>
<div class="colFour menu">
<ul>
<li>Page 2</li>
<li>pag3 3</li>
</ul>
</div>
<div class="colFour menu">
<ul>
<li>page 4</li>
<li>page 5</li>
</ul>
</div>
<div class="colFour menu">
<ul>
<li>page 6</li>
</ul>
</div>
</div>
<!-- /container -->
</nav>
</div>
</li>
<li>Test 1</li>
<li>Test 2</li>
<li>Test 3</li>
<li>VACANCIES</li>
<li>CONTACT</li>
</ul>
Look at Walker_Nav_Menu class. It defines how a menu items are printed and gives you full control over it.
From the resource:
wp_nav_menu( array(
'menu' => 'Your menu',
'walker' => new New_Walker_Nav_Menu()
) );
/**
* Custom walker class.
*/
class New_Walker_Nav_Menu extends Walker_Nav_Menu {
/**
* Starts the list before the elements are added.
*
* Adds classes to the unordered list sub-menus.
*
* #param string $output Passed by reference. Used to append additional content.
* #param int $depth Depth of menu item. Used for padding.
* #param array $args An array of arguments. #see wp_nav_menu()
*/
function start_lvl( &$output, $depth = 0, $args = array() ) {
// Depth-dependent classes.
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
'sub-menu',
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// Build HTML for output.
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
}
/**
* Start the element output.
*
* Adds main/sub-classes to the list items and links.
*
* #param string $output Passed by reference. Used to append additional content.
* #param object $item Menu item data object.
* #param int $depth Depth of menu item. Used for padding.
* #param array $args An array of arguments. #see wp_nav_menu()
* #param int $id Current item ID.
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// Depth-dependent classes.
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// Passed classes.
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
// Build HTML.
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
// Link attributes.
$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 ) .'"' : '';
$attributes .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';
// Build HTML output and pass through the proper filter.
$item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
I am using a custom nav walker and would like to create a tree menu.
Example:
<ul class="nav nav-list">
<li><label class="tree-toggler nav-header">Header 1</label>
<ul class="nav nav-list tree">
<li>Link</li>
<li>Link</li>
<li><label class="tree-toggler nav-header">Header 1.1</label>
<ul class="nav nav-list tree">
<li>Link</li>
<li>Link</li>
<li><label class="tree-toggler nav-header">Header 1.1.1</label>
<ul class="nav nav-list tree">
<li>Link</li>
<li>Link</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Now my goal is to check if a list item has a sub menu and if it has a sub menu I want to wrap the li's text in a label to create the collapse effect.
Here's my custom nav walker
class themeslug_walker_nav_menu extends Walker_Nav_Menu {
// add classes to ul sub-menus
function start_lvl( &$output, $depth ) {
// depth dependent classes
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
'sub-menu',
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// build html
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
}
// add main/sub classes to li's and links
function start_el( &$output, $item, $depth, $args ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// depth dependent classes
$depth_classes = array(
( $depth == 0 ? 'topElement' : 'parent' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// passed classes
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
if($depth === 0){
// build html
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '"><label class="tree-toggler">'.$item->title.'</label>';
}else{
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
};
// link attributes
$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 ) .'"' : '';
$attributes .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';
$item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
// build html
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
This works fine but only for the li's in my first depth.
So I am looking for a check if the li has a sub menu or not
Is there anyone who can help me out please.
Thanks in advance!
Simply check if has children (to be checked what is actual name of this class) class exist in $classes array.
if ( $args->has_children && $depth === 0 ) {
// if item (li) has children and its depth is 0
}
In wp v6 Bool param from
$args->walker->has_children
How can I do this:
I want to create menu using wp_nav_menu() and to customize it's output html a little. I want to put < i > in link < a > inside every < li > item of the menu.
I know that I can acomplish this using background-image of < li > items in css, but my goal is to use font icons inside navigation.
I also know that in order to acomplish this we can use walker function inside wp_nav_menu()or use wp_get_nav_menu_object() function, but I simply can't make it right to work.
Have you tried the before or the link_before options?
before will output before the <a> and link_before will output inside the <a> before the text.
http://codex.wordpress.org/Function_Reference/wp_nav_menu
$settings = array(
'before' => '<i class="icon"></i>',
'link_before' => '<i class="icon"></i>'
);
wp_nav_menu( $settings );
Use wp walker function and insert wp menu description there. Explaining more below -
Just put this code in your theme's functions.php file:
class fluent_themes_custom_walker_nav_menu extends Walker_Nav_Menu {
private $blog_sidebar_pos = "";
// add classes to ul sub-menus
function start_lvl( &$output, $depth = 0, $args = Array() ) {
// depth dependent classes
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
'dropdown-menu',
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? '' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// build html
$output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
}
// add main/sub classes to li's and links
function start_el( &$output, $item, $depth = 0, $args = Array(), $id = 0 ) {
global $wp_query, $wpdb;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// depth dependent classes
$depth_classes = array(
( $depth == 0 ? '' : '' ), //class for the top level menu which got sub-menu
( $depth >=1 ? '' : 'dropdown' ), //class for the level-1 sub-menu which got level-2 sub-menu
( $depth >=2 ? 'sub-sub-menu-item' : '' ), //class for the level-2 sub-menu which got level-3 sub-menu
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// passed classes
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
// build html
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
// link attributes
$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 ) .'"' : '';
//$attributes .= ' class="' . ( $depth > 0 ? '' : '' ) . '"';
// Check if menu item is in main menu
$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."'");
if ( $depth == 0 && $has_children > 0 ) {
// These lines adds your custom class and attribute
$attributes .= ' class="dropdown-toggle"';
$attributes .= ' data-toggle="dropdown"';
$attributes .= ' data-hover="dropdown"';
$attributes .= ' data-animations="fadeInUp"';
}
$description = ! empty( $item->description ) ? '<i class="fa '.esc_attr( $item->description ).'" aria-hidden="true"></i>' : '';
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $description.$args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; //If you want the description to be output after <a>
//$item_output .= $description.$args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; //If you want the description to be output before </a>
// Add the caret if menu level is 0
if ( $depth == 0 && $has_children > 0 ) {
$item_output .= ' <i class="fa fa-caret-down"></i>';
}
$item_output .= '</a>';
$item_output .= $args->after;
// build html
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args, $id );
}
} //End Walker_Nav_Menu
See this line:
$description = ! empty( $item->description ) ? '<i class="fa '.esc_attr( $item->description ).'" aria-hidden="true"></i>' : '';
And this line:
$item_output .= $description.$args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
Here you see $item->desctiption is a variable. For example: if you put fa-user as menu item description of a menu. The html output of the above line will be:
The full html output of the menu will be something like this:
<ul class="top-nav nav-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-hover="dropdown" data-toggle="dropdown" data-animations="fadeInUp">
<i class="fa fa-user" aria-hidden="true"></i>My Profile
<i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu ">
<li><i class="icon-bargraph"></i> Dashboard</li>
<li><i class="icon-gears"></i> Profile Setting</li>
<li><i class="icon-heart"></i> Questions</li>
<li><i class="icon-lock"></i> Logout</li>
</ul>
</li>
</ul>
However, here is your wp nav menu code in your header.php file or in any other theme files:
wp_nav_menu( array('theme_location' => 'top_bar_login','container' => false,'container_id' => '','conatiner_class' => '','menu_class' => 'top-nav nav-right','echo' => true,'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>','depth' => 10, 'walker' => new fluent_themes_custom_walker_nav_menu) );
If you are not sure where is the description of wordpress menu, or you want more details with screenshot. You can read this article Adding Different Icons To Different Items Of WP Nav Menu
I'am also trying to add icons in my menu.
I've tried before and link_before options but I did't find the way to get any item's variables inside these args.
My aim is to get the following output using Title Attribute set in Custom Link from Customize Menus
<li id="menu-item-30" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-30">
<a title="social-facebook" href="http://facebook.com">
<i class="fi-social-facebook"></i>Facebook Page
</a>
</li>
<li id="menu-item-30" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-30">
<a title="social-google-plus+" href="http://plus.google.com">
<i class="fi-social-google-plus"></i>Google+ Page
</a>
</li>
I've also check the other answer but I don't know how to add thumbnails in the Custom Link of the Customize Menus.
paste code to the page where you output your nav
<?php
wp_nav_menu(
array(
'theme_location' => 'primary',
'container' => false,
'walker' => new my_nav_walker()
)
);
?>
and then call walker.php in functions.php
require get_template_directory().'/inc/walker.php';
copy class Walker_Nav_Menu in class-walker-nav-menu.php from wp-includes folder
change Walker_Nav_Menu class to my_nav_walker
and then inside function start_el of my_nav_walker class
make a variable called $description as:
$description = ! empty( $item->description ) ? '<i class="fa '.esc_attr( $item->description ).'" ></i>' : '';
Paste this code inside start_el function of my_nav_walker class
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $description.$args->link_before . $title . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
if you add fa-user in description of menu item from backend user icon appear between a href tag inside li
We are building a theme on WordPress 3.5.1 and we created two custom menus - one for the header and one for the footer. In the footer the titles are not linkable, therefore we created custom links with href "#" and then changed the href to "". The result are empty links with <a>. I know it's possible to change the cursor of these empty links with CSS:
.footer-content #sitemap ul.menu > li.menu-item > a {
cursor: text;
}
and I also found out a way to remove these empty links with JavaScript and jQuery:
$('.footer-content #sitemap ul.menu > li.menu-item > a').each(function() {
// If href is empty, remove <a> element.
var href = $(this).attr('href');
var href_length = 0;
if (!(typeof href === 'undefined')) {
var href_length = href.length;
}
if (href_length === 0) {
var contents = $(this).contents();
$(this).replaceWith(contents);
}
});
(the footer menu is inside the .footer-content #sitemap elements:
<div class="footer-content">
<div id="sitemap" class="not_mobile">
)
but is it possible to remove the empty <a> elements from the HTML without using JavaScript? The function that creates the footer menu is:
<?php wp_nav_menu( array( 'theme_location' => 'footer_menu' ) ); ?>
Thanks,
Uri # Initech.
Yes, It is possible. You can use the walker. Put the following class in your functions.php file
class themeslug_walker_nav_menu extends Walker_Nav_Menu {
// add main/sub classes to li's and links
function start_el( &$output, $item, $depth, $args ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// depth dependent classes
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// passed classes
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
// build html
$output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="' . $depth_class_names . ' ' . $class_names . '">';
// link attributes
$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 ) .'"' : '';
$attributes .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';
if($depth == 0) {
$item_output = sprintf( '%1$s%2$s%3$s%4$s%5$s',
$args->before,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
} else {
$item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
}
// build html
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
and add this walker in your wp_nav_menu function
<?php wp_nav_menu( array( 'theme_location' => 'footer_menu', 'walker' => new themeslug_walker_nav_menu ) ); ?>
This will remove the anchor tag <a> from each menu item.
OK, I found a solution. I searched and found out function start_el(...) on class Walker_Nav_Menu, then copied it and changed only the last part of it:
class themeslug_walker_nav_menu extends Walker_Nav_Menu {
/**
* #see Walker::start_el()
* #since 3.0.0
*
* #param string $output Passed by reference. Used to append additional content.
* #param object $item Menu item data object.
* #param int $depth Depth of menu item. Used for padding.
* #param int $current_page Menu item ID.
* #param object $args
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$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_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $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 ) .'"' : '';
$item_output = $args->before;
if (! empty( $item->url )) {
$item_output .= '<a'. $attributes .'>';
}
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
if (! empty( $item->url )) {
$item_output .= '</a>';
}
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Then I changed the call to wp_nav_menu on footer.php:
<?php wp_nav_menu( array( 'theme_location' => 'footer_menu', 'walker' => new themeslug_walker_nav_menu ) ); ?>
It works and there are no <a> links when the href is empty (my changes are both ifs: if (! empty( $item->url )) {). Thanks to Mangesh Parte for the idea.
Uri.