You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义Walker:实现子菜单项的多列拆分

动态拆分WordPress导航子菜单为多列的解决方案

我来帮你实现基于子项数量动态分组的多列子菜单!你的需求确实没法单纯用CSS搞定,得在自定义Walker类里做PHP层面的逻辑处理,以下是完整的修改方案:

核心思路

我们会在Walker类中加入子项计数逻辑,当渲染到指定数量的子项时,自动闭合当前列的<ul>并开启新的列容器,最后用CSS让这些列并排显示。

修改后的SC_Menu_Walker类

class SC_Menu_Walker extends Walker_Nav_Menu {
    // 新增成员变量用于追踪子项计数
    private $current_subitem_count = 0;
    private $total_subitems = 0;
    private $items_per_column = 3; // 可自定义每列最多显示的子项数

    function start_el(&$output, $item, $depth=0, $args=[], $id=0) {
        global $wp_query;
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
        $this->curItem = $item;
        $class_names = $value = '';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
        $class_names = ' class="'. esc_attr( $class_names ) . '"';

        // 仅对二级及以上子菜单项做列拆分处理
        if ($depth >= 1) {
            $this->current_subitem_count++;
            // 当达到每列上限时,闭合当前列并开启新列
            if ($this->current_subitem_count > 1 && $this->current_subitem_count % $this->items_per_column == 1) {
                $output .= '</ul><ul class="'.$this->get_column_menu_class($depth).'">';
            }
        }

        $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
        if ($item->url && $item->url != '#') {
            $output .= '<a href="' . $item->url . '">';
        } else {
            $output .= '<span>';
        }
        $output .= $item->title;
    }

    function start_lvl(&$output, $depth = 0, $args = array()) {
        $sc_page_item_label = get_post_meta( $this->curItem->object_id, '_sc_page_item_label', true );
        $sc_page_item_description = get_post_meta( $this->curItem->object_id, '_sc_page_item_description', true );
        $sc_page_item_url = get_post_meta( $this->curItem->object_id, '_sc_page_item_url', true );
        $sc_page_item_page_url = get_page_link($sc_page_item_url);
        $wrapperScrollStart="";
        
        if ($depth == 1) {
            $wrapperScrollStart="<div class='sub-menu__inner'>";
            $wrapperScrollEnd ='</div>';
        }

        // 获取当前父菜单项的所有子项总数
        $menu_id = is_object($args->menu) ? $args->menu->term_id : $args->menu;
        $menu_items = wp_get_nav_menu_items($menu_id, array(
            'post_parent' => $this->curItem->ID,
            'orderby' => 'menu_order',
            'order' => 'ASC'
        ));
        $this->total_subitems = count($menu_items);
        $this->current_subitem_count = 0;

        // 替换原单一ul为多列容器,初始化第一列
        $output .= '<div class="sub-menu sub"> <div class="o-custom-container"> <div class="sub-menu__wrapper_info o-sm-col-12 o-lg-col-5"><div class="o-lg-col-7"><h5>'.$sc_page_item_label.'</h5> <div class="u-font-size-medium">'.$sc_page_item_description.'</div></div> <div> <div class="c-learn-more-holder"> <div class="c-learn-more"> <a href="'.$sc_page_item_page_url.'" class="c-learn-more-link "></a> <div class="c-learn-more-title">Learn more</div> </div> </div> </div> </div>'.$wrapperScrollStart.'<div class="sub-menu__columns"><ul class="'.$this->get_column_menu_class($depth).'">';
    }

    function end_lvl(&$output, $depth = 0, $args = array()) {
        $wrapperScrollEnd = '';
        if ($depth == 1) {
            $wrapperScrollEnd ='</div>';
        }
        // 闭合最后一个列的ul和多列容器
        $output .= '</ul></div>'.$wrapperScrollEnd.'</div>';
    }

    // 辅助方法:复用菜单类逻辑
    private function get_column_menu_class($depth) {
        if ($depth == 1) {
            return "sub-menu__list sub-menu__list--scrollbar";
        }
        return "sub-menu__list o-sm-col-12 o-lg-col-7 u-font-size-medium";
    }
}

配套CSS样式

添加以下CSS让列并排显示,可根据你的设计需求调整:

.sub-menu__columns {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem; /* 列之间的间距 */
    margin-top: 1rem;
}

.sub-menu__columns .sub-menu__list {
    flex: 1 1 calc(50% - 1rem); /* 两列布局,自动平分宽度 */
    min-width: 280px; /* 小屏幕自动换行 */
    list-style: none;
    padding: 0;
}

关键逻辑说明

  1. 计数追踪:通过$current_subitem_count和$total_subitems变量记录当前子项位置和总数。
  2. 动态拆分:在start_el中,每渲染$items_per_column个子项就自动创建新列。
  3. 结构调整:将原单一<ul>替换为<div class="sub-menu__columns">容器,包裹所有列的<ul>。
  4. 灵活适配:如果需要自动根据子项数量分N列,可修改$items_per_column的计算方式,比如:
    // 自动分成两列,每列数量尽量平均
    $this->items_per_column = ceil($this->total_subitems / 2);
    

这样当你的首个导航项有6个子项时,会自动分成两列各3个;如果是5个,会分成3个+2个的布局,完全满足动态分组的需求。

内容的提问来源于stack exchange,提问作者CritingZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 15:32:27