Come posso impedire a una pagina Web di scorrere verso l'alto quando si fa clic su un collegamento che attiva JavaScript?


135

Quando ho un collegamento cablato con un evento jQuery o JavaScript come:

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

Come posso impedire alla pagina di scorrere verso l'alto? Quando rimuovo l'attributo href dall'ancora la pagina non scorre verso l'alto ma il collegamento non sembra essere in grado di fare clic.

Risposte:


197

È necessario impedire che si verifichi l'azione predefinita per l'evento click (ovvero la navigazione verso la destinazione del collegamento).

Ci sono due modi per farlo.

Opzione 1: event.preventDefault()

Chiamare il .preventDefault()metodo dell'oggetto evento passato al gestore. Se stai usando jQuery per associare i tuoi gestori, quell'evento sarà un'istanza di jQuery.Evente sarà la versione di jQuery di .preventDefault(). Se si utilizza addEventListenerper associare i gestori, sarà una Eventversione DOM non elaborata di .preventDefault(). Ad ogni modo farà ciò di cui hai bisogno.

Esempi:

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

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

Opzione 2: return false;

In jQuery :

La restituzione di false da un gestore eventi chiamerà automaticamente event.stopPropagation () e event.preventDefault ()

Quindi, con jQuery, puoi in alternativa utilizzare questo approccio per prevenire il comportamento del collegamento predefinito:

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

Se stai utilizzando eventi DOM non elaborati, questo funzionerà anche sui browser moderni, poiché le specifiche HTML 5 determinano questo comportamento. Tuttavia, le versioni precedenti delle specifiche no, quindi se hai bisogno della massima compatibilità con i browser più vecchi, dovresti chiamare .preventDefault()esplicitamente. Vedere event.preventDefault () vs. return false (no jQuery) per i dettagli della specifica.


9
Pubblicato una soluzione (3 anni di ritardo) che non richiede il collegamento di un gestore di clic: stackoverflow.com/a/11246131/216941
Matt Crinklaw-Vogt

In questo caso, Achille lo sta facendo solo perché vuole che il link appaia cliccabile, per il quale non ha bisogno di usare affatto href = "#". Vedi la mia risposta per maggiori informazioni.
Achecopar,

164

Puoi impostare il tuo href #!invece di#

Per esempio,

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

non farà alcuno scorrimento quando si fa clic.

Attenzione! Ciò aggiungerà comunque una voce alla cronologia del browser quando si fa clic, il che significa che dopo aver fatto clic sul collegamento, il pulsante Indietro dell'utente non li porterà alla pagina in cui si trovavano in precedenza. Per questo motivo, probabilmente è meglio usare l' .preventDefault()approccio o usarli entrambi in combinazione.

Ecco un Fiddle che illustra questo (basta scorrere il browser verso il basso fino a ottenere una barra di scorrimento):
http://jsfiddle.net/9dEG7/


Per i nerd spec - perché funziona:

Questo comportamento è specificato nelle specifiche HTML5 nella sezione Navigazione verso un identificatore di frammento . Il motivo per cui un collegamento con un href di "#"fa scorrere il documento verso l'alto è che questo comportamento è esplicitamente specificato come il modo di gestire un identificatore di frammento vuoto:

2. Se fragidè la stringa vuota, la parte indicata del documento è la parte superiore del documento

L'uso di un href "#!"invece funziona semplicemente perché evita questa regola. Non c'è nulla di magico nel punto esclamativo: crea semplicemente un comodo identificatore di frammento perché è notevolmente diverso da un tipico frammento e è improbabile che corrisponda mai all'elemento ido namedi un elemento nella tua pagina. In effetti, potremmo mettere praticamente qualsiasi cosa dopo l'hash; gli unici frammenti che non saranno sufficienti sono la stringa vuota, la parola "in alto" o le stringhe che corrispondono nameo gli idattributi degli elementi nella pagina.

Più precisamente, abbiamo solo bisogno di un identificatore di frammento che ci farà passare al punto 8 del seguente algoritmo per determinare la parte indicata del documento dal fragido:

  1. Applicare l'algoritmo del parser URL all'URL e lasciare che fragid sia il componente frammento dell'URL analizzato risultante.

  2. Se fragidè la stringa vuota, la parte indicata del documento è la parte superiore del documento; ferma l'algoritmo qui.

  3. Lascia che fragid bytessia il risultato della decodifica percentuale fragid.

  4. Lascia che decoded fragidsia il risultato dell'applicazione dell'algoritmo del decodificatore UTF-8 a fragid bytes. Se il decodificatore UTF-8 emette un errore del decodificatore, interrompere il decodificatore e saltare invece al passaggio etichettato no decoded fragid.

  5. Se nel DOM è presente un elemento con un ID esattamente uguale a decoded fragid, quindi il primo di tali elementi nell'ordine dell'albero è la parte indicata del documento; ferma l'algoritmo qui.

  6. Nessun frammento decodificato : se nel DOM è presente un elemento con un attributo name il cui valore è esattamente uguale a fragid( nondecoded fragid ), il primo di tali elementi nell'ordine dell'albero è la parte indicata del documento; ferma l'algoritmo qui.

  7. Se fragid è una corrispondenza ASCII senza distinzione tra maiuscole e minuscole per la stringa top, la parte indicata del documento è la parte superiore del documento; ferma l'algoritmo qui.

  8. Altrimenti, non esiste una parte indicata del documento.

Fintanto che si preme il passaggio 8 e non viene indicata alcuna parte del documento , entra in gioco la seguente regola:

Se non è presente alcuna parte indicata ... l'agente utente non deve fare nulla.

ecco perché il browser non scorre.


4
Non importa se metti "!" o qualsiasi altro valore, purché l'id non faccia parte del DOM.
Gopinath,

3
Dopo essere stato una volta sostenitore di questo metodo, da allora ho fatto un 180 e sconsiglio. Attenzione: collegamenti come questo cambieranno comunque l'URL della pagina, risultando in una voce aggiuntiva nella cronologia del browser e facendo sì che il pulsante "indietro" rimuova semplicemente il frammento dall'URL invece di fare ciò che l'utente si aspetta. Quindi questa soluzione da sola, pur rispondendo alla domanda come posta, in genere non è un'alternativa desiderabile all'utilizzo preventDefault()in un gestore di clic - piuttosto tristemente.
Mark Amery,

1
Perché non usare href = "javascript :;" anziché? Per quanto ne so, non cambierà la cronologia del browser. Inserito al riguardo sulla mia risposta.
Achecopar,

30

Un approccio semplice è quello di sfruttare questo codice:

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

Questo approccio non impone un aggiornamento della pagina, quindi la barra di scorrimento rimane in posizione. Inoltre, consente di modificare a livello di codice l'evento onclick e gestire l'associazione di eventi lato client utilizzando jQuery.

Per questi motivi, la soluzione sopra è migliore di:

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

dove l'ultima soluzione eviterà il problema di scorrimento se e solo se il metodo myClickHandler non fallisce.


12

Restituire false dal codice che stai chiamando funzionerà e in diverse circostanze è il metodo preferito, ma puoi farlo anche tu

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

Quando si tratta di SEO, dipende davvero da cosa verrà utilizzato il tuo link. Se lo utilizzerai effettivamente per collegarti ad altri contenuti, sarei d'accordo idealmente che qui vorresti qualcosa di significativo, ma se stai usando il link per scopi di funzionalità, forse come Stack Overflow fa per la barra degli strumenti dei post (grassetto, corsivo, hyperlink , ecc.) quindi probabilmente non importa.


9

Dovresti cambiare il

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

per

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

In questo modo quando si fa clic sul collegamento, la pagina non scorrerà verso l'alto. Questo è più pulito dell'uso di href = "#" e quindi impedisce l'esecuzione dell'evento predefinito.

Ho buone ragioni per questo sulla prima risposta a questa domanda , come la return false;non si eseguirà se la funzione chiamata genera un errore, oppure potresti aggiungere la return false;a una doSomething()funzione e poi dimenticare di usarereturn doSomething();


7

Prova questo:

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

4

Se puoi semplicemente cambiare il hrefvalore, dovresti usare:

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

Un'altra soluzione chiara che ho appena trovato è quella di utilizzare jQuery per impedire che si verifichi l'azione di clic e causi lo scorrimento della pagina, ma solo per i href="#"collegamenti.

<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>

Sicuramente return falsedovrebbe essere dopo la preventDefault()linea, altrimenti non arriverai mai a questa seconda linea?
Hobailey,


2

Inoltre, è possibile utilizzare event.preventDefault all'interno dell'attributo onclick .

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

Non è necessario scrivere l'evento click exstra.


0

Puoi anche semplicemente scrivere così: -

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

0

Quando si chiama la funzione, seguirla con l' return false esempio:

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

0

Crea una pagina che contiene due collegamenti: uno in alto e uno in basso. Facendo clic sul collegamento superiore, la pagina deve scorrere fino alla fine della pagina in cui è presente il collegamento inferiore. Facendo clic sul collegamento in basso, la pagina deve scorrere fino all'inizio della pagina.


0
<a onclick="yourfunction()">

questo funzionerà benissimo. non è necessario aggiungere href = "#"


0

Potresti voler controllare il tuo CSS. Nell'esempio qui: https://css-tricks.com/the-checkbox-hack/ c'è position: absolute; top: -9999px;. Questo è particolarmente sciocco su Chrome, poiché onclick="whatever"salta ancora nella posizione assoluta dell'elemento cliccato.

Rimozione position: absolute; top: -9999px;, perché display: none;potrebbe aiutare.


0

Per Bootstrap 3 per il collasso, se non si specifica target dati sull'ancora e si fa affidamento su href per determinare il target, l'evento verrà impedito. Se usi il target dei dati dovrai prevenire tu stesso l'evento.

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.