Добавление класса span внутри тега якоря wp_nav_menu
Я нашел примеры добавления класса к элементам верхнего уровня для отображения стрелки в пунктах меню с подпунктами, но это плохо сочетается со встроенными классами WordPress, невозможно корректно отображать стрелку с текущим состоянием и CSS hover, это просто нарушает все состояния.
Текущее навигационное меню выглядит так <li><a>Текст</a></li>
Есть ли способ добавить <span class="arrow"></span>
внутрь родительского тега <a></a>
?
Пример,
Добавить ⇒ <span class="arrow"></span>
внутрь ⇒ <a/></a>
тегов
В итоге ⇒ <li><a>Текст<span class="arrow"></span></a></li>
для родительского элемента.
Текущий код добавляет теги <span></span>
снаружи тегов <a></a>
родительского элемента
class My_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_lvl(&$output, $depth, $args) {
$indent = str_repeat("\t", $depth);
if('primary' == $args->theme_location && $depth ==0){
$output .='<span class="arrow"></span>';
}
$output .= "\n$indent<ul class=\"sub-menu\">\n";
}
}
Оригинальное название вопроса отредактировано с: "добавить span class внутри <a>
"
Пробовали ли вы использовать параметры before
или link_before
в массиве аргументов при объявлении функции wp_nav_menu
?
Примечание: используйте after
или link_after
для обратного эффекта.
Пример:
wp_nav_menu(
//обычные аргументы здесь... и т.д.
'before' => '<span class="arrow"></span>',
//или 'link_before' => '<span class="arrow"></span>',
);
Из Codex:
$before
(string) (опционально) Текст перед тегом <a> ссылки
По умолчанию: None
например: 'before' => ''
или...
$link_before
(string) (опционально) Текст перед текстом ссылки
По умолчанию: None
например: 'link_before' => ''
Полезные ресурсы:

Это создает два экземпляра, где отображается span class внутри тега на основном и вторичном уровнях, чтобы вы могли добавить разные изображения для вашего span class в целях дизайна и навигации.
Это помогает пользователям и разработчикам показать, есть ли выпадающее меню в заголовке, а также упрощает навигацию по сайту.
1. Сначала добавьте этот код в файл functions.php.
class Nav_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .'>';
$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
if ( 'primary' == $args->theme_location ) {
$submenus = 0 == $depth || 1 == $depth ? get_posts( array( 'post_type' => 'nav_menu_item', 'numberposts' => 1, 'meta_query' => array( array( 'key' => '_menu_item_menu_item_parent', 'value' => $item->ID, 'fields' => 'ids' ) ) ) : false;
$item_output .= ! empty( $submenus ) ? ( 0 == $depth ? '<span class="arrow"></span>' : '<span class="sub-arrow"></span>' ) : '';
}
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
2. Добавьте код ниже в header.php, где установлен ваш wp_nav_menu.
Объяснение: этот код устанавливает новый пользовательский меню, в данном случае Nav_Walker_Nav_Menu.
<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'walker' => new Nav_Walker_Nav_Menu() ) ); ?>
3. Добавьте CSS
Это позволит отображать ваши новые изображения стрелок внутри тегов span на основном и вторичном уровнях.
#menu-header-menu li span.arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu li a:hover span.arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li span.sub-arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li a:hover span.sub-arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}
Надеюсь, это поможет! :)

Оба ответа, опубликованные пользователями userabuser и wordpress_designer, отличные, но я хочу предложить ответ, который является комбинацией этих двух.
С этим решением вы можете использовать логику для определения, где не следует применять link_before
, а также что именно вы хотите добавить перед текстом ссылки.
Сначала создайте очень простой класс, подобный приведенному ниже. Этот класс фактически отвечает только за проверку, когда элемент не является подменю ($depth <= 0
), а также за очистку и запоминание значения link_before
.
if ( ! class_exists('PREFIX_Menu_Walker')) {
class PREFIX_Menu_Walker extends Walker_Nav_Menu {
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$before = property_exists($args, 'link_before') ? $args->link_before : '';
// Очищаем `link_before` при обработке элементов корневого уровня
if ($depth <= 0 && !empty($before)) {
$args->link_before = '';
}
// Продолжаем работу с классом Walker_Nav_Menu по умолчанию в WordPress
parent::start_el( $output, $item, $depth, $args, $id );
// Восстанавливаем исходное значение `link_before` в $args
$args->link_before = $before;
}
}
}
Второе, что вам нужно сделать — это добавить аргументы walker
и link_before
в массив wp_nav_menu
, вот так:
wp_nav_menu([
'link_before' => '<span>Привет</span>',
'walker' => new PREFIX_Menu_Walker()
]);
