Ask your WordPress questions! Pay money and get answers fast! (more info)

Adding a Class to Navigation Element WordPress

  • SOLVED

I would like to add another class to the navigation.php file. Currently there are only two classes: "current_subpage" and "has_subnav". I would like to add another class to the li with "has_subnav" that has a child of ‘current_subpage’ to show that the parent has an active child. So in other words, the class would need to be applied to the parent li that has a child with a current subpage. See example below. I believe this would be added to the navigation.php file, but im not sure what the PHP would be. Any direction or assistance is much appreciated. I am new to PHP so please let me know if I can provide any additional information. See attached file.

————————
Original
————————

<ul>
<li><a href="#"><span>Partner Resources</span></a></li>
<li class="has_subnav"><a href="#"><span>Become a Partner</span></a>
<ul>
<li class="current_subpage"><a href="#"><span>Partnership Inquiry Confirmation</span></a></li>
</ul>
</li>
</ul>

————————
Desired
————————

<ul>
<li><a href="#"><span>Partner Resources</span></a></li>
<li class="has_subnav current"><a href="#"><span>Become a Partner</span></a>
<ul>
<li class="current_subpage"><a href="#"><span>Partnership Inquiry Confirmation</span></a></li>
</ul>
</li>
</ul>

Answers (5)

2012-08-23

Ivaylo Draganov answers:

Hi there,

The solutiuon is probably simple, but you should provide some more info. The template that you mention - <em>navigation.php</em> is not a standard WP template file. It probably comes with the theme that you are using. Please tell us which is your theme and/or post the actual navigation.php file.


clandeene comments:

The theme I am using is Sterling by TrueThemes. Below is the PHP file. Thank you in advance!

<?php
/*-----------------------------------------------------------------------------------*/
/* Left Nav
/*-----------------------------------------------------------------------------------*/
class truethemes_sub_nav_walker extends Walker_Nav_Menu {
var $found_parents = array();

function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul>\n";
}

function start_el(&$output, $item, $depth, $args) {
global $wp_query, $item_output;
$parent_item_id = 0;
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$class_names = $value = '';
$classes = array();
if(in_array('current-menu-item',$item->classes)){
$classes[] = 'current_subpage';
}
global $wpdb;
$has_children = $wpdb->get_var($wpdb->prepare("SELECT COUNT(meta_id) FROM $wpdb->postmeta WHERE meta_key='_menu_item_menu_item_parent' AND meta_value='".$item->ID."'"));
if($has_children > 0){
$classes[] = 'has_subnav';
}

$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item));

if(!empty($class_names)){
$class_names = ' class="'.esc_attr($class_names).'"';
}

if (in_array('current-menu-item',$item->classes)|| in_array('current-menu-parent',$item->classes) || in_array('current-menu-ancestor',$item->classes) || (is_array($this->found_parents) && in_array($item->menu_item_parent, $this->found_parents))) {
$this->found_parents[] = $item->ID;
if ($item->menu_item_parent != $parent_item_id) {
$output .= $indent.'<li'.$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;
$item_output .= '<a'.$attributes.'><span>';
$item_output .= $args->link_before.apply_filters('the_title', $item->title, $item->ID).$args->link_after;
$item_output .= '</span></a>';
$item_output .= $args->after;
}
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
}

function end_el(&$output, $item, $depth) {
$parent_item_id = 0;

if (in_array('current-menu-item',$item->classes)|| in_array('current-menu-parent',$item->classes)|| in_array('current-menu-ancestor',$item->classes) || (is_array($this->found_parents) && in_array($item->menu_item_parent, $this->found_parents))) {
if (is_array($this->found_parents) && in_array($item->ID, $this->found_parents) && $item->menu_item_parent != $parent_item_id) {
$output .= "</li>\n";
}
}
}

function end_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
// If the sub-menu is empty, strip the opening tag, else closes it
if (substr($output, - 5) == "<ul>\n") {
$output = substr($output, 0, strlen($output) - 6);
} else {
$output .= "$indent</ul>\n";
}
}
}
function sterling_remove_empty_menu_tags($html_replace){
//removes any empty html tags.
$pattern = "/<[^\/>]*>([\s]?)*<\/[^>]*>/";
return preg_replace($pattern,'', $html_replace);
}
?>


Ivaylo Draganov comments:

Neat! That's exactly the file we need to change.

But I think that WP provides a class for what you want to highlite. Do you see a class <em>current-menu-ancestor</em> on the item that contains the current active page?


clandeene comments:

It has current-menu-ancestor in the top navigation only, in the sidebar nav, the only two classes that are applied are "current_subpage" and "has_subnav"

I have turned maintenance mode off on my website, so you can check it out. See this page (http://blog.zysolutions.com/about/press-releases/wsi-velocity-and-zy-solutions-announce-new-partnership/). In this example, I would like to add another class to the following LI tag.

<li class="has_subnav"><a href="http://blog.zysolutions.com/about/press-releases/"><span>Press Releases</span></a>


Ivaylo Draganov comments:

If you don't mind having all the WP classes dumped to your sidebar <li>'s then you can try replacing this line in <em>navigation.php</em>:

$classes = array();


with this:

$classes = empty( $item->classes ) ? array() : (array) $item->classes;


clandeene comments:

I would prefer not to have all of the styles not to get dumped into the sidebar since im using them for the top navigation styling, but this may work. I will get back to you shortly if this is the best solution.

Thanks again for all your help!

2012-08-23

Michael Caputo answers:

Are you using Wordpress's menu feature?

If you're using it properly it should add these classes (or something similar) in automatically.


clandeene comments:

I am using the Wordpress feature, but the classes are assigned in the navigation.php file. See my response to Ivaylo.

2012-08-23

Francisco Javier Carazo Gil answers:

Hi,

You should add class before in the CSS file of your theme. Then you can add it directly using menu's administration in your dashboard.


clandeene comments:

I dont believe that the css classes within the menu administration would address my issue, as a class should only be applied when a parent has a child that is active. The class should not be present at all times.


Francisco Javier Carazo Gil comments:

Clandsee,

Insrtead of modifying this php file, you can introduce an script after echo using JavaScript - jQuery.

I would like to add another class to the li with "has_subnav" that has a child of ‘current_subpage’ to show that the parent has an active child:


$("li.has_subnav > .current_subpage : parent").addClass("my_new_class");


You should create this new class into CSS file.


clandeene comments:

What file would I add this line of code to? The header php file?


Francisco Javier Carazo Gil comments:

You should add this at the end of navigation.php. This should be into a <script> tag.


<script>
$("li.has_subnav > .current_subpage : parent").addClass("my_new_class");
</script>


Remember also to create the new class. The class would be activated into the DOM but it would not appear in the source file.


clandeene comments:

Thanks for your assistance. I added your code to the very end of my navigation.php, uploaded it, and add the class to my css:

.my_new_class {
display:inline !important;
}

I dont see it being applied. Is there any other steps i'm missing? I'm a beginner so bear with me. :)


Francisco Javier Carazo Gil comments:

If the rule is only this, do not use add class use this one:

<script>
$("li.has_subnav > ul > li.current_subpage:parent").css("display", "inline");
</script>


clandeene comments:

I would like to add more than one rule, that is just what I started with.


Francisco Javier Carazo Gil comments:

If it is not running there will be a problem with jQuery selector, try this one:
<script>
$("li.has_subnav > ul > li.current_subpage:parent").addClass("my_new_class");
</script>


Francisco Javier Carazo Gil comments:

Sorry, I haven't see your HTML code well. You want to add "current" class exactly what you want.

Well. Try this:


$("li.has_subnav > ul > li.current_subpage").each(function () {
$(this).parent().parent().addClass("my_new_class");
});


clandeene comments:

Currently, it is still not working. Here is the PHP file. Anything that I am missing? I have added a style to the css file. If this works, it is exactly what I was looking for.

<?php
/*-----------------------------------------------------------------------------------*/
/* Register Menus
/*-----------------------------------------------------------------------------------*/
register_nav_menu('Main Menu', 'Main Menu');
register_nav_menu('Footer Menu', 'Footer Menu');



/*-----------------------------------------------------------------------------------*/
/* Custom Walker - Left Nav
/*-----------------------------------------------------------------------------------*/
class truethemes_sub_nav_walker extends Walker_Nav_Menu {
var $found_parents = array();

function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul>\n";
}

function start_el(&$output, $item, $depth, $args) {
global $wp_query, $item_output;
$parent_item_id = 0;
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
if(in_array('current-menu-item',$item->classes)){
$classes[] = 'current_subpage';
}
global $wpdb;
$has_children = $wpdb->get_var($wpdb->prepare("SELECT COUNT(meta_id) FROM $wpdb->postmeta WHERE meta_key='_menu_item_menu_item_parent' AND meta_value='".$item->ID."'"));
if($has_children > 0){
$classes[] = 'has_subnav';
}

$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item));

if(!empty($class_names)){
$class_names = ' class="'.esc_attr($class_names).'"';
}

if (in_array('current-menu-item',$item->classes)|| in_array('current-menu-parent',$item->classes) || in_array('current-menu-ancestor',$item->classes) || (is_array($this->found_parents) && in_array($item->menu_item_parent, $this->found_parents))) {
$this->found_parents[] = $item->ID;
if ($item->menu_item_parent != $parent_item_id) {
$output .= $indent.'<li'.$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;
$item_output .= '<a'.$attributes.'><span>';
$item_output .= $args->link_before.apply_filters('the_title', $item->title, $item->ID).$args->link_after;
$item_output .= '</span></a>';
$item_output .= $args->after;
}
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
}

function end_el(&$output, $item, $depth) {
$parent_item_id = 0;

if (in_array('current-menu-item',$item->classes)|| in_array('current-menu-parent',$item->classes)|| in_array('current-menu-ancestor',$item->classes) || (is_array($this->found_parents) && in_array($item->menu_item_parent, $this->found_parents))) {
if (is_array($this->found_parents) && in_array($item->ID, $this->found_parents) && $item->menu_item_parent != $parent_item_id) {
$output .= "</li>\n";
}
}
}

function end_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
// If the sub-menu is empty, strip the opening tag, else closes it
if (substr($output, - 5) == "<ul>\n") {
$output = substr($output, 0, strlen($output) - 6);
} else {
$output .= "$indent</ul>\n";
}
}
}
function sterling_remove_empty_menu_tags($html_replace){
//removes any empty html tags.
$pattern = "/<[^\/>]*>([\s]?)*<\/[^>]*>/";
return preg_replace($pattern,'', $html_replace);
}





/*-----------------------------------------------------------------------------------*/
/* Custom Walker - Gallery Filtering
/*-----------------------------------------------------------------------------------*/
class truethemes_gallery_walker extends Walker_Category {
function start_el(&$output, $category, $depth, $args) {
extract($args);
$cat_name = esc_attr( $category->name);
$cat_name = apply_filters( 'list_cats', $cat_name, $category );
$link = '<a href="#" data-filter=".term-'.$category->term_id.'" ';
if ( $use_desc_for_title == 0 || empty($category->description) )
$link .= 'title="' . sprintf(__( 'View all items filed under %s' , 'framework_localize'), $cat_name) . '"';
else
$link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
$link .= '>';
// $link .= $cat_name . '</a>';
$link .= $cat_name;
if(!empty($category->description)) {
$link .= ' <span>'.$category->description.'</span>';
}
$link .= '</a>';
if ( (! empty($feed_image)) || (! empty($feed)) ) {
$link .= ' ';
if ( empty($feed_image) )
$link .= '(';
$link .= '<a href="' . get_category_feed_link($category->term_id, $feed_type) . '"';
if ( empty($feed) )
$alt = ' alt="' . sprintf(__( 'Feed for all posts filed under %s' , 'framework_localize'), $cat_name ) . '"';
else {
$title = ' title="' . $feed . '"';
$alt = ' alt="' . $feed . '"';
$name = $feed;
$link .= $title;
}
$link .= '>';
if ( empty($feed_image) )
$link .= $name;
else
$link .= "<img src='$feed_image'$alt$title" . ' />';
$link .= '</a>';
if ( empty($feed_image) )
$link .= ')';
}
if ( isset($show_count) && $show_count )
$link .= ' (' . intval($category->count) . ')';
if ( isset($show_date) && $show_date ) {
$link .= ' ' . gmdate('Y-m-d', $category->last_update_timestamp);
}
if ( isset($current_category) && $current_category )
$_current_category = get_category( $current_category );
if ( 'list' == $args['style'] ) {
$output .= '<li class="segment-'.rand(2, 99).'"';
$class = 'cat-item cat-item-'.$category->term_id;
if ( isset($current_category) && $current_category && ($category->term_id == $current_category) )
$class .= ' current-cat';
elseif ( isset($_current_category) && $_current_category && ($category->term_id == $_current_category->parent) )
$class .= ' current-cat-parent';
$output .= '';
$output .= ">$link\n";
} else {
$output .= "\t$link<br />\n";
}
}
}
?>
<script>

$("li.has_subnav > ul > li.current_subpage").each(function () {

$(this).parent().parent().addClass("my_new_class");

});

</script>

2012-08-23

Jarret Minkler answers:

If you did it in PHP, the usual way is to compare the href's to the current url, in your case you are using dynamic menus it looks like. In this case it would be Javascript. Start by adding the class you want to the first menu item, or default. Then on click of any new menu item remove that class from the current, and apply it to the clicked item. Or, just use one of the many many many menu javascript menu code snips that are available anywhere. Jqueryui, bootstrap, yui, mootools etc etc


clandeene comments:

Unfortunately, I am new to PHP and JavaScript, so I would need a little bit more direction. I think what I need is to add some PHP to say if "child_children" and "has_subnav" and the child has "current_subpage" then apply class to parent "has_subnav" of current. The problem is I do not know how to write that cold.

2012-08-23

Daryl Lozupone answers:

Hi clandeene--

The WP menu system already does this for you. It appears, however, that you are not using that system. As Ivaylo says, <em>navigation.php</em> is not a standard WP template file, so I assume your theme is using some sort of custom menu system.

Here is an example of the built-in WP menu system output:

<li id="menu-item-54" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-ancestor current-menu-parent menu-item-54"><a href="#">Layouts</a>
<ul class="sub-menu">
<li id="menu-item-53" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-51 current_page_item menu-item-53"><a href="http://174.121.0.218/~violet/?page_id=51">Full Width</a></li>
<li id="menu-item-100" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-100"><a href="http://174.121.0.218/~violet/?page_id=98">Slider</a></li>
</ul>
</li>


In this case, the current page is <em>Full Width</em>. You can see that li element has a class of <em>current-menu-item</em>. It's parent, <em>Layout</em>, has a class of <em>current-menu-parent</em>.

If you would like assistance with setting up your theme to use WP's built-in navigation menus, I would be happy to help with that. Otherwise, you would have to do as Jarret suggested and write some javascript to apply classes to the li elements based on the current page's URL. It would then step up a level to the parent item of that current page and apply the 'current' class to that element as well.

I hope that helps.


clandeene comments:

Thanks for the response. As I mentioned to Ivaylo Draganov, it appears that the class current-menu-ancestor is in the top navigation only, in the sidebar nav, the only two classes that are applied are "current_subpage" and "has_subnav."


Daryl Lozupone comments:

Clandeene--

Looking at the HTML source for the page you listed above, I see the following code:

<li id="menu-item-1546" class="menu-item menu-item-type-post_type menu-item-object-page current-page-ancestor current-menu-ancestor current-menu-parent current-page-parent current_page_parent current_page_ancestor menu-item-1546"><a href="http://blog.zysolutions.com/about/press-releases/">Press Releases</a>

Notice all of the classes: <em>current-menu-parent</em>, <em>current-menu-ancestor</em>, etc.


Daryl Lozupone comments:

Ah yes, I see it now.


clandeene comments:

Yup, I just changed it per Ivaylo's suggestion, so that it would show all of the WP classes.