如何在WordPress中使用wp_nav_menu()为<li>添加Class?

70

我正在使用wp_nav_menu($args),我想将my_own_class CSS类名添加到<li>元素中。

我希望得到以下结果:

<li class='my_own_class'><a href=''>Link</a>

怎样做到那个?


这个函数的文档非常详细,但是似乎更容易将类添加到ul中或用某些东西包装链接内容并相应地更改CSS(自定义步行器是您的选择):http://codex.wordpress.org/Function_Reference/wp_nav_menu - C. E.
或者,您可以创建自己的菜单遍历器(Codex),并在wp_nav_menu()函数中使用它。 - Erenor Paz
16个回答

172
不需要创建自定义遍历程序。只需使用附加参数并为nav_menu_css_class设置过滤器即可。 例如:
$args = array(
    'container'     => '',
    'theme_location'=> 'your-theme-loc',
    'depth'         => 1,
    'fallback_cb'   => false,
    'add_li_class'  => 'your-class-name1 your-class-name-2'
    );
wp_nav_menu($args);

注意新的 'add_li_class' 参数。

并在 functions.php 上设置过滤器。

function add_additional_class_on_li($classes, $item, $args) {
    if(isset($args->add_li_class)) {
        $classes[] = $args->add_li_class;
    }
    return $classes;
}
add_filter('nav_menu_css_class', 'add_additional_class_on_li', 1, 3);

6
好的方案。如果我是楼主,我会接受这个答案。 - Peyman Mohamadpour
1
在我看来,最佳解决方案是通用且简洁的。 - Sogeking
3
最佳解决方案,但我需要修改它以避免出现错误“Undefined property: stdClass::$item_class”解决方案: 如果(isset($args->item_class)) { ...等等 - Stuart Cusack
1
1和3个参数的作用是什么?请解释。 - Mirajul Momin
1 是优先级顺序。数字越小,对应的执行越早,具有相同优先级的函数按照添加到操作中的顺序执行。3 是该函数接受的参数数量。在这种情况下,过滤器将接受 $classes、$items 和 $args 参数。请阅读 https://developer.wordpress.org/reference/functions/add_filter/ 以获取更多信息。 - Zunan
1
这对我没有用。我不得不添加array_key_exists('add_li_class', $args)而不是isset($args->add_li_class)。对于$classes[] = $args->add_li_class;,我必须添加$classes[] = $args['add_li_class']; - SplitterAlex

76
你可以在functions.php文件中为nav_menu_css_class操作添加过滤器。
示例:
function atg_menu_classes($classes, $item, $args) {
  if($args->theme_location == 'secondary') {
    $classes[] = 'list-inline-item';
  }
  return $classes;
}
add_filter('nav_menu_css_class', 'atg_menu_classes', 1, 3);

文档:https://developer.wordpress.org/reference/hooks/nav_menu_css_class/


7
我知道这个答案发布的时间比被选中的答案晚很多,但我认为它应该被标记为正确答案,因为它恰好做到了问题所要求的。 - Richard Hedges
我无法让它工作,直接复制到我的functions.php文件中,它什么也没做。 - Spencer Shattuck
1
@SpencerShattuck,你的主题中是否有一个名为“secondary”的菜单位置?你可能还需要像下面这样的代码:<code> register_nav_menus( array( 'primary' => __( 'Primary Menu' ), 'secondary' => __( 'Secondary Menu' ) ) ); </code> - Andres F Garcia
我在以下网址找到了适合我的解决方案:https://github.com/wp-bootstrap/wp-bootstrap-navwalker - Spencer Shattuck

68

这里是关于在WordPress中添加自定义类到wp_nav_menu链接的方法: WordPress add custom class in wp_nav_menu links

或者您可以从管理员面板中添加类<li class='my_own_class'><a href=''>Link</a></li>:

  1. 进入YOURSITEURL/wp-admin/nav-menus.php

  2. 打开 SCREEN OPTIONS

  3. 选中 CSS CLASSES,然后您将在每个菜单链接中看到一个 CSS Classes (optional)字段。

1
这是回答,楼主。 - samuelkobe
7
必须由最终用户完成,不能在主题中实现解决方案。 - user1447420
1
对于开发人员来说,这是最好的选择,尤其是当他们正在开发静态主题时。 - msz
1
对于庞大的菜单,这并不是一个实际可行的解决方案。 - th3pirat3

17

在不编辑functions.php文件的情况下,向<li>标签添加类:

  1. 进入外观->菜单->屏幕选项->CSS类
  2. 您将在菜单项窗口中启用CSS类选项

输入图片描述


15

请按照以下所示的方式使用此过滤器 nav_menu_css_class

function add_classes_on_li($classes, $item, $args) {
    $classes[] = 'nav-item';
    return $classes;
}
add_filter('nav_menu_css_class','add_classes_on_li',1,3);

更新

要将此筛选器用于特定菜单,请按如下操作:

if ( 'main-menu' === $args->theme_location ) { //replace main-menu with your menu
    $classes[] = "nav-item"; 
}

但是我们如何使用这种方法来针对特定的菜单呢?我有一个名为main-menu的菜单和另一个名为footer-menu的菜单。 - klewis
3
尝试使用 if ( 'main-menu' === $args->theme_location ) { $classes[] = "nav-item"; }$classes[] = "nav-item"; 包装起来。 - Regolith

6
如果你只想“添加类”,为什么不使用 str_replace 函数呢?请参考以下代码:
<?php
    echo str_replace( '<li class="', '<li class="myclass ',
        wp_nav_menu(
            array(
                'theme_location'    => 'main_menu',
                'container'         => false,
                'items_wrap'        => '<ul>%3$s</ul>',
                'depth'             => 1,
                'echo'              => false
            )
        )
    );
?>

虽然这是一个快速解决方案,适用于单层菜单或想要为所有<li>元素添加类的菜单,但不建议用于更复杂的菜单。


对于那些不使用标准的<li>作为项目的人来说,这是一个好主意。 - X9DESIGN

3

这些回答似乎都没有真正回答这个问题。以下是我在自己网站上使用的类似方法,通过目标菜单项的标题/名称进行定位:

function add_class_to_menu_item($sorted_menu_objects, $args) {
    $theme_location = 'primary_menu';  // Name, ID, or Slug of the target menu location
    $target_menu_title = 'Link';  // Name/Title of the menu item you want to target
    $class_to_add = 'my_own_class';  // Class you want to add

    if ($args->theme_location == $theme_location) {
        foreach ($sorted_menu_objects as $key => $menu_object) {
            if ($menu_object->title == $target_menu_title) {
                $menu_object->classes[] = $class_to_add;
                break; // Optional.  Leave if you're only targeting one specific menu item
            }
        }
    }

    return $sorted_menu_objects;
}
add_filter('wp_nav_menu_objects', 'add_class_to_menu_item', 10, 2);

3

我添加了一个类来方便实现菜单参数。因此,您可以按照以下方式自定义并包含在您的函数中:

include_once get_template_directory() . DIRECTORY_SEPARATOR . "your-directory" . DIRECTORY_SEPARATOR . "Menu.php";

<?php $menu = (new Menu('your-theme-location'))
            ->setMenuClass('your-menu')
            ->setMenuID('your-menu-id')
            ->setListClass('your-menu-class')
            ->setLinkClass('your-menu-link anchor') ?>
    
            // Print your menu
            <?php $menu->showMenu() ?>

<?php

class Menu
{
    private $args = [
        'theme_location' => '',
        'container' => '',
        'menu_id' => '',
        'menu_class' => '',
        'add_li_class' => '',
        'link_class' => ''
    ];

    public function __construct($themeLocation)
    {
        add_filter('nav_menu_css_class', [$this,'add_additional_class_on_li'], 1, 3);
        add_filter( 'nav_menu_link_attributes', [$this,'add_menu_link_class'], 1, 3 );

        $this->args['theme_location'] = $themeLocation;
    }

    public function wrapWithTag($tagName){
        $this->args['container'] = $tagName;
        return $this;
    }

    public function setMenuID($id)
    {
        $this->args['menu_id'] = $id;
        return $this;
    }

    public function setMenuClass($class)
    {
        $this->args['menu_class'] = $class;
        return $this;
    }

    public function setListClass($class)
    {
        $this->args['add_li_class'] = $class;
        return $this;
    }

    public function setLinkClass($class)
    {
        $this->args['link_class'] = $class;
        return $this;
    }

    public function showMenu()
    {
        return wp_nav_menu($this->args);
    }

    function add_additional_class_on_li($classes, $item, $args) {
        if(isset($args->add_li_class)) {
            $classes[] = $args->add_li_class;
        }
        return $classes;
    }

    function add_menu_link_class( $atts, $item, $args ) {
        if (property_exists($args, 'link_class')) {
            $atts['class'] = $args->link_class;
        }
        return $atts;
    }
}

2
<?php
    echo preg_replace( '#<li[^>]+>#', '<li class="col-sm-4">',
            wp_nav_menu(
                    array(
                        'menu' => $nav_menu, 
                        'container'  => false,
                        'container_class'   => false,
                        'menu_class'        => false,
                        'items_wrap'        => '%3$s',
                                            'depth'             => 1,
                                            'echo'              => false
                            )
                    )
            );
?>

2
您可以简单地使用wp_nav_menu_items过滤导航菜单的HTML列表内容。 显示导航菜单
wp_nav_menu( array(
   'theme_location' => 'parimary',
   'container' => 'ul',
   'menu_class'=> 'nav col-12 col-md-auto mb-2 justify-content-center mb-md-0',
   'add_li_class'  => 'your-class-name1 your-class-name-2',
) );


菜单注册
function thesportworship_register_menus(){
    register_nav_menus( array(
        'primary'  => __( 'Main Menu', 'thesportworship' ),
    ) );
}
add_action( 'after_setup_theme', 'thesportworship_register_menus', 0 );

应用筛选器
function add_additional_class($classes, $item, $args){
    if(isset($args->add_li_class)){
        $classes[] = $args->add_li_class;
    }
    return $classes;
}

add_filter('nav_menu_css_class', 'add_additional_class', 1, 3);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接