¿Cómo evito que una página web se desplace hacia la parte superior cuando se hace clic en un enlace que activa JavaScript?

135

Cuando tengo un enlace que está conectado con un evento jQuery o JavaScript como:

<a href="#">My Link</a>

¿Cómo evito que la página se desplace hacia arriba? Cuando elimino el atributo href del ancla, la página no se desplaza hacia la parte superior, pero el enlace no parece hacer clic.

Aquiles
fuente

Respuestas:

197

Debe evitar que ocurra la acción predeterminada para el evento de clic (es decir, navegar al destino del enlace).

Hay dos maneras de hacer esto.

Opción 1: event.preventDefault()

Llame al .preventDefault()método del objeto de evento pasado a su controlador. Si está utilizando jQuery para vincular sus controladores, ese evento será una instancia jQuery.Eventy será la versión de jQuery .preventDefault(). Si está utilizando addEventListenerpara enlazar sus controladores, será una Eventversión DOM y la versión RAW sin formato .preventDefault(). De cualquier manera hará lo que necesita.

Ejemplos:

$('#ma_link').click(function($e) {
    $e.preventDefault();
    doSomething();
});

document.getElementById('#ma_link').addEventListener('click', function (e) {
    e.preventDefault();
    doSomething();
})

Opcion 2: return false;

En jQuery :

Devolver falso desde un controlador de eventos llamará automáticamente a event.stopPropagation () y event.preventDefault ()

Entonces, con jQuery, puede usar este enfoque alternativamente para evitar el comportamiento predeterminado del enlace:

$('#ma_link').click(function(e) {
     doSomething();
     return false;
});

Si está utilizando eventos DOM sin procesar, esto también funcionará en los navegadores modernos, ya que la especificación HTML 5 dicta este comportamiento. Sin embargo, las versiones anteriores de la especificación no lo hicieron, por lo que si necesita la máxima compatibilidad con navegadores antiguos, debe llamar .preventDefault()explícitamente. Consulte event.preventDefault () vs. return false (no jQuery) para obtener detalles específicos.

Paolo Bergantino
fuente
9
Publicó una solución (3 años de retraso) que no requiere adjuntar un controlador de clics: stackoverflow.com/a/11246131/216941
Matt Crinklaw-Vogt
En este caso, Aquiles solo está haciendo esto porque quiere que el enlace aparezca como cliqueable, para lo cual no necesita usar href = "#" en absoluto. Vea mi respuesta para más información.
achecopar
164

Puede configurar su href en #!lugar de#

Por ejemplo,

<a href="#!">Link</a>

no hará ningún desplazamiento al hacer clic.

¡Tener cuidado! Esto aún agregará una entrada al historial del navegador cuando se haga clic, lo que significa que después de hacer clic en su enlace, el botón de retroceso del usuario no los llevará a la página en la que estaban anteriormente. Por esta razón, probablemente sea mejor usar el .preventDefault()enfoque, o usar ambos en combinación.

Aquí hay un Fiddle que ilustra esto (simplemente mueva el navegador hacia abajo hasta que obtenga una barra de desplazamiento):
http://jsfiddle.net/9dEG7/


Para los nerds específicos, por qué esto funciona:

Este comportamiento se especifica en la especificación HTML5 en la sección Navegar a un identificador de fragmento . La razón por la que un enlace con un href de "#"hace que el documento se desplace hacia arriba es que este comportamiento se especifica explícitamente como la forma de manejar un identificador de fragmento vacío:

2. Si fragides la cadena vacía, entonces la parte indicada del documento es la parte superior del documento

Usar un href de en su "#!"lugar funciona simplemente porque evita esta regla. No hay nada de mágico en el signo de exclamación: solo hace un identificador de fragmento conveniente porque es notablemente diferente a un típico frágil y es poco probable que coincida con el ido namede un elemento en su página. De hecho, podríamos poner casi cualquier cosa después del hash; los únicos frágiles que no serán suficientes son la cadena vacía, la palabra 'top' o cadenas que coinciden nameo idatributos de elementos en la página.

Más exactamente, solo necesitamos un identificador de fragmento que nos hará pasar al paso 8 en el siguiente algoritmo para determinar la parte indicada del documento a partir del fragmento:

  1. Aplique el algoritmo del analizador de URL a la URL y deje que fragid sea ​​el componente de fragmento de la URL analizada resultante.

  2. Si fragides la cadena vacía, entonces la parte indicada del documento es la parte superior del documento; Detenga el algoritmo aquí.

  3. Sea fragid bytesel resultado de la decodificación porcentual fragid.

  4. Sea decoded fragidel resultado de aplicar el algoritmo de decodificador UTF-8 a fragid bytes. Si el decodificador UTF-8 emite un error de decodificador, aborte el decodificador y, en su lugar, salte al paso etiquetado no decoded fragid.

  5. Si hay un elemento en el DOM que tiene una ID exactamente igual a decoded fragid, entonces el primer elemento en orden de árbol es la parte indicada del documento; Detenga el algoritmo aquí.

  6. Fragmento sin decodificar : si hay un elemento en el DOM que tiene un atributo de nombre cuyo valor es exactamente igual a fragid( nodecoded fragid ), entonces el primer elemento en orden de árbol es la parte indicada del documento; Detenga el algoritmo aquí.

  7. Si fragid es una coincidencia entre mayúsculas y minúsculas ASCII para la cadena top, entonces la parte indicada del documento es la parte superior del documento; Detenga el algoritmo aquí.

  8. De lo contrario, no hay parte indicada del documento.

Mientras lleguemos al paso 8 y no haya una parte indicada del documento , la siguiente regla entra en juego:

Si no hay una parte indicada ... entonces el agente de usuario no debe hacer nada.

Por eso el navegador no se desplaza.

Matt Crinklaw-Vogt
fuente
44
No importa si pones '!' o cualquier otro valor, siempre que la identificación no sea parte del DOM.
Gopinath
3
Después de ser un defensor de este método, he hecho un 180 y desaconsejo. Cuidado: los enlaces como este seguirán cambiando la URL de la página, lo que dará como resultado una entrada adicional en el historial del navegador y hará que el botón "atrás" simplemente elimine el fragmento de la URL en lugar de hacer lo que el usuario espera. Por lo tanto, esta solución por sí sola, mientras responde a la pregunta que se le hace, generalmente no es una alternativa deseable para usar preventDefault()en un controlador de clics, sino tristemente.
Mark Amery
1
¿Por qué no usar href = "javascript :;" ¿en lugar? Hasta donde sé, no cambiará el historial del navegador. Publicado al respecto en mi respuesta.
achecopar
30

Un enfoque fácil es aprovechar este código:

<a href="javascript:void(0);">Link Title</a>

Este enfoque no obliga a actualizar la página, por lo que la barra de desplazamiento permanece en su lugar. Además, le permite cambiar mediante programación el evento onclick y manejar el enlace de eventos del lado del cliente utilizando jQuery.

Por estas razones, la solución anterior es mejor que:

<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>

donde la última solución evitará el problema de desplazamiento de salto si y solo si el método myClickHandler no falla.

Phreeskier
fuente
12

Devolver falso del código que está llamando funcionará y en varias circunstancias es el método preferido, pero también puede hacerlo para que esto

<a href="javascript:;">Link Title</a>

Cuando se trata de SEO, realmente depende de para qué se va a utilizar su enlace. Si realmente lo va a usar para vincular a algún otro contenido, entonces estaría de acuerdo idealmente que desee algo significativo aquí, pero si está utilizando el enlace para fines de funcionalidad, tal como lo hace Stack Overflow para la barra de herramientas de publicación (negrita, cursiva, hipervínculo , etc.) entonces probablemente no importa.

Decano
fuente
9

Deberías cambiar el

<a href="#">My Link</a>

a

<a href="javascript:;">My Link</a>

De esta manera, cuando se hace clic en el enlace, la página no se desplazará hacia arriba. Esto es más limpio que usar href = "#" y luego evitar que se ejecute el evento predeterminado.

Tengo buenas razones para esto en la primera respuesta a esta pregunta , como return false;que no se ejecutará si la función llamada arroja un error, o puede agregar el return false;a una doSomething()función y luego olvidar usarreturn doSomething();

aquecopar
fuente
7

Prueba esto:

<a href="#" onclick="return false;">My Link</a>
mikeluby
fuente
4

Si simplemente puede cambiar el hrefvalor, debe usar:

<a href="javascript:void(0);">Link Title</a>

Otra buena solución que se me ocurrió es usar jQuery para detener la acción de hacer clic y hacer que la página se desplace, pero solo para los href="#"enlaces.

<script type="text/javascript">
    /* Stop page jumping when links are pressed */
    $('a[href="#"]').live("click", function(e) {
         return false; // prevent default click action from happening!
         e.preventDefault(); // same thing as above
    });
</script>
Dazbradbury
fuente
Seguramente return falsedebería estar después de la preventDefault()línea, de lo contrario nunca llegarás a esta segunda línea.
hobailey
3

Enlace a algo más sensible que la parte superior de la página en primer lugar. Luego cancele el evento predeterminado.

Ver la regla 2 de mejora progresiva pragmática .

Quentin
fuente
Esto también hace que su sitio sea más amigable con SEO.
Frankie
2

Además, puede usar event.preventDefault dentro del atributo onclick .

<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>

No es necesario escribir un evento de clic exstra.

efirat
fuente
0

Simplemente puede escribir así también: -

<a href="#!" onclick="function()">Delete User</a>
usuario2436792
fuente
0

Cuando llame a la función, sígala con un return false ejemplo:

<input  type="submit" value="Add" onclick="addNewPayment();return false;">
buddhi weerasinghe
fuente
0

Cree una página que contenga dos enlaces: uno en la parte superior y otro en la parte inferior. Al hacer clic en el enlace superior, la página tiene que desplazarse hacia abajo hasta la parte inferior de la página donde está presente el enlace inferior. Al hacer clic en el enlace inferior, la página debe desplazarse hacia la parte superior de la página.

Damini
fuente
0
<a onclick="yourfunction()">

Esto funcionará bien. no es necesario agregar href = "#"

Varaj Vignesh
fuente
0

Es posible que desee verificar su CSS. En el ejemplo aquí: https://css-tricks.com/the-checkbox-hack/ hay position: absolute; top: -9999px;. Esto es particularmente tonto en Chrome, ya queonclick="whatever" aún salta a la posición absoluta del elemento cliqueado.

Retirar position: absolute; top: -9999px;, para display: none;poder ayudar.

Scott Phillips
fuente
0

Para Bootstrap 3 para el colapso, si no especifica el objetivo de datos en el ancla y confía en href para determinar el objetivo, se evitará el evento. Si usa el objetivo de datos, deberá evitar el evento usted mismo.

<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>

<div id="demo" class="collapse"> 
<p>Lorem ipsum dolor sit amet</p>
</div>
Doug
fuente