Как динамически изменить CSS класс меню в WordPress: практические методы и примеры

В WordPress часто требуется не просто вывести меню, а динамически изменять CSS классы элементов меню в зависимости от определённых условий. Это полезно, например, для выделения текущего пункта меню, добавления дополнительных стилей для определённых ролей пользователей или изменения поведения меню на основе контекста страницы.

Почему важно менять CSS класс меню динамически

По умолчанию WordPress добавляет стандартные классы, такие как current-menu-item или current_page_parent, чтобы помочь стилизовать активные пункты меню. Но в некоторых случаях этого недостаточно. Например, если нужно:

  • Отобразить специальные иконки или эффекты для определённых пунктов меню.
  • Изменить класс в зависимости от роли пользователя (гость, подписчик, админ).
  • Динамически подсвечивать пункты меню по сложным условиям, не поддерживаемым WP по умолчанию.

Для таких задач понадобится программно изменять или добавлять CSS классы элементов меню.

Использование фильтра wphide_nav_menu_css_class для изменения классов пунктов меню

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

function wphide_nav_menu_css_class($classes, $item, $args, $depth) {
    // Пример: выделяем пункт меню с определённым ID
    if ($item->ID == 42) {
        $classes[] = 'wphide-special-item';
    }

    // Пример: добавляем класс для пользователей с ролью 'subscriber'
    if (is_user_logged_in()) {
        $user = wp_get_current_user();
        if (in_array('subscriber', (array) $user->roles)) {
            $classes[] = 'wphide-subscriber-item';
        }
    }

    // Пример: меняем класс для главного пункта меню на главной странице
    if (is_front_page() && in_array('menu-item-home', $classes)) {
        $classes[] = 'wphide-home-highlight';
    }

    return $classes;
}
add_filter('nav_menu_css_class', 'wphide_nav_menu_css_class', 10, 4);

В этом примере мы добавляем разные классы по условиям: ID пункта, роль пользователя и текущая страница.

Как проверить ID пункта меню

Чтобы узнать ID пункта меню, зайдите в админку WordPress, откройте Внешний вид - Меню, наведите курсор на нужный пункт — внизу браузера появится ссылка с параметром menu-item=ID. Этот ID используйте в проверках.

Изменение CSS классов через Walker_Nav_Menu

Если нужно более гибко управлять выводом меню, можно создать свой класс-наследник от Walker_Nav_Menu и переопределить метод start_el. Это позволит полностью контролировать HTML каждого пункта меню.

class WPHide_Custom_Walker_Nav_Menu extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth=0, $args=array(), $id=0) {
        $classes = empty($item->classes) ? array() : (array) $item->classes;

        // Добавляем кастомный класс для пунктов с дочерними элементами
        if (in_array('menu-item-has-children', $classes)) {
            $classes[] = 'wphide-has-children';
        }

        // Добавляем класс для пункта меню с определённым названием
        if ($item->title == 'Контакты') {
            $classes[] = 'wphide-contact-link';
        }

        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args, $depth));
        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';

        $output .= "<li" . $class_names . ">";

        $attributes  = !empty($item->url) ? ' href="' . esc_attr($item->url) . '"' : '';

        $item_output = $args->before;
        $item_output .= "<a" . $attributes . ">" . $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after . "</a>";
        $item_output .= $args->after;

        $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
    }
}

Используйте этот класс при выводе меню:

wp_nav_menu(array(
    'theme_location' => 'primary',
    'walker' => new WPHide_Custom_Walker_Nav_Menu()
));

Пример: добавление бейджа "NEW" к свежим пунктам меню

Предположим, у вас есть меню, и вы хотите динамически добавить к некоторым пунктам меню бейдж "NEW" на основе даты их создания (например, мета-данных или пользовательского поля). Для простоты рассмотрим вариант, когда список «новых» ID пунктов хранится в массиве.

function wphide_add_new_badge_to_menu($item_output, $item, $depth, $args) {
    $new_items = array(12, 34, 56); // ID пунктов меню, которым нужен бейдж

    if (in_array($item->ID, $new_items)) {
        $badge = ' <span class="wphide-menu-badge">NEW</span>';
        $item_output = str_replace($item->title, $item->title . $badge, $item_output);
    }

    return $item_output;
}
add_filter('walker_nav_menu_start_el', 'wphide_add_new_badge_to_menu', 10, 4);

Добавьте CSS для бейджа в файл стилей вашей темы или плагина:

.wphide-menu-badge {
    background-color: #ff0000;
    color: #fff;
    font-size: 10px;
    padding: 2px 5px;
    margin-left: 5px;
    border-radius: 3px;
    text-transform: uppercase;
}

Советы по использованию плагинов для управления меню

Для динамического управления классами меню можно рассмотреть плагины, которые позволяют добавлять пользовательские поля к пунктам меню (например, WP Menu Custom Fields). С их помощью можно задавать дополнительные атрибуты и классы в админке без кода.

Также плагин Clearfy Pro содержит инструменты оптимизации и управления для WordPress, которые могут косвенно помочь с кастомизацией меню и улучшением производительности.

Подводим итог — лучшие практики

1. Используйте фильтр nav_menu_css_class для простого и быстрого добавления или изменения классов.

2. Для сложных изменений создавайте собственный Walker_Nav_Menu, чтобы полностью контролировать структуру HTML.

3. Для удобства и расширяемости применяйте плагины, добавляющие пользовательские поля к меню.

4. Всегда тестируйте изменения на разных страницах и с разными ролями пользователей, чтобы не сломать навигацию.

⭐⭐⭐⭐⭐