¿Cómo hacer que un elemento del menú principal no tenga enlace, pero tenga submenús enlazados?
Estoy construyendo un menú horizontal y algunas de las entradas en ese menú tendrán desplegables (submenús) y otras no. Las que tienen submenús no son realmente páginas. Solo están destinadas a servir como guías para los desplegables.
Por ejemplo, digamos que el menú horizontal es el siguiente:
Inicio | Sobre Nosotros | Productos | Direcciones | Contacto
Y el elemento "productos" está destinado a tener 3 páginas enlazadas en una lista desplegable vertical debajo de él, por lo que "productos" en sí no representa una página, ¿cómo puedo hacer esto en WP?
(Uso WP como CMS, con páginas estáticas de inicio e interiores. Construyo mis propias plantillas, estilizo los menús en CSS, luego registro los menús en el functions.php y los llamo en las plantillas.) En WP agregas entradas a los menús a través de la lista de páginas o mediante enlaces personalizados. Pero no quiero que "productos" esté enlazado. Si no agrego un enlace al enlace personalizado, no me permitirá agregarlo al menú.
¿Se puede hacer esto a través del administrador de menús o tengo que abordarlo de otra manera?
¡Gracias por cualquier ayuda!

La forma más fácil de hacerlo sin ningún plugin es utilizar la función "Menús" de WordPress. Aquí están las instrucciones para WordPress 4.8:
- Desde tu panel de control de WordPress, ve a "Apariencia → Menús"
- En la pestaña "Editar Menús", selecciona "Enlaces personalizados"
- Para la URL, ingresa "#" (sin comillas)
- Para el texto del enlace, ingresa el texto deseado para el nivel superior de tu menú desplegable
- Haz clic en el botón "Añadir al menú"
- Arrastra el elemento del menú a la posición deseada dentro de tu menú
- Para el elemento de menú que acabas de añadir, haz clic en la flecha hacia abajo a la derecha del elemento (dice "enlace personalizado" a la izquierda del elemento)
- Elimina el "#" de la URL. Esto - en todos los navegadores - convertirá el enlace en texto plano.
- Haz clic en el botón "Guardar menú"

Gracias por el consejo. Es fácil, aunque no perfecto, ya que las etiquetas aún parecen "enlaces" al pasar el ratón, pero no llevan a ningún sitio. Así que puede funcionar en caso de necesidad.

¿Leíste el comentario completo? Después de añadir el enlace, haz clic en la flecha desplegable junto al nombre del enlace y elimina el "#" del cuadro de texto de la URL. Esto, en todos los navegadores, hará que el enlace no sea clickeable.

Sí, gracias, leí todo el comentario. Volví a intentarlo y me di cuenta de mi problema. Cuando dejo el #, la palabra aparece en la barra de navegación pero como un "enlace muerto". Cuando eliminé el #, la palabra no aparecía en la barra de navegación a menos que pasara el ratón sobre ella y aparecía en estado hover. Así que supongo que eso significa que tengo que aplicar CSS a la palabra para que aparezca sin estar enlazada. No estoy seguro de por qué aparece el estado hover...

Esto sigue en la versión 4.9.5, sin embargo no estoy seguro ya que 'parece' un hack aprovechándose de un bug. Si no lo es... va a ahorrarle muchos dolores de cabeza a la gente... Esto es algo parecido al hecho de que WordPress considera "1 2 3 4 5 6" como una contraseña segura... todavía.

A título informativo, si realizas el Paso 8 (por la razón que sea), entonces tu cursor no será una mano cuando pases sobre el enlace personalizado. En ese caso, podrías darle estilo con pointer:cursor.

Tengo algunas ideas:
- Establecer el enlace personalizado a
#
que no devolverá nada - Añadir una clase personalizada a los elementos y luego usar jQuery para eliminar los enlaces.
- Usar un equivalente en PHP al método de jQuery
- Usar el plugin Desactivar Enlace del Menú Padre (o desmontarlo y escribir uno propio)

¡Gracias por los consejos y enlaces! Como sugirió Gavin, usar un # para un enlace personalizado "funciona"; las otras opciones pueden funcionar mejor, aunque no son tan fáciles. Bueno, el plugin probablemente sea fácil, pero odio usar plugins si puedo lograr lo mismo de manera más directa. Tendré que decidir el mejor enfoque. ¡Gracias de nuevo!

Si planeas usarlo en dispositivos táctiles, ten cuidado con usar href=""
vacío porque la mayoría de los usuarios de dispositivos táctiles no podrán ver el menú desplegable sin usar JS

Los enlaces se rompen. Podrías considerar incorporar algunas de estas ideas en tu respuesta

El método más sencillo que se me ocurrió fue crear un elemento de Enlace personalizado con el valor de URL del enlace como #
. Esto envía al usuario a un hash vacío en la misma página, por lo que básicamente no enlaza a ningún lugar.
Sin embargo, hay algunos efectos secundarios de usar hashes vacíos para enlaces de marcador de posición. El enlace seguirá apareciendo y comportándose como un enlace, lo que podría confundir a un usuario cuando hace clic en lo que parece un enlace pero no sucede nada. El otro efecto es que hacer clic en un enlace de hash vacío anulará cualquier hash existente, enviando al usuario a la parte superior de la página. Esto podría no ser tan preocupante para un menú que ya está en la parte superior de la página, pero es bastante molesto cuando la página salta inesperadamente cuando no lo esperas, especialmente si se trata de un menú en el pie de página.
La solución es combinar el método de hash vacío con un fragmento de código para detectar cuándo se usan enlaces de hash vacíos en el menú y eliminar el atributo href
de ese enlace por completo. Un elemento a
sin un atributo href
es el método correcto en HTML 5 para crear un enlace de marcador de posición.
/**
* Eliminar el href de enlaces vacíos `<a href="#">` en los menús de navegación
* @param string $menu el HTML actual del menú
* @return string el HTML del menú modificado
*/
add_filter( 'wp_nav_menu_items', function ( $menu ) {
return str_replace( '<a href="#"', '<a', $menu );
} );

Esto funcionó para mí:
Activé Clases CSS en Menús > Opciones de pantalla > Clases CSS Luego le asigné al elemento del menú que quería desactivar la clase ".nolink" y agregué este fragmento de código a mi panel de CSS personalizado:
.nolink {
pointer-events: none;
cursor: default;
}

Usar #
como objetivo del enlace y luego aplicar una clase CSS personalizada para fines de estilo es, en mi opinión, la solución menos complicada. Sin embargo, establecer pointer-events: none
no tiene mucho sentido para mí, ya que romperá los submenús. ¿Podrías explicar por qué estableciste ese atributo?

Aprecio que este es un hilo antiguo, pero una forma rápida y sencilla de tener un enlace en Wordpress es haciendo que la URL del enlace sea:
#_
Observa el guión bajo después del hashtag. De esta manera, si tu menú se desplaza hacia abajo en la página (es decir, está fijo), no obtendrás un salto hacia la parte superior de la página al hacer clic en él y no requiere ningún plugin o script adicional.

Utilizando el enfoque PHP agregué este código a functions.php:
function remove_link_contact_menu($item_output, $item) {
if ($item->post_name == 'contact')
return '<span>' . $item->title . '</span>';
return $item_output;
}
add_filter('walker_nav_menu_start_el', 'remove_link_contact_menu', 20, 2);
add_filter('megamenu_walker_nav_menu_start_el', 'remove_link_contact_menu', 20, 2);
Esto reemplazará el enlace con un elemento span para el ítem del menú cuyo post_name == "contact", que es exactamente lo que estaba buscando. Puedes fácilmente modificar esto para verificar por el título del menú o el ID, o agregar código para verificar si tiene elementos hijos en el menú, etc.

- Establece el enlace personalizado a # que no devolverá nada. Elemento de lista
Añade este filtro:
add_filter( 'wp_nav_menu_items', 'wpse_remove_empty_links' ); function wpse_remove_empty_links( $menu ) { return preg_replace("/<a href=\"#\">(.+?)<\/a>/is", "<span>$1</span>", $menu); }
Edita el CSS del span para que tenga el mismo estilo que
<a>
, no olvidescursor: context-menu;
.

Esto eliminará el clic (y le quitará los estilos al elemento). De esta manera, no tendrás que usar enlaces personalizados con # en tu menú.
add_action( 'wp_footer', function(){
?>
<script>
(function( $ ) {
var itemm = $('#main-menu .menu-item-has-children > a');
itemm.click(function(){
document.activeElement && document.activeElement.blur();
return false;
});
})(jQuery);
</script>
<?php
}, 1, 0 );

Como otros han sugerido aquí, puedes crear un elemento de menú personalizado con # como su URL. Luego borra el # una vez que se haya agregado al menú. Y finalmente, puedes usar esta expresión regular simple para eliminar la etiqueta <a> de esos enlaces.
preg_replace('/<a>([^<]+)<\/a>/i', '<span class="no-link">$1</span>', $navHTML);

Me doy cuenta de que llego tarde al juego, pero estos son los dos métodos que utilizo:
1) Hacer que el elemento principal del menú sea un duplicado del primer subelemento y cambiar su etiqueta. Por ejemplo, si el primer elemento bajo "Productos" es "Producto 1", usa "Producto 1" como elemento principal del menú, luego cambia su etiqueta a "Productos". De esta manera, tanto "Productos" como "Producto 1" llevarán a la página Producto 1.
2) Agregar una redirección para que la página de Productos sea redirigida a Producto 1. El beneficio de esta opción es que te permite crear una página de Productos en blanco para crear un listado jerárquico en Páginas, pero si alguien intenta ir a la página en blanco de Productos, será redirigido.

Lo resolví de esta manera: en header.php (de tu tema) busqué:
'link_before' => '',
'link_after' => '',
y lo reemplacé con:
'link_before' => '<script>var scriptTag=document.getElementsByTagName("script");scriptTag=scriptTag[scriptTag.length-1];if(scriptTag.parentNode.href)if(scriptTag.parentNode.href.slice(-1)=="#")document.write("<span onclick=\"return false\">")</script>',
'link_after' => '<script>var scriptTag=document.getElementsByTagName("script");scriptTag=scriptTag[scriptTag.length-1];if(scriptTag.parentNode.href)if(scriptTag.parentNode.href.slice(-1)=="#")document.write("</span>")</script>',
En palabras simples, este script verifica si el enlace padre termina con "#", en ese caso agrega un elemento span alrededor del contenido de la etiqueta A, lo cual deshabilita el clic.
¡Espero que te ayude! :-)

Hola, sé que esta es una respuesta antigua pero para futuras referencias, no recomendaría simplemente modificar el archivo de cabecera de tu tema porque cuando se actualice todo tu código será sobrescrito. La mejor solución para esto es crear un tema hijo con tu código personalizado.

Escrito desde 1/2019, la solución que produce HTML5 correcto es hacer lo siguiente.
- Añade un Enlace Personalizado con la URL establecida como #, y el nombre que prefieras. Ambos campos son obligatorios.
- Edita el Enlace Personalizado recién añadido para que la URL quede vacía.
- Guarda los cambios.
Esto producirá un menú de nivel superior que es <a>Menú</a>
, que es la forma correcta de representar un enlace no clickeable.

Crea un menú de enlace personalizado como se mencionó anteriormente. Revisa el código fuente y busca el href del submenú, por ejemplo: #mm-1. Pega esto en la URL del enlace personalizado y guarda el menú. Esto hará que la versión móvil también funcione cuando pulses en el texto del menú.

Mi versión se ve así:
Primero, en el menú del panel de administración, en el enlace deseado, en el campo href
pon #
o déjalo vacío, y luego en function.php
del tema se añade:
function replace_empty_menu_links( $item_output, $item, $depth, $args ) {
if ( $item->url == '#' || $item->url == '' ) {
$item_output = sprintf( '%1$s<' . 'div' . '%2$s>%3$s%4$s%5$s</' . 'div' . '>%6$s',
$args->before,
$attributes,
$args->link_before,
apply_filters( 'the_title', $item->title, $item->ID ),
$args->link_after,
$args->after
);
}
return $item_output;
}
add_filter( 'walker_nav_menu_start_el', 'replace_empty_menu_links', 10, 4 );
Puedes reemplazar 'div'
con cualquier elemento que te convenga.
Esto funciona para la versión 5.3.2 (probado en esta versión, pero debería funcionar en otras también).
De esta forma, se conserva el funcionamiento de todos los argumentos 'before'
, 'after'
, 'link_before'
, 'link_after'
, etc. de wp_nav_menu()
.
Además, esto también funciona para submenús.

Una solución mucho más sencilla se puede encontrar en otra pregunta:
Busca la respuesta de Askelon. Funciona perfectamente, sin necesidad de usar preg_replaces o jquery.

Puedes desactivar los eventos en la etiqueta <a>
para todos los elementos del menú de primer nivel usando CSS puro. La clase .main-menu
puede tener otro nombre según cómo hayas nombrado tu menú.
/* desactivar elementos del menú padre */
ul.main-menu > li > a {
pointer-events: none;
}
