Wie kann ich verhindern, dass eine Webseite nach oben gescrollt wird, wenn auf einen Link geklickt wird, der JavaScript auslöst?

135

Wenn ich einen Link habe, der mit einem jQuery- oder JavaScript-Ereignis verbunden ist, wie z.

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

Wie verhindere ich, dass die Seite nach oben rollt? Wenn ich das href-Attribut aus dem Anker entferne, wird die Seite nicht nach oben gescrollt, aber der Link scheint nicht anklickbar zu sein.

Achilles
quelle

Antworten:

197

Sie müssen verhindern, dass die Standardaktion für das Klickereignis (dh das Navigieren zum Linkziel) auftritt.

Es gibt zwei Möglichkeiten, dies zu tun.

Option 1: event.preventDefault()

Rufen Sie die .preventDefault()Methode des Ereignisobjekts auf, das an Ihren Handler übergeben wurde. Wenn Sie jQuery zum Binden Ihrer Handler verwenden, ist dieses Ereignis eine Instanz von jQuery.Eventund die jQuery-Version von .preventDefault(). Wenn Sie addEventListenerIhre Handler zum Binden verwenden, handelt es sich um eine Eventund die unformatierte DOM-Version von .preventDefault(). In beiden Fällen wird das getan, was Sie brauchen.

Beispiele:

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

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

Option 2: return false;

In jQuery :

Wenn Sie von einem Ereignishandler false zurückgeben, werden automatisch event.stopPropagation () und event.preventDefault () aufgerufen.

Mit jQuery können Sie diesen Ansatz alternativ verwenden, um das Standard-Link-Verhalten zu verhindern:

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

Wenn Sie unformatierte DOM-Ereignisse verwenden, funktioniert dies auch in modernen Browsern, da die HTML 5-Spezifikation dieses Verhalten vorschreibt. Ältere Versionen der Spezifikation haben dies jedoch nicht getan. Wenn Sie also maximale Kompatibilität mit älteren Browsern benötigen, sollten Sie .preventDefault()explizit aufrufen . Siehe event.preventDefault () vs. return false (kein jQuery) für das Spezifikationsdetail.

Paolo Bergantino
quelle
9
Veröffentlichte eine Lösung (3 Jahre zu spät), für die kein Click-Handler angehängt werden muss
Matt Crinklaw-Vogt
In diesem Fall tut Achilles dies nur, weil er möchte, dass der Link als anklickbar angezeigt wird, für den er überhaupt nicht href = "#" verwenden muss. Siehe meine Antwort für weitere Informationen.
Achecopar
164

Sie können Ihre href auf #!anstatt einstellen#

Beispielsweise,

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

führt beim Klicken kein Scrollen durch.

In acht nehmen! Dadurch wird beim Klicken weiterhin ein Eintrag zum Browserverlauf hinzugefügt. Dies bedeutet, dass die Schaltfläche "Zurück" des Benutzers nach dem Klicken auf Ihren Link nicht zu der Seite führt, auf der er zuvor war. Aus diesem Grund ist es wahrscheinlich besser, den .preventDefault()Ansatz zu verwenden oder beide in Kombination zu verwenden.

Hier ist eine Geige, die dies veranschaulicht (schieben Sie einfach Ihren Browser nach unten, bis Sie eine Bildlaufleiste erhalten):
http://jsfiddle.net/9dEG7/


Für die Spec-Nerds - warum das funktioniert:

Dieses Verhalten wird in der HTML5-Spezifikation im Abschnitt Navigieren zu einer Fragmentkennung angegeben . Der Grund dafür, dass ein Link mit einer href von "#"das Dokument nach oben scrollt, besteht darin, dass dieses Verhalten explizit als Methode zur Behandlung einer leeren Fragmentkennung angegeben wird:

2. Wenn fragides sich um die leere Zeichenfolge handelt, befindet sich der angegebene Teil des Dokuments oben im Dokument

Die Verwendung eines href von "#!"funktioniert stattdessen einfach, weil diese Regel vermieden wird. Das Ausrufezeichen ist nichts Magisches - es ist nur eine bequeme Fragmentkennung, da es sich deutlich von einem typischen Fragid unterscheidet und wahrscheinlich nie mit dem idoder nameeines Elements auf Ihrer Seite übereinstimmt . In der Tat könnten wir fast alles nach dem Hash setzen; Die einzigen Fragmente, die nicht ausreichen, sind die leere Zeichenfolge, das Wort "oben" oder Zeichenfolgen, die übereinstimmen nameoder idAttribute von Elementen auf der Seite.

Genauer gesagt benötigen wir nur eine Fragmentkennung, die dazu führt, dass wir Schritt 8 im folgenden Algorithmus durchlaufen, um den angegebenen Teil des Dokuments aus dem Fragid zu bestimmen:

  1. Wenden Sie den URL-Parser-Algorithmus auf die URL an und lassen Sie fragid die Fragmentkomponente der resultierenden analysierten URL sein.

  2. Wenn fragides sich um die leere Zeichenfolge handelt, befindet sich der angegebene Teil des Dokuments oben im Dokument. Stoppen Sie den Algorithmus hier.

  3. Sei fragid bytesdas Ergebnis der prozentualen Dekodierung fragid.

  4. Sei decoded fragiddas Ergebnis der Anwendung des UTF-8-Decoder-Algorithmus auf fragid bytes. Wenn der UTF-8-Decoder einen Decoderfehler ausgibt, brechen Sie den Decoder ab und springen Sie stattdessen zu dem mit beschrifteten Schritt no decoded fragid.

  5. Wenn sich im DOM ein Element befindet, dessen ID genau gleich ist decoded fragid, ist das erste derartige Element in Baumreihenfolge der angegebene Teil des Dokuments. Stoppen Sie den Algorithmus hier.

  6. Kein dekodierter Fragid : Wenn das DOM ein Element mit einem Namensattribut enthält , dessen Wert genau gleich fragid( nichtdecoded fragid ) ist, ist das erste derartige Element in Baumreihenfolge der angegebene Teil des Dokuments. Stoppen Sie den Algorithmus hier.

  7. Wenn fragid eine Übereinstimmung zwischen ASCII-Groß- und Kleinschreibung für die Zeichenfolge nicht berücksichtigt, befindet sich topder angegebene Teil des Dokuments oben im Dokument. Stoppen Sie den Algorithmus hier.

  8. Andernfalls ist kein Teil des Dokuments angegeben.

Solange wir Schritt 8 drücken und kein Teil des Dokuments angegeben ist , kommt die folgende Regel ins Spiel:

Wenn kein Teil angegeben ist ... darf der Benutzeragent nichts tun.

Aus diesem Grund scrollt der Browser nicht.

Matt Crinklaw-Vogt
quelle
4
Es spielt keine Rolle, ob Sie '!' oder einen anderen Wert, solange die ID nicht Teil des DOM ist.
Gopinath
3
Nachdem ich einmal ein Verfechter dieser Methode war, habe ich seitdem eine 180 gemacht und davon abgeraten. Achtung: Links wie diese ändern weiterhin die Seiten-URL, was zu einem zusätzlichen Eintrag im Browserverlauf führt und dazu führt, dass die Schaltfläche "Zurück" das Fragment einfach aus der URL entfernt, anstatt das zu tun, was der Benutzer erwartet. Daher ist diese Lösung für sich genommen, obwohl sie die gestellte Frage beantwortet, normalerweise keine wünschenswerte Alternative zur Verwendung preventDefault()in einem Klick-Handler - eher traurig.
Mark Amery
1
Warum nicht href = "javascript:;" stattdessen? Soweit ich weiß, wird der Verlauf des Browsers dadurch nicht geändert. Gepostet darüber auf meiner Antwort.
Achecopar
30

Ein einfacher Ansatz besteht darin, diesen Code zu nutzen:

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

Dieser Ansatz erzwingt keine Seitenaktualisierung, sodass die Bildlaufleiste an Ort und Stelle bleibt. Außerdem können Sie das Ereignis onclick programmgesteuert ändern und die clientseitige Ereignisbindung mithilfe von jQuery verarbeiten.

Aus diesen Gründen ist die obige Lösung besser als:

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

Wobei die letzte Lösung das Scroll-Jump-Problem genau dann vermeidet, wenn die myClickHandler-Methode nicht fehlschlägt.

phreeskier
quelle
12

Die Rückgabe von false aus dem von Ihnen aufgerufenen Code funktioniert und ist unter bestimmten Umständen die bevorzugte Methode. Sie können dies jedoch auch tun

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

Wenn es um SEO geht, hängt es wirklich davon ab, wofür Ihr Link verwendet wird. Wenn Sie es tatsächlich verwenden, um auf andere Inhalte zu verlinken, würde ich im Idealfall zustimmen, dass Sie hier etwas Sinnvolles wünschen, aber wenn Sie den Link für Funktionszwecke verwenden, wie es Stack Overflow für die Post-Symbolleiste tut (fett, kursiv, Hyperlink) usw.) dann spielt es wahrscheinlich keine Rolle.

Dean
quelle
9

Sie sollten das ändern

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

zu

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

Auf diese Weise wird die Seite beim Klicken auf den Link nicht nach oben gescrollt. Dies ist sauberer als die Verwendung von href = "#" und die Verhinderung der Ausführung des Standardereignisses.

Ich habe gute Gründe dafür bei der ersten Antwort auf diese Frage , wie die return false;wird nicht ausgeführt, wenn die aufgerufene Funktion einen Fehler auslöst, oder Sie können die return false;zu einer doSomething()Funktion hinzufügen und dann vergessen, zu verwendenreturn doSomething();

Achecopar
quelle
7

Versuche dies:

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

Wenn Sie den hrefWert einfach ändern können, sollten Sie Folgendes verwenden:

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

Eine andere nette Lösung, die ich mir gerade ausgedacht habe, ist die Verwendung von jQuery, um das Auftreten der Klickaktion zu verhindern und das Scrollen der Seite zu bewirken, jedoch nur für href="#"Links.

<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
quelle
Sicherlich return falsesollte das nach der preventDefault()Zeile sein, sonst kommen Sie nie zu dieser zweiten Zeile?
Hobailey
3

Verlinken Sie in erster Linie auf etwas Sinnvolleres als den oberen Rand der Seite. Brechen Sie dann das Standardereignis ab.

Siehe Regel 2 der pragmatischen progressiven Verbesserung .

QUentin
quelle
Dies macht Ihre Website auch SEO-freundlicher.
Frankie
2

Sie können event.preventDefault auch im onclick- Attribut verwenden.

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

Es ist nicht erforderlich, ein Exstra-Klick-Ereignis zu schreiben.

efirat
quelle
0

Sie können einfach auch so schreiben: -

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

Folgen Sie dem Aufruf der Funktion anhand eines return false Beispiels:

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

Erstellen Sie eine Seite, die zwei Links enthält - einen oben und einen unten. Wenn Sie auf den oberen Link klicken, muss die Seite zum Ende der Seite scrollen, auf der sich der untere Link befindet. Wenn Sie auf den unteren Link klicken, muss die Seite nach oben scrollen.

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

das wird gut funktionieren. keine Notwendigkeit, href = "#" hinzuzufügen

Varaj Vignesh
quelle
0

Vielleicht möchten Sie Ihr CSS überprüfen. Im Beispiel hier: https://css-tricks.com/the-checkbox-hack/ gibt es position: absolute; top: -9999px;. Dies ist in Chrome besonders doof, da onclick="whatever"immer noch zur absoluten Position des angeklickten Elements gesprungen wird.

Entfernen position: absolute; top: -9999px;, für display: none;könnte helfen.

Scott Phillips
quelle
0

Wenn Sie für Bootstrap 3 zum Reduzieren kein Datenziel für den Anker angeben und sich bei der Bestimmung des Ziels auf href verlassen, wird das Ereignis verhindert. Wenn Sie ein Datenziel verwenden, müssen Sie das Ereignis selbst verhindern.

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