Пользовательский класс для wp nav menu

Вопрос или проблема

Я пытаюсь изменить аргументы по умолчанию в функции wp_nav_menu.
В основном мне нужно добавить пользовательский класс к UL и пользовательский класс к LI.

Я пробовал использовать

<?php
function my_wp_nav_menu_args( $args="" )
{
    $args['menu_class'] = "test";
    return $args;
} // функция

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

Это добавило “test” к внешнему div. Я пытался изменить

‘items_wrap’ => ‘%3$s’,

не повезло.

Это старый вопрос, но он может быть по-прежнему очень актуален, поэтому я решил разместить фрагмент кода, который я разработал за эти годы. Это, по сути, наиболее близкий способ персонализировать классы для каждого элемента меню в WordPress без разработки собственного Nav Walker. Это становится все более актуальным с утилитарными CSS-фреймворками, такими как Tailwind, которые действительно требуют доступа к разметке или опциям для добавления собственных классов.

Он использует большинство фильтров, доступных в функции wp_nav_menu и жизненном цикле, чтобы добавить классы везде. Во-первых, вы используете wp_nav_menu, как обычно, но затем передаете пользовательские параметры в функцию. Эти пользовательские параметры затем обнаруживаются фильтрами и добавляют классы, где это необходимо.

Например, можно создать пользовательское выпадающее меню, добавив только классы к элементам списка первого уровня, или добавить фоновое изображение/иконку только к ссылкам третьего уровня. Все возможные опции подробно описаны в первом комментарии.

<?php
/**
 * Фильтры WordPress для разрешения пользовательских аргументов для wp_nav_menu, 
 * чтобы, в свою очередь, разрешить пользовательские классы для каждого элемента меню.
 *
 * Вы также можете применить класс только к определенной глубине вашего меню.
 *
 * Фильтры используют аргумент глубины, заданный WordPress,
 * который является индексом, и, следовательно, начинается с уровня 0 (ноль).
 *
 * Поддерживаемые пользовательские аргументы: 
 * link_atts или link_atts_$depth            ->      Добавить любой атрибут к элементам <a>
 * a_class или a_class_$depth                ->      Добавить классы к элементам <a>
 * li_class или li_class_$depth              ->      Добавить классы к элементам <li>
 * submenu_class или submenu_class_$depth    ->      Добавить классы к элементам подменю <ul>
 *
 * Пример: добавить класс "text-black" ко всем ссылкам и класс "text-blue" только к ссылкам третьего уровня
 * wp_nav_menu([
 *     'theme_location' => 'primary_navigation',
 *     'a_class' => 'text-black',
 *     'a_class_2'
 *     ...
 * ])
 *
 * Пример: Более полный пример с некоторыми классами TailwindCSS и синтаксисом AlpineJS
 * 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
 */

/**
 * Добавить пользовательские атрибуты или классы к ссылкам в 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']);

    /**
     * Исправление для классов tailwindcss, которые включают ":" (двоеточие)
     * Введите тройное подчеркивание hover___text-primary вместо hover:text-primary
     *
     * Некоторые фильтры предоставлены, чтобы вы могли настроить свои собственные замены,
     * передавая их напрямую в preg_replace, поэтому поддерживает и массивные замены.
     *
     * WordPress trac по вопросу экранирования CSS классов:
     * @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 );

/**
 * Добавить пользовательские классы к li в 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 );

/**
 * Добавить пользовательские классы к ul.sub-menu в 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);

Ответ или решение

Пользовательский класс для wp_nav_menu в WordPress

Вам необходимо модифицировать стандартные параметры функции wp_nav_menu в WordPress, чтобы добавить пользовательские классы к тегам <ul> и <li>. Рассмотрим, как этого добиться с использованием фильтров и хуков в WordPress.

Настройка wp_nav_menu

Стандартная функция wp_nav_menu позволяет настроить меню на вашем сайте, но часто потребности по кастомизации бывают более сложные, чем предлагает стандартный набор параметров. В данном случае вам нужно добавить особые классы, что можно сделать с помощью фильтров.

Добавление пользовательских классов

Для достижения вашей цели, можно воспользоваться следующими шагами:

  1. Добавление классов к тегу <ul>:
    Используйте фильтр wp_nav_menu_args, чтобы добавить классы к элементу меню.

    add_filter('wp_nav_menu_args', function($args) {
       $args['menu_class'] = 'ваш_пользовательский_класс_ul';
       return $args;
    });
  2. Добавление классов к тегам <li>:
    Для добавления классов к элементам списка используйте фильтр nav_menu_css_class. Создайте функцию, которая добавляет желаемые классы к каждому элементу меню.

    add_filter('nav_menu_css_class', function($classes, $item, $args, $depth) {
       $classes[] = 'ваш_пользовательский_класс_li';
       return $classes;
    }, 10, 4);
  3. Использование глубины:
    Если вам нужно добавлять разные классы в зависимости от уровня вложенности, вы можете применять условные конструкции или дополнительные параметры:

    add_filter('nav_menu_css_class', function($classes, $item, $args, $depth) {
       if ($depth === 0) {
           $classes[] = 'первый_уровень_kласс';
       } elseif ($depth === 1) {
           $classes[] = 'второй_уровень_kласс';
       }
       return $classes;
    }, 10, 4);

Полный пример кода

Вот полный пример, который включает как добавление классов к <ul>, так и к <li>:

function custom_wp_nav_menu_args($args) {
    $args['menu_class'] = 'ваш_пользовательский_класс_ul'; // Класс для ul
    return $args;
}
add_filter('wp_nav_menu_args', 'custom_wp_nav_menu_args');

add_filter('nav_menu_css_class', function($classes, $item, $args, $depth) {
    $classes[] = 'ваш_пользовательский_класс_li'; // Класс для li
    return $classes;
}, 10, 4);

Заключение

Настройка пользовательских классов для элементов меню в WordPress позволяет вам значительно повысить гибкость и управляемость дизайна вашего сайта. Учитывая современные подходы в веб-разработке, такие как использование CSS-фреймворков и различных библиотек для стилизации, добавление пользовательских классов к меню является практическим решением для создания адаптивных и визуально привлекательных интерфейсов. Не забывайте тестировать ваши изменения на разных уровнях вложенности меню, чтобы убедиться в правильности настройки.

Если у вас есть дополнительные вопросы или сложности с реализацией, не стесняйтесь обращаться за помощью к сообществу WordPress или профессиональным разработчикам!

Оцените материал
Добавить комментарий

Капча загружается...