Animiertes Scrollen mit jQuery

Kein Beitragsbild

Marcel Weber

Student der Kommunikations- und Softwaretechnik

Sie klicken auf einen Link und anstatt einfach zum entsprechenden Anker zu springen, wird sanft zum gewünschten Anker gescrollt. Ich sehe diesen Effekt in letzter Zeit immer öfter und war erstaunt, wie einfach er mit jQuery umgesetzt werden kann. Selbst die Erhaltung der „richtigen“ URL (www.url.de#anker) stellt keine Probleme dar. Demo im neuen Fenster

jQuery Code

$(document).ready(function() {
	$('a[href*=#]').bind("click", function(event) {
		event.preventDefault();
		var ziel = $(this).attr("href");

		$('html,body').animate({
			scrollTop: $(ziel).offset().top
		}, 2000 , function (){location.hash = ziel;});
});
return false;
});

Erkläuterung

$(document).ready(function() {

Der Effekt soll natürlich erst angewendet werden, wenn die Seite fertig geladen ist.

$('a[href*=#]').bind("click", function(event) {

Mit a[href*=#] wählen wir alle Links aus, deren Ziel mit einer Raute beginnt, also alle Anker-Links. Mit der bind() Funktion binden wir den folgenden Code an das Klick-Ereignis der Links, so dass er nach dem Klick ausgeführt wird.

event.preventDefault();

Der Code wird jetzt zwar erst nach dem Klick ausgeführt, jedoch versucht der Browser immer noch zuerst zum Anker zu springen, was zu einem Flackern vor dem Scrollen führt. Dieses Standardverhalten wird durch die preventDefault() Methode unterbunden. Beispiel zum Flackern

var ziel = $(this).attr("href");

Um gleich einfacher auf das Link-Ziel zugreifen zu können, wird dieses in die Variable “ziel” geschrieben.

$('html,body').animate({

Nun wählen wir den Bereich aus, den wir animieren wollen, die komplette Seite, als html. Da der Browser Safari den html-selektor nicht erkennt, muss noch “body” angehängt werden. Die Seite wird nun mit der animate() Funktion animiert.

scrollTop: $(ziel).offset().top

Die scrollTop() Funktion scrollt zu dem Wert, der ihr übergeben wird. scrollTop(400) würde die Seite beispielsweise um 400 Pixel nach unten scrollen. Die genaue Position des Ankers, zu dem wir scrollen wollen, bekommen wir mit der offset() Funktion. Mit ihr kann die genaue Position eines Elementes von links und von oben im Dokument ermittelt werden. Da wir hier nur den Abstand von oben benötigen, nutzen wir “offset().top”.

}, 2000 , function (){location.hash = ziel;});
});
return false;
});

Die Zahl nach der Klammer gibt die Dauer der Animation in Millisekunden an (duration). Jetzt kommt die meiner Meinung nach wichtigste Funktion ins Spiel. Die Callback-Funktion der Animation wird ausgeführt, sobald die Animation vollständig beendet ist, also wenn die Seite zum gewünschten Anker gescrollt ist. Diese Funktion brauchen wir, da wir ja das Standardverhalten des Links unterdrückt haben, also den Sprung zum Anker und die Anpassung der URL. Mit location.hash setzen wir eine neue Textmarke und passen so die URL an. Ohne diese Funktion würde der Anker beim Klick nicht an die URL angehängt.

Kennst du unser E-Book-Bundle? Spare jetzt 6,99 €!

E-Book Bundle von Andreas Hecht

Beispiel

Ausgangs URL
www.url.de

Nach Sprung zu einem Anker OHNE location.hash
www.url.de

Nach Sprung zu einem Anker MIT location.hash
www.url.de#anker

Fazit

Es darf über die Notwendigkeit dieses Kniffs gestritten werden, ich persönlich halte ihn für einen ansprechenden und interessanten Effekt, der in vielen Seiten gut zur Wirkung kommt und dem Benutzer vielleicht auch besser verdeutlicht, wo er denn nach einem Klick landet. ™

Ergänzung für Opera

Da ich durch den Kommentar von NightWalker auf das Fehlverhalten in Opera hingewiesen wurde ist hier nun der für Opera optimierte Code.

$(document).ready(function() {
	$('a[href*=#]').bind("click", function(event) {
		event.preventDefault();
		var ziel = $(this).attr("href");
                
                if ($.browser.opera) {
                    var target = 'html';
                }else{
                    var target = 'html,body';
                }

		$(target).animate({
			scrollTop: $(ziel).offset().top
		}, 2000 , function (){location.hash = ziel;});
});
return false;
});

Opera Demo im neuen Fenster

Marcel Weber

Student der Kommunikations- und Softwaretechnik

Hinterlasse einen Kommentar

67 Kommentare auf "Animiertes Scrollen mit jQuery"

Benachrichtige mich zu:
avatar
Sortiert nach:   neueste | älteste | beste Bewertung
Basti
Gast

Das Script funktioniert gut. Als Anpassung für eine meiner Websites muss ich jedoch dem Anker-Sprungziel einen Abstand von 180px mitgeben, da ein div-Kasten mit dieser Höhe oben fixiert ist. Den Abstand habe ich noch “.top” im Script eingefügt ” scrollTop: $(ziel).offset().top -180 ” Nun das Problem: Klicke ich auf den Link, scrollt er mir exakt an die richtige Position. Man sieht dass er es gemacht hat. Dann führt er leider noch einen Schritt aus und verschiebt den Scrollvorgang an die normale Browseroberkante. Kann man diesen letzten Scrollschritt irgendwie aufhalten?
Danke für eure Antworten … wäre wichtig

dirk
Gast

Ich stehe gerade auch vor dem Problem mit dem Abstand von oben.
Hat dafür jemand eine Lösung parat?

Eugen
Gast

Nicht schlecht! Ich habe jedoch ein Problem. Auf meine Seite können die Besucher Bewertungen abgeben. Doch da muss man jetzt den Link “Bewertungen” oder “Bewertung schreiben” zweimal klicken bevor man zu den Tab springt.

Schaue Mal hier http://www.devildeals.de/produkt/acer-aspire-z3-600-dq-stheg-002-all-in-one-desktop-pc/

Klicke dort auf “Bewertungen” oder “Bewertung schreiben”. Wenn du einmal klickst dann scrollt es noch nicht. Beim zweiten Mal hat man den gewünschten Effekt.

Gib es dafür eine Lösung so, dass man beim ersten Klick direkt scrollt?

Gruß, Eugen

Camira
Gast

scrollLeft: $(ziel).offset().left,

…ist die Lösung fürs horizontale scrollen,

den Abstand habe ich noch nicht …

Tipps?

besten Dank

Camira
Gast

Hallo,
super gut erklärt, danke! Und ein Script, das im Gegensatz zu einigen anderen auch funzt, hab nun noch Verschiedenes probiert, um die Ankernavi auch horizontal und mit einem Abstand zwischen Anker und Browserfenster (oben) hinzubekommen, hat leider nix geklappt, wäre sehr dankbar für Tipps

beste Grüße, Camira

Sven Emmrich
Gast

Hi Marcel,

geile Seite! Die erste zu dem Thema, die ich zzumindest nach Blick in Deinen kommentierten Webseitencode verständlich fand. Dieckes Lob dafür. Ich habe nun das Problem, dass bei mir auf der Seite http://www.high-potential.net/wie-es-funktioniert.html nur diejenigen Links sauber funktionieren, die nach oben scrollen. Diejenigen, die nach unten scrollen sollen, gehen auch erst langsam nach oben, um dann anschließend leicht verzögert aprupt nach unten zum Anker zu springen.

Kann mir da einer der Experten bitte behilflich sein? Hier in den Comments oder per Mail?

Vielen Dank!!!

Liebe Grüße

Sven

Michel Otto
Gast

Hallo,

also script ist sehr gut nun habe ich eine Fachfrage.
Ich habe eine HTML 5 animation mit einem Click event zu einem Anker, was dann nicht so schön scrollt sondern springt.

Welche möglichkeit habe ich in dem click event einen a href link zu erzeugen dann würde es denk ich mal gehen oder ich muss das scroll script ansich ändern weil das ja nur auf a href wirkt.

Verwende das LocalScroll Plugin.

Bitte um Hilfe auf mein Email.

Michel Otto
Gast
trackback

[…] – Animiertes Scrollen […]

Denny
Gast

erst einmal großes lob für das tolle script zum animierten scrollen. funktioniert echt top. kann man das script so ändern, dass auch anker auf einer anderen unterseite die ich anspringen möchte angescollt wird? also in etwa so dass die unterseite erst ganz normal geladen wird und dann automatisch zum anker gescrollt wird?

Dennis
Gast

Das würde mich auch interessieren! Konntest du bereits eine Lösung finden?

Randy
Gast

Schönes Script!
Wenn man übrigens die normale Anker-Struktur bedienen will (also zum Ziel und ), kann man schreiben:

scrollTop: $(‘a[name=’+ziel.replace(/#/g, “”)+’]’).offset().top

Michael
Gast

…spitze Marcel!
Vielen vielen Dank!

Michael
Gast

Hallo Marcel,

vielen Dank. Animiert srollen klappt bei mir aber dennoch nicht… 🙁

Michael
Gast

Hallo,

wie könnte ich es hinbekommne, die Absätze in einem DIV mit fester Breite und Höhe einzubinden, dass diese auch darin soft gescrollt werden?

Würde alles bis auf die “Navi” in den div#scrollbereich einfügen.
Bsp-CSS dazu:

#scrollbereich {
height: 300px;
width: 800px;
overflow: scroll;
}

-> damit läuft allerdings der “softscroll” nicht mehr.

Grüße

Michael

fimbim
Gast

Hallo, super Script.
Gibt es auch die Möglichkeit das ganze für eine horizontale Slidefunktion um zu bauen.

Matthias
Gast

Also ehrlich gesagt habe ich das was ich frabriziert hatte schon wieder weggeworfen.

Habe versucht das mit dem Script hier zu kombinieren.

function goto_1(anker){
if(window.location.hash==””){
window.location.href = anker;
}
}

<?php
if ($seite==”versicherungen”){
echo ”bodymitonloadfunktion”;}
else{
echo ”bodyohneonloadfuktion”;
}

Gruß
Matthias

Matthias
Gast

Hallo
finde das ganze recht gut, nur ich bräuchte das ganze im body mit onload statt klick. Versuche das schon 4 Std hat aber irgendwie nicht so richtig funktioniert.

Gruß
Matthias

trackback

[…] im selben (variablen!) Dokument verweisen? Ich habe diesen Code-Schnipsel selbst nur

MikE
Gast

Danke für diese super Erklärung und die Demo. Hat mir wirklich sehr geholfen!

Gruß.

Fritz
Gast

Ein weiteres Problem dieser an sich schönen Methode (schön, weil der User sieht, wohin der Sprung führt):

Die Zurück-Funktion des Browsers wird kaputt gemacht. Im Klartext: nach einen “gewöhnlichen” Sprung zu einem Anker komme ich mit der Zurück-Taste (oder alt + Pfeiltaste links o. ä.) wieder zum Ausgangspunkt des Sprungs. Nach dem Sanft Scrollen leider nicht.
Damit wird der User verunsichert. Sein Browser funktioniert plötzlich nicht mehr wie gewohnt.
Eigentlich schade. Die Browserhersteller sollten wirklich mal darüber nachdenken, dieses feature einzubauen.

trackback

[…] Animiertes Scrollen mit jQuery – Wie man mit jQuery weich zu einem HTML-Anker scrollen kann. […]

Sven
Gast
@Marcel: Richtig, es liegt am IE (wen wundert’s 😉 und nicht am Script. Geeignete Suchbegriffe sind z.B. “in-page keyboard navigation”, über die ich eben auf folgenden Artikel gestoßen bin [url]http://juicystudio.com/article/ie-keyboard-navigation.php[/url] [juicystudio.com]. Das waren noch IE6-Zeiten, und das Problem besteht im IE offenbar bis heute. Es werden mehrere Lösungsmöglichkeiten aufgezeigt, die ich eben aus Zeitgründen nur auf die Schnelle durchprobiert habe, von denen aber leider keine in meiner Testumgebung funktionierte. Damals wurde das hasLayout-Konzept dafür verantwortlich gemacht (z.B. im o.g. Artikel, auf den auch Ingo Chao in seinem berühmten Artikel über das hasLayout-Konzept Bezug nahm), aber da das hasLayout-Konzept im IE8… Read more »
trackback

[…] ich hab mal wieder eine Frage. Warum funktioniert Hier das animierte Scrollen mit jquery von Hier nicht? Gru

Sven
Gast
@Wolfgang Weber: Das sollte ich noch hinzufügen: Für ein einfaches “nach oben” bzw. “Zum Seitenanfang” klappt das Script von Marcel auch im IE. Aber es geht uns ja um die korrekte Fokus-Zuweisung über den gesamten Vorgang der Tab-Navigation hinweg. @Gerd: Vielen Dank für den Hinweis auf Dein Script. Leider besteht hier dasselbe Manko wie beim Script von Marcel: Auch hiermit klappt die Tab-Navigation im IE nicht (außer dem einfachen “nach oben”-Link). Auch hier erfolgt der Sprung zum Sprungziel, aber beim nächsten Tab gehts nicht von da aus weiter, sondern zurück zum ersten Link. Also hapert es noch mit der Fokus-Zuweisung.… Read more »
Gerd
Gast

Nur zur Info für Interessierte. So etwas Ähnliches wurde ohne JQuery bereits vor einigen Jahren von uns gemacht: http://www.kryogenix.org/code/browser/smoothscroll

Ist ein netter und oft nützlicher Effekt, den ich schon mehrfach auf Wunsch eingesetzt habe.

Wolfgang Weber
Gast
@Sven: Danke für die Info bezüglich Internet Explorer 8! Wenn die Accessibility leidet, kommt das Script natürlich nicht in Frage. Schade, denn das animierte Scrollen ist wirklich ein netter Effekt. Ich habe übrigens derzeit eine andere Variante im Einsatz, und theoretisch sollte das auch im IE keine Probleme machen (habe es allerdings noch nicht getestet): $(‘div.nach_oben a’).click(function(event) { $(this).blur(); $.scrollTo(‘#top’, 800); $(‘#sprungmarke_1’).focus(); event.preventDefault(); }); Voraussetzung dafür ist das Plugin “jQuery.ScrollTo – Easy element scrolling using jQuery” von Ariel Flesler. Das Problem dabei ist, dass obiges Code-Schnippsel halt nur für “nach oben”- bzw. “zum Seitenanfang”-Links gedacht ist, während Marcels Code viel… Read more »
Sven
Gast
@Pert (#35) Gib statt der 2000 mal testweise z.B. 1200 ein, dann geht’s schneller. Mir ging’s ähnlich wie Dir. @David Danke für Deine freundlichen Erläuterungen und Tipps! @Wolfgang (#33) Gute Frage bzgl. der Tabnavigation im IE, die ich in #15 ja auch schon andeutete: Zumindest im IE8 klappt die Tabnavigation in Verbindung mit dem animierten Scrollen nicht; wer es ausprobieren will, füge in der Demo in jedem Abschnitt mal ein paar Links ein und teste dann das Verhalten der Tabnavigation im IE: leider unzumutbar. Solange das nicht auch im IE klappt, ist das Script für mich im Produktivbetrieb leider nicht… Read more »
Pert
Gast

Schööön… aber mir wird dabei schwindelig!

David Müller
Gast
Hi Wolfgang, Ich verstehe den Sinn des von dir angegeben Links nicht so ganz…: “glossar.php?dies=5&das=6#Test” Wenn du dem PHP-Script Parameter übergibst, möchtest du doch in der Regel einen Seitenreload oder sehe ich das falsch? Wenn du also einen Reload willst, dann greift das im Artikel beschriebene Script ohnehin nicht mehr, da es ja nicht bei einem Pageload automatisch prüft, ob sich in der URL ein Anker befindet (ein Vorschlag, wie man das umsetzen könnte, habe ich weiter oben geposted). Wenn es dir CMS-bedingt nicht anders möglich ist, die Links zu gestalten, kann ich das natürlich verstehen. Habe dir mal das… Read more »
Wolfgang Weber
Gast

Links der folgenden Art funktionieren bei mir damit überhaupt nicht mehr (Firefox 3.0.13, die aktuelle Version für Ubuntu 8.04):

“glossar.php?dies=5&das=6#Test”

Dem kann aber einfach abgeholfen werden, indem man das * in $(‘a[href*=#]’) durch ein ^ ersetzt.

Nun meine Frage: Welche Erfahrungen habt Ihr gemacht, wenn man die Tabulatortaste zum Navigieren benutzt? Verstehen die Browser, wo sie bei einem Druck auf die Tab-Taste hinsollen, wenn man zuvor einen seiteninternen Link mittels animiertem Scrollen angesteuert hat? Oder gerät die Reihenfolge komplett durcheinander?

Mein Firefox 3.0.13 verhält sich diesbezüglich korrekt. Interessieren würden mich insbesondere die Internet Explorer Versionen 7, 8 und 6.

Danke und Grüße aus der Steiermark!
Wolfgang

Frank
Gast

Vielen Dank für eure Hilfe.

Liebe Grüsse.

Thomas St.
Gast

Bei einfachen Links wie “test.html#Anker1” klappt das ja noch. Aber bei Links wie z.B.

http://test.de/index.php5?page=seite4#Anker2
http://test.de/index.php5?page=seite1&ID=1#Anker3

versagt das Ganze (zumindest bei mir).
Solche Links sind ja bei dynamischen Seiten absolut normal.

Aber href*=# sollte doch eigentlich immer greifen sobald sich ein “#” im href befindet – oder sehe ich das falsch?

David Müller
Gast

@Frank: Ich bin mal so frei..


var sprung = function(event) {
event.preventDefault();
var ziel = $(this).attr("href");
var target = ($.browser.opera) ? 'html' : 'html,body';
$(target).animate({
scrollTop: $(ziel).offset().top
}, 2000 , function (){location.hash = ziel;});
}
$(document).ready(function() {
$('a[href*=#]').bind("click", sprung);
return false;
});

/edit: Obgleich mir etwas schleierhaft ist, warum man sowohl html als auch body als Selector verwenden sollte. Täte es denn nicht der body alleine auch?

Frank
Gast

Vielen Dank für das tolle Script.

ICh bin leider ein absoluter Neuling, hun hab auch das Problem mit Opera, du hast ja schon die Lösung für dieses Problem gepostet. Könntest du mir bitte den kompletten Code (mit Browserweiche) vieleicht noch einmal posten. Vielen herzlichen Dank.

Liebe Grüsse
Frank

Frank
Gast

Schicke Sache

David Müller
Gast

Hi Björn,

man könnte das ganze noch etwas weiterspinnen und direkt onload schauen, ob ein Anker mit übergeben wurde, um so direkt das scrollen zu initialisieren.

Ich stelle mir das etwa so vor, das man den selben Code welcher für die Links benutzt wird gleich wiederverwenden kann:


if (location.hash) sprung();

Das würde zwar in der Form nicht funktionieren, ist aber mit wenig Arbeit schnell umzugestalten. Und dann hätte auch der *=-Selektor seine Daseinsberechtigung. Nichtsdestotrotz hast du natürlich recht, das man bei pageinternen Verweißen auf den Pagename getrost verzichten kann (und sollte).

lg

Björn
Gast

@Sven: David hat den unterschied ja schon erklärt. Es handelt sich hierbei ja lediglich um CSS3 Selektoren, welche mit jQuery schon heute nutzbar sind.
Der andere Selektor hat allerdings keine Auswirkungen auf die Validierung.

@David: Hatte den Selektor nur vorgeschlagen, da im Artikel von der Auswahl aller Links mit einer Raute AM ANFANG war. 🙂

IMHO macht es keinen Sinn, z. B. auch externe Links wie etwa http://www.andere-domain.tld/home.html#anker mit auszuwählen, da das Script dort dann sowieso nicht mehr ausgeführt wird.

Dein Beispiel macht natürlich auch Sinn. Es kommt eben darauf an, wie das HTML der Seite aufgebaut ist. 🙂

lg

megbert
Gast

@Klawischnigg:
Naja, Mehrwert für Benutzer ist schon vorhanden.

Er sieht nämlich, was passiert.

Beim Klick-und-schwupp-ist-der-neue-Inhalt-sichtbar ist nicht offensichtlich, dass der Inhalt sich auf der gleichen Seite befindet, beim weichen Scrollen wird es ihm dagegen mit einfachen, selbsterklärenden Mitteln klar verdeutlicht.

Du kannst diese Visualisierung natürlich auch ohne das Framework machen, ist dann halt ein wenig mehr individueller Code. Aber warum das Rad nochmal neu erfinden?

Klawischnigg
Gast

Naja – Mehrwert für Benutzer – Null.
Viel mehr gibts dazu nicht zu sagen, ausser daß man sich zusätzlich noch den Speicher mit niemals gebrauchten im Framework verbogenen Funktionen vollmüllt.

Wolfgang
Gast

Seit wann ist jQuery eigentlich so fett? 55 Kb finde ich schon heftig.

David Müller
Gast
@Sven: Ich habe (FF3.52, versucht mit Webdev-Toolbar, Firebug und FF-interner Fehlerkonsole (die ja letztendlich alle auf dem gleichen Error-Modell basieren) keinerlei Fehlermeldungen / Warnungen. Bezüglich dem von Björn angesprochenen Seletor würde ich diese Seite empfehlen: http://docs.jquery.com/Selectors (unter “Attributes”). $(‘a[href*=#]’) matcht alle Links mit einer Raute irgendwo im href-Attribut. $(‘a[href^=#]’) (Björns Vorschlag) matcht alle Links mit einer Raute AM ANFANG des href-Attributs. Allerdings würde ich auch eher zum ursprünglichen Selektor *= greifen, weil du somit sowohl auch href=”index.html#Eintrag15″ als auch auf href=”#Eintrag15″ verweisen kannst. Performancetechnisch ist da kaum ein Unterschied zu erwarten, gerade bei nicht selbstgeschriebenem Code ist man so zumindest… Read more »
David Müller
Gast

@ NightWalker: Ich denk mal, dass das bei dir am Anker “#top” liegt, der (genau wie #bottom) nicht fest definiert werden muss, sondern einfach verwendet werden kann. Logischerweise hat dieser auch keine “reale” Position, d.h. jQuery kann den .offset().top-Wert nicht ermitteln. Wenn du beinem allerdings die id=”top” gibst, sollte das wieder funktionieren.

lg

NightWalker
Gast

Ich persönlich sehe darin keinen wirklichen Usability gewinn. Ausserdem scheint es mit Opera nicht zu funktionieren. Runter scrollen klappt aber wenn man auf “wieder nach oben” klickt sprint er sofort nach oben aber das Bild flackert noch ein paar sekunden

Sven
Gast
Schönes Tutorial, danke! Björn, könntest Du vielleicht Deinen Vorschlag kurz einem JS-Neuling erklären? Ich hatte schon gehofft, es könnte die Lösung für das Validierungsproblem sein, war aber nicht so. Die Webdeveloper-Toolbar zeigt (auch auf der Demoseite) folgende Warnung: Warnung: Indentifikator oder String für Wert in Attribut-Selektor erwartet, aber ‘#’ gefunden. Quelldatei: http://www.drweb.de/magazin/wp-content/uploads/animiertesscrollen.html Zeile: 0 Oder je nach ausgewähltem Anker: Warnung: Indentifikator oder String für Wert in Attribut-Selektor erwartet, aber ‘#’ gefunden. Quelldatei: http://www.drweb.de/magazin/wp-content/uploads/animiertesscrollen.html#anker4 Zeile: 0 Hat jemand einen Tipp, wie man das JS verändert, um keine Warnung mehr zu bekommen, oder ist das unvermeidlich, weil eine richtige URL erwartet wird?… Read more »