1

I am trying to edit the default arguments in the wp_nav_menu function. Basically I need to add a custom class to the UL and a custom class to the LI.

I have tried to use

<?php
function my_wp_nav_menu_args( $args = '' )
{
    $args['menu_class'] = "test";
    return $args;
} // function

add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );
?>

This added a test to the div outside.I tried to edit

'items_wrap' => '%3$s',

no luck.

4
  • 1
    Haven't you tried custom class mentioned in THIS built-in function? Commented Jul 5, 2013 at 20:15
  • which one specifically?
    – user31344
    Commented Jul 5, 2013 at 20:26
  • $menu_class & 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>'? Commented Jul 5, 2013 at 20:32
  • yeah I tried that no dice, I am using a walker class and that seems to be doing it right. It's not explained very well, but apparantly you set up a walker class in the functions.php and then call that in your template.
    – user31344
    Commented Jul 5, 2013 at 20:45

1 Answer 1

0

This is an old question, but might be very much relevant still today so I thought I would drop a piece of code I developed over the years. It's basically as close as you can get to customizing classes on every element of a menu in WordPress without developing a custom Nav Walker. This is getting more and more relevant with utility-first CSS framweworks like Tailwind that really require you to have access to the markup or options to add your own classes.

It uses most of the filters available in the WordPress wp_nav_menu function and lifecycle to add classes everywhere. First, you use wp_nav_menu as you would usually, but then pass custom parameters to the function. Those custom parameters are then detected by the filters and add the classes where they need to be.

One would be able, for example, to create a custom dropdown menu by adding only classes to the first level of list elements or add a background image / icon to only 3rd level links. All the possible options are detailed in the docblock at the top.

<?php
/**
 * WordPress filters to allow custom arguments to wp_nav_menu to,
 * in turn, allow custom classes to every element of a menu.
 *
 * You can apply a class only to certain depth of your menu as well.
 *
 * The filters use the depth argument given by WordPress
 * which is an index, thus starts with level 0 (zero).
 *
 * Custom Arguments supported : 
 * link_atts or link_atts_$depth            ->      Add any attribute to <a> elements
 * a_class or a_class_$depth                ->      Add classes to <a> elements
 * li_class or li_class_$depth              ->      Add classes to <li> elements
 * submenu_class or submenu_class_$depth    ->      Add classes to submenu <ul> elements
 *
 * Ex.: add a "text-black" class to all links and "text-blue" class only to 3rd level links
 * wp_nav_menu([
 *     'theme_location' => 'primary_navigation',
 *     'a_class' => 'text-black',
 *     'a_class_2'
 *     ...
 * ])
 *
 * Ex.: More complete example with some TailwindCSS classes and AlpineJS sugar
 * wp_nav_menu([
 *     'theme_location' => 'primary_navigation',
 *     'menu_class' => 'relative w-full z-10 pl-0 list-none flex',
 *     'link_atts_0' => [
 *         ":class" => "{ 'active': tab === 'foo' }",
 *         "@click" => "tab = 'foo'"
 *     ],
 *     'li_class' => 'w-full',
 *     'li_class_0' => 'mb-12',
 *     'a_class' => 'text-sm xl:text-xl text-white border-b hover:border-white',
 *     'a_class_0' => 'text-3xl xl:text-5xl relative dash-left js-stagger  a-mask after:bg-primary',
 *     'li_class_1' => 'js-stagger a-mask after:bg-primary hidden lg:block',
 *     'a_class_1' => 'flex h-full items-center uppercase py-2 relative border-white border-opacity-40 hover:border-opacity-100',
 *     'submenu_class' => 'list-none pl-0 grid grid-cols-1 lg:grid-cols-2 lg:gap-x-12 xl:gap-x-24 xxl:gap-x-32',
 *     'container'=>false
 * ])
 * 
 * @author davidwebca
 * @link https://gist.github.com/davidwebca/a7b278bbb0c0ce1d1ec5620126e863bb
 */


/**
 * Add custom attributes or classes to links in wp_nav_menu
 */
add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) {
    if (property_exists($args, 'link_atts')) {
        $atts = array_merge($atts, $args->link_atts);
    }
    if (property_exists($args, "link_atts_$depth")) {
        $atts = array_merge($atts, $args->{"link_atts_$depth"});
    }

    if(empty($atts['class'])) {
        $atts['class'] = '';
    }

    $classes = explode(' ', $atts['class']);

    /**
     * Fix for tailwindcss classes that include ":" (colon)
     * Enter triple underscore hover___text-primary instaed of hover:text-primary
     *
     * Some filters provided so that you can customize your own replacements,
     * passed directly to preg_replace so supports array replacements as well.
     *
     * WordPress trac following the issue of escaping CSS classes:
     * @link https://core.trac.wordpress.org/ticket/33924
     */
    $patterns = apply_filters( 'nav_menu_css_class_unescape_patterns', '/___/');
    $replacements = apply_filters( 'nav_menu_css_class_unescape_replacements', ':' );
    $classes = array_map(function($cssclass) use( $patterns, $replacements) {
        return preg_replace($patterns, $replacements, $cssclass);
    }, $classes);

    if (property_exists($args, 'a_class')) {
        $arr_classes = explode(' ', $args->a_class);
        $classes = array_merge($classes, $arr_classes);
    }
    if (property_exists($args, "a_class_$depth")) {
        $arr_classes = explode(' ', $args->{"a_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    $atts['class'] = implode(' ', $classes);

    return $atts;
}, 1, 4 );

/**
 * Add custom classes to lis in wp_nav_menu
 */
add_filter( 'nav_menu_css_class', function ( $classes, $item, $args, $depth ) {
    if (property_exists($args, 'li_class')) {
        $arr_classes = explode(' ', $args->li_class);
        $classes = array_merge($classes, $arr_classes);
    }
    if (property_exists($args, "li_class_$depth")) {
        $arr_classes = explode(' ', $args->{"li_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    return $classes;
}, 1, 4 );

/**
 * Add custom classes to ul.sub-menu in wp_nav_menu
 */
add_filter('nav_menu_submenu_css_class', function( $classes, $args, $depth ) {
    if (property_exists($args, 'submenu_class')) {
        $arr_classes = explode(' ', $args->submenu_class);
        $classes = array_merge($classes, $arr_classes);
    }

    if (property_exists($args, "submenu_class_$depth")) {
        $arr_classes = explode(' ', $args->{"submenu_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    return $classes;
}, 1, 3);

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.