0

I don't want to have the parent menu items of my site's nav menus linking to a separate page. For one thing I don't want to have a superfluous page. For another these links hobble site navigation for mobile users who can't "hover" over a link (to bring up the child items).

The best solution would be to disable the parent menu item links. But how do I do that, especially now that with WordPress 3.5 the Disable Parent Menu Item plugin has stopped working?

One possible solution is here.

5 Answers 5

1

Do not create fake URLs (#). This would be very bad for users with a screen reader: the are using a list of available links to browse your site. The same is true for javascript: links, they are not exactly elegant markup anyway.

You need two steps:

  1. Mark the items with children before the walker starts.
  2. Replace the markup for the top parents.

I will use an empty <a> element here to make it easy to get the cursor. You will probably need something like this in your stylesheet:

.menu > .has-children {
    cursor: pointer;
}

The filter to mark parent items is taken from this answer. The second function just checks for that property and it tests if the item is itself not a child item.

add_filter( 'wp_nav_menu_objects',      't5_add_has_children_to_nav_items' );
add_filter( 'walker_nav_menu_start_el', 't5_unlink_parent_item', 10, 4 );

/**
 * Add aproperty 'has_children' to menu items
 *
 * @wp-hook wp_nav_menu_objects
 * @param   array $items
 * @return  array
 */
function t5_add_has_children_to_nav_items( $items )
{
    $parents = wp_list_pluck( $items, 'menu_item_parent' );
    $out     = array ();

    foreach ( $items as $item )
    {
        in_array( $item->ID, $parents ) && $item->has_children = TRUE;
        $out[] = $item;
    }
    return $items;
}
/**
 * Replace top parent element markup.
 *
 * @wp-hook walker_nav_menu_start_el
 * @param   string $item_output
 * @param   object $item
 * @param   int    $depth
 * @param   object $args
 * @return  string
 */
function t5_unlink_parent_item( $item_output, $item, $depth, $args )
{
    // not first level parent item
    if ( empty ( $item->has_children ) or 0 != $item->menu_item_parent )
        return $item_output;

    $title = apply_filters(
        'the_title',
        $item->title,
        $item->ID
    );
    $id = apply_filters(
        'nav_menu_item_id',
        'menu-item-'. $item->ID,
        $item, $args
    );
    $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $classes[] = 'menu-item-' . $item->ID;
    $classes[] = 'has-children';
    $class_names = join(
        ' ',
        apply_filters(
            'nav_menu_css_class',
            array_filter( $classes ),
            $item,
            $args
        )
    );
    $class_names = $class_names
        ? ' class="' . esc_attr( $class_names ) . '"'
        : '';

    return "<li$id>$args->before<a class='menu-item has-children'>$title</a>$args->after";
}
6
  • This is a better answer than mine but it indicates a fundamental flaw in WordPress menus that this much code is needed to achieve what should be a simple thing :)
    – JCL1178
    Commented Jan 18, 2013 at 6:23
  • @JCL1178 I guess not many authors use a href-less top level. And most custom themes use a custom walker anyway. I see the native implementation as a starting guide that works in most cases but isn’t forced onto the developer.
    – fuxia
    Commented Jan 18, 2013 at 6:27
  • Thanks for your lengthy reply, toscho. You put a lot of work into it I can see. Actually, the answer in the link I posted says to remove the hash symbol, so there's no hash symbol in the link that appears in the menu: it becomes a link without an href, i.e., no URL, fake or otherwise. Since your solution seems to depend on evacuating the href as well, I wonder how it is better for screen-readers. Is your walker worthwhile?
    – JohnK
    Commented Mar 24, 2013 at 1:44
  • @JohnK The plugin from that thread is probably the worst possible attempt to solve that issue. You will get conflicts with other plugins with that, because it calls wp_print_scripts a second time. This should never have passed the plugin review … Anyway, use the PHP solution here; it is free of side effects, except when you use a plugin that comes with its own custom walker.
    – fuxia
    Commented Mar 24, 2013 at 1:57
  • The link wasn't to the plug-in, toscho, but to a simple, 'by-hand' way to replace it in making a non-clickable menu item. Seems to produce the same effect as your code. I'd like to give you credit for your work, but I can only choose yours as the correct answer if you somehow justify its superiority over the simple way.
    – JohnK
    Commented Mar 24, 2013 at 2:25
0

I would simply create custom menu items with a javascript:void(0) as the href whenever a parent item is needed.

3
  • Good answer, and a much better solution than using hash symbol as the link as indicated in the posters link.
    – gteh
    Commented Jan 18, 2013 at 5:38
  • Actually if you read carefully, that solution says to remove the hash symbol, so there's no hash symbol in the link.
    – JohnK
    Commented Mar 24, 2013 at 1:31
  • But how? can you give a example?
    – 244boy
    Commented Nov 26, 2019 at 10:05
0

Works with WordPress 3.5:

  1. Add a Link entry with the name you want and a # URL
  2. Edit the menu entry you just created and remove the #

You have to do both steps, as you can't add a menu entry with an empty URL.

1
  • Can you explain more?
    – 244boy
    Commented Nov 26, 2019 at 9:50
0

A little late but for future use. You can create a custom link for the parent. When you add it you have to add a #, but once it's added you can remove it which disables the link.

-1

To eliminate the active "hover" cursor:

Theme Options > Drop down menu > Make parent menu items clickable : disable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.