Как сделать, чтобы активный пункт меню wordpress не содержал ссылку на себя

По правилам юзабилити, ничего не должно содержать ссылку на себя. Если пользователь переходит на страницу, например, «Контакты», пункт меню «Контакты» должен потерять интерактивность, это правильное и хорошее поведение. Как это сделать в wordpress? При помощи правки functions.php

Для начала, поместите в functions.php следующий код:

/**
 * Extension for wp_nav_menu()
 * Remove element "a" from current menu item
 *
 * Optional $args contents additional arguments
 * string replace_a_by - Whether to wrap the link text node, and what to wrap it with. Default 'span'.
 * string xpath        - xPath expression.
 *
 * @param $args
 * @see wp_nav_menu()
 * @return mixed Menu output if $echo is false, false if there are no items or no menu was found.
 */
function wp_nav_menu_extended($args = array()) {
    $_echo = array_key_exists('echo', $args) ? $args['echo'] : true;
    $args['echo'] = false;

    $menu = wp_nav_menu($args);

    // Load menu as xml
    $menu = simplexml_load_string($menu);

    // Find current menu item with xpath selector
    if (array_key_exists('xpath', $args)) {
        $xpath = $args['xpath'];
    } else {
        $xpath = '//li[contains(@class, "current-menu-item") or contains(@class, "current_page_item")]';
    }

    $current = $menu->xpath($xpath);

    // If current item exists
    if (!empty($current)) {
        $text_node = (string) $current[0]->children();

        // Remove link
        unset($current[0]->a);

        // Create required element with text from link
        $element_name = $args['replace_a_by'] ? $args['replace_a_by'] : 'span';

        $dom = dom_import_simplexml($current[0]);
        $n = $dom->insertBefore(
            $dom->ownerDocument->createElement($element_name, $text_node),
            $dom->firstChild
        );

        $current[0] = simplexml_import_dom($n);
    }

    $xml_doc = new DOMDocument('1.0', 'utf-8');
    $menu_x = $xml_doc->importNode(dom_import_simplexml($menu), true);
    $xml_doc->appendChild($menu_x);

    $menu = $xml_doc->saveXML($xml_doc->documentElement);

    if ($_echo) {
        echo $menu;
    } else {
        return $menu;
    }
}

А затем разместите в header.php вот такой вызов:

<?php wp_nav_menu_extended( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu') ); ?>

Остаётся понять, как проделать эту же операцию с заголовком блога. Лечится заменой вызова заголовка в header.php вот таким образом:

<h1 class="vcard author">
<?php if ( is_front_page() && !is_paged())
echo bloginfo('name');
else echo "";
?>
</h1>

<h1 class="vcard author">
<a href="<?php echo get_option('home'); ?>/" title="На главную страницу">

<?php if ( is_front_page() && !is_paged())
echo "";
 else 
 echo bloginfo('name');
?>

</a>
</h1>

UPD: 15 апреля 2024 года. Способ устарел и на блочных темах уже не работает. Теперь надо править CSS. Вносим в дополнительный CSS следующую конструкцию:

.wp-block-navigation .current-menu-item [aria-current="page"] {
	pointer-events: none; 
	cursor: default;
}

Посмотрите только, каким классом оформлено ваше меню и поместите его в первой строке вместо .wp-block-navigation и всё сработает.

Вы, конечно, спросите, а как быть с заголовком блога? Как сделать, чтобы когда пользователь находится на главной странице, заголовок не был интерактивным, а когда на дочерних — был? Вот так:

.wp-block-site-title [aria-current="page"] {
	pointer-events: none; 
	cursor: default;
}

Опубликовано

в

,

от

Метки:

Если хотите получать новые посты на имейл, подпишитесь на рассылку. Пишу нечасто и по делу. 

Предыдущий пост
Подробный список всего, что мне нравится и не нравится.