I'm new to wordpress and trying to learn my way through from making a theme. Right now I am using wp_nav_menu to generate my menu My menu consists of pages and categories

However, the default generation of the menu looks like

<div id="navi">
<div class="menu-primary-container">  
  <ul id="menu-primary" class="menu">
    <li id="menu-item-14" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-14"></li>
    <li id="menu-item-16" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-16"></li>
    <li id="menu-item-20" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20"></li>
    <li id="menu-item-15" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-15"></li>
    <li id="menu-item-17" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-17"></li>

I want to remove all the class and id from li and ul. I have been googling for awhile now. Tried different methods and no luck. Any help would be much appreciated. I'm currently using Wordpress 3.1

Thank you in advance!

  • Use the Falcon plugin, it has a feature to cleanup menu item's ID & classes, but keep only essentials ones (like current-menu-item).
    – Anh Tran
    Aug 1, 2023 at 7:08

5 Answers 5


If you look in the wp_nav_menu() function, you see the items are written by walk_nav_menu_tree(), which calls Walker_Nav_Menu to do the work (unless you specified your own walker class). This class contains a method start_el() that is called for each menu item. In this function, you see that the classes are filtered through nav_menu_css_class and the id is filtered through nav_menu_item_id. So if you attach your own code to these hooks, you can change them to anything you want.

Submenus are always wrapped with <ul class="sub-menu">, the main wrapper can be changed via the menu_id and menu_class arguments.


You can change the id and class of each item with the nav_menu_item_id and nav_menu_css_class filter hooks like so:

add_filter('nav_menu_item_id', 'clear_nav_menu_item_id', 10, 3);
function clear_nav_menu_item_id($id, $item, $args) {
    return "";

add_filter('nav_menu_css_class', 'clear_nav_menu_item_class', 10, 3);
function clear_nav_menu_item_class($classes, $item, $args) {
    return array();

This will result in items saying <li id="" class="">. The same mechanism can be used to set IDs to something useful, such as the page slug.

  • 4
    Always best to use core WP return functions. So in this case use: add_filter( 'nav_menu_item_id', '__return_null', 10, 3 ); or add_filter( 'nav_menu_css_class', '__return_empty_array', 10, 3 );
    – WPExplorer
    Mar 7, 2018 at 22:17
function wp_nav_menu_remove_attributes( $menu ){
    return $menu = preg_replace('/ id=\"(.*)\" class=\"(.*)\"/iU', '', $menu );
add_filter( 'wp_nav_menu', 'wp_nav_menu_remove_attributes' );
  • will this prevent me from adding a "active" class for my active navigation?
    – eddyward
    Mar 23, 2011 at 5:25
  • Yes, because this is what u asked for.
    – zeo
    Mar 23, 2011 at 5:44

This solution was posted on wp3layout .You should add this to your theme's function.php

function remove_css_id_filter($var) {
    return is_array($var) ? array_intersect($var, array('current-menu-item')) : '';
add_filter( 'page_css_class', 'remove_css_id_filter', 100, 1);
add_filter( 'nav_menu_item_id', 'remove_css_id_filter', 100, 1);
add_filter( 'nav_menu_css_class', 'remove_css_id_filter', 100, 1);

Hope this helps.


I believe that you should keep menu-item-has-children & current-menu-item for styling

paste below code in your functions.php

//remove useless CSS classes for each li item
function remove_css_from_menu($var)
    return is_array($var) ? array_intersect($var, array('current-menu-item', 'menu-item-has-children',)) : '';
add_filter('nav_menu_css_class', 'remove_css_from_menu', 100, 1);
//remove ID for each li item
add_filter('nav_menu_item_id', '__return_false');
  • inspired from previous comment of @Jan Fabry
    – Abouasy
    Aug 1, 2023 at 5:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.