Spaces. Smartes Cloud Hosting für anspruchsvolle Webprojekte. Loslegen und Spaces testen. Von Mittwald.
Marcel Weber 26. August 2009

Animiertes Scrollen mit jQuery

Kein Beitragsbild

Sie kli­cken auf einen Link und anstatt ein­fach zum ent­spre­chen­den Anker zu sprin­gen, wird sanft zum gewünsch­ten Anker gescrollt. Ich sehe die­sen Effekt in letz­ter Zeit immer öfter und war erstaunt, wie ein­fach er mit jQuery umge­setzt wer­den kann. Selbst die Erhaltung der „rich­ti­gen“ URL (www.url.de#anker) stellt kei­ne Probleme dar. Demo im neu­en 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ür­lich erst ange­wen­det wer­den, wenn die Seite fer­tig gela­den ist.

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

Mit a[href*=#] wäh­len wir alle Links aus, deren Ziel mit einer Raute beginnt, also alle Anker-Links. Mit der bind() Funktion bin­den wir den fol­gen­den Code an das Klick-Ereignis der Links, so dass er nach dem Klick aus­ge­führt wird.

event.preventDefault();

Der Code wird jetzt zwar erst nach dem Klick aus­ge­führt, jedoch ver­sucht der Browser immer noch zuerst zum Anker zu sprin­gen, was zu einem Flackern vor dem Scrollen führt. Dieses Standardverhalten wird durch die preventDefault() Methode unter­bun­den. Beispiel zum Flackern

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

Um gleich ein­fa­cher auf das Link-Ziel zugrei­fen zu kön­nen, wird die­ses in die Variable “ziel” geschrie­ben.

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

Nun wäh­len wir den Bereich aus, den wir ani­mie­ren wol­len, die kom­plet­te Seite, als html. Da der Browser Safari den html-selek­tor nicht erkennt, muss noch “body” ange­hängt wer­den. Die Seite wird nun mit der ani­ma­te() Funktion ani­miert.

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

Die scrollTop() Funktion scrollt zu dem Wert, der ihr über­ge­ben wird. scrollTop(400) wür­de die Seite bei­spiels­wei­se um 400 Pixel nach unten scrol­len. Die genaue Position des Ankers, zu dem wir scrol­len wol­len, bekom­men wir mit der off­set() Funktion. Mit ihr kann die genaue Position eines Elementes von links und von oben im Dokument ermit­telt wer­den. Da wir hier nur den Abstand von oben benö­ti­gen, nut­zen wir “offset().top”.

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

Die Zahl nach der Klammer gibt die Dauer der Animation in Millisekunden an (dura­ti­on). Jetzt kommt die mei­ner Meinung nach wich­tigs­te Funktion ins Spiel. Die Callback-Funktion der Animation wird aus­ge­führt, sobald die Animation voll­stän­dig been­det ist, also wenn die Seite zum gewünsch­ten Anker gescrollt ist. Diese Funktion brau­chen wir, da wir ja das Standardverhalten des Links unter­drückt haben, also den Sprung zum Anker und die Anpassung der URL. Mit location.hash set­zen wir eine neue Textmarke und pas­sen so die URL an. Ohne die­se Funktion wür­de der Anker beim Klick nicht an die URL ange­hängt.

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 die­ses Kniffs gestrit­ten wer­den, ich per­sön­lich hal­te ihn für einen anspre­chen­den und inter­es­san­ten Effekt, der in vie­len Seiten gut zur Wirkung kommt und dem Benutzer viel­leicht auch bes­ser ver­deut­licht, wo er denn nach einem Klick lan­det. (tm)

Ergänzung für Opera

Da ich durch den Kommentar von NightWalker auf das Fehlverhalten in Opera hin­ge­wie­sen wur­de ist hier nun der für Opera opti­mier­te 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 neu­en Fenster

Marcel Weber

Student der Kommunikations- und Softwaretechnik

63 Kommentare

  1. Das Script funk­tio­niert gut. Als Anpassung für eine mei­ner Websites muss ich jedoch dem Anker-Sprungziel einen Abstand von 180px mit­ge­ben, da ein div-Kasten mit die­ser Höhe oben fixiert ist. Den Abstand habe ich noch “.top” im Script ein­ge­fügt ” scrollTop: $(ziel).offset().top -180 ” Nun das Problem: Klicke ich auf den Link, scrollt er mir exakt an die rich­ti­ge Position. Man sieht dass er es gemacht hat. Dann führt er lei­der noch einen Schritt aus und ver­schiebt den Scrollvorgang an die nor­ma­le Browseroberkante. Kann man die­sen letz­ten Scrollschritt irgend­wie auf­hal­ten?
    Danke für eure Antworten … wäre wich­tig

  2. Nicht schlecht! Ich habe jedoch ein Problem. Auf mei­ne Seite kön­nen die Besucher Bewertungen abge­ben. Doch da muss man jetzt den Link “Bewertungen” oder “Bewertung schrei­ben” zwei­mal kli­cken 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 schrei­ben”. Wenn du ein­mal klickst dann scrollt es noch nicht. Beim zwei­ten Mal hat man den gewünsch­ten Effekt.

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

    Gruß, Eugen

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

    …ist die Lösung fürs hori­zon­ta­le scrol­len,

    den Abstand habe ich noch nicht …

    Tipps?

    bes­ten Dank

  4. Hallo,
    super gut erklärt, dan­ke! Und ein Script, das im Gegensatz zu eini­gen ande­ren auch funzt, hab nun noch Verschiedenes pro­biert, um die Ankernavi auch hori­zon­tal und mit einem Abstand zwi­schen Anker und Browserfenster (oben) hin­zu­be­kom­men, hat lei­der nix geklappt, wäre sehr dank­bar für Tipps

    bes­te Grüße, Camira

  5. Hi Marcel,

    gei­le Seite! Die ers­te zu dem Thema, die ich zzu­min­dest nach Blick in Deinen kom­men­tier­ten Webseitencode ver­ständ­lich 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 die­je­ni­gen Links sau­ber funk­tio­nie­ren, die nach oben scrol­len. Diejenigen, die nach unten scrol­len sol­len, gehen auch erst lang­sam nach oben, um dann anschlie­ßend leicht ver­zö­gert aprupt nach unten zum Anker zu sprin­gen.

    Kann mir da einer der Experten bit­te behilf­lich sein? Hier in den Comments oder per Mail?

    Vielen Dank!!!

    Liebe Grüße

    Sven

  6. Hallo,

    also script ist sehr gut nun habe ich eine Fachfrage.
    Ich habe eine HTML 5 ani­ma­ti­on mit einem Click event zu einem Anker, was dann nicht so schön scrollt son­dern springt.

    Welche mög­lich­keit habe ich in dem click event einen a href link zu erzeu­gen dann wür­de 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.

  7. erst ein­mal gro­ßes lob für das tol­le script zum ani­mier­ten scrol­len. funk­tio­niert echt top. kann man das script so ändern, dass auch anker auf einer ande­ren unter­sei­te die ich ansprin­gen möch­te ange­s­collt wird? also in etwa so dass die unter­sei­te erst ganz nor­mal gela­den wird und dann auto­ma­tisch zum anker gescrollt wird?

  8. Schönes Script!
    Wenn man übri­gens die nor­ma­le Anker-Struktur bedie­nen will (also zum Ziel und ), kann man schrei­ben:

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

  9. …spit­ze Marcel!
    Vielen vie­len Dank!

  10. Hallo Marcel,

    vie­len Dank. Animiert srol­len klappt bei mir aber den­noch nicht… :(

  11. @Michael

    $(document).ready(function() {
    // Alle inter­nen Links aus­wäh­len
    $(‘a[href*=#]’).bind(“click”, function(event) {
    // Standard Verhalten unter­drü­cken
    event.preventDefault();
    // Linkziel in Variable schrei­ben
    var ziel = $(this).attr(“href”);
    var tar­get = ‘#scroll­be­reich’;
    //Scrollen der Seite ani­mie­ren, body benö­tigt für Safari
    $(target).animate({
    //Zum Ziel scrol­len (Variable)
    scrollTop: ($(ziel).offset().top)-($(target).offset().top) + ($(target).scrollTop())
    // Dauer der Animation und Callbackfunktion die nach der Animation auf­ge­ru­fen wird, sie stellt das Standardverhalten wie­der her und ergänzt die URL
    }, 2000 , func­tion (){location.hash = ziel;});
    });
    return fal­se;
    });

  12. Hallo,

    wie könn­te ich es hin­be­komm­ne, die Absätze in einem DIV mit fes­ter Breite und Höhe ein­zu­bin­den, dass die­se auch dar­in soft gescrollt wer­den?

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

    #scroll­be­reich {
    height: 300px;
    width: 800px;
    over­flow: scroll;
    }

    -> damit läuft aller­dings der “soft­scroll” nicht mehr.

    Grüße

    Michael

  13. Hallo, super Script.
    Gibt es auch die Möglichkeit das gan­ze für eine hori­zon­ta­le Slidefunktion um zu bau­en.

  14. Also ehr­lich gesagt habe ich das was ich frab­ri­ziert hat­te schon wie­der weg­ge­wor­fen.

    Habe ver­sucht das mit dem Script hier zu kom­bi­nie­ren.

    func­tion goto_1(anker){
    if(window.location.hash==“”){
    window.location.href = anker;
    }
    }

    <?php
    if ($seite==“versicherungen”){
    echo ”body­miton­load­funk­ti­on”;}
    else{
    echo ”bodyoh­ne­on­load­fuk­ti­on”;
    }

    Gruß
    Matthias

  15. @Matthias kannst du mal ein Beispiel pos­ten, wie dein code im moment aus­sieht?

    Gruß Marcel

  16. Hallo
    fin­de das gan­ze recht gut, nur ich bräuch­te das gan­ze im body mit onload statt klick. Versuche das schon 4 Std hat aber irgend­wie nicht so rich­tig funk­tio­niert.

    Gruß
    Matthias

  17. Danke für die­se super Erklärung und die Demo. Hat mir wirk­lich sehr gehol­fen!

    Gruß.

  18. Ein wei­te­res Problem die­ser 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öhn­li­chen” Sprung zu einem Anker kom­me ich mit der Zurück-Taste (oder alt + Pfeiltaste links o. ä.) wie­der zum Ausgangspunkt des Sprungs. Nach dem Sanft Scrollen lei­der nicht.
    Damit wird der User ver­un­si­chert. Sein Browser funk­tio­niert plötz­lich nicht mehr wie gewohnt.
    Eigentlich scha­de. Die Browserhersteller soll­ten wirk­lich mal dar­über nach­den­ken, die­ses fea­ture ein­zu­bau­en.

  19. @Sven

    Versuch mal fol­gen­den Code :-)
    Als ergän­zung musst du in dei­nen Sprungzielen einen Tabindex set­zen!

    $(document).ready(function() {
    	$('a[href*=#]').bind("click", function(event) {
    		event.preventDefault();
    		var ziel = $(this).attr("href");
                    
                    var active = ziel.substring(1,ziel.length);
                    if ($.browser.opera) {
                        var target = 'html';
                    }else{
                        var target = 'html,body';
                    }
    
    		$(target).animate({
    			scrollTop: $(ziel).offset().top
    		}, 2000 , function (){location.hash = ziel;
     document.getElementById(active).focus(); });
    });
    return false;
    });
    
  20. @Marcel:
    Richtig, es liegt am IE (wen wundert’s ;-) und nicht am Script. Geeignete Suchbegriffe sind z.B. “in-page key­board navi­ga­ti­on”, über die ich eben auf fol­gen­den 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 offen­bar bis heu­te. Es wer­den meh­re­re Lösungsmöglichkeiten auf­ge­zeigt, die ich eben aus Zeitgründen nur auf die Schnelle durch­pro­biert habe, von denen aber lei­der kei­ne in mei­ner Testumgebung funk­tio­nier­te.

    Damals wur­de das hasLayout-Konzept dafür ver­ant­wort­lich gemacht (z.B. im o.g. Artikel, auf den auch Ingo Chao in sei­nem berühm­ten Artikel über das hasLayout-Konzept Bezug nahm), aber da das hasLayout-Konzept im IE8 ja m.W. nicht mehr Anwendung fin­det, muss es an was ande­rem lie­gen.

    Interessierte kön­nen ja mal mit den auf juicystudio.com gezeig­ten Lösungen tes­ten und und hier evtl. über posi­ti­ve Ergebnisse berich­ten.

    Vielleicht gibt’s auf drweb ja dem­nächst sogar einen eige­nen Artikel zu die­ser spe­zi­el­len Problematik. Mein Wunschautor: Marcel Weber ;-)

  21. @Sven: Ich habe ver­sucht eine Lösung für das Problem zu fin­den, bis jetzt bin ich aber noch nicht fün­dig gewor­den.

    Jedoch bin ich bei mei­ner Suche auf etwas ande­res gesto­ßen, was ich bis­her gar­nicht beach­tet habe.

    Als wenn ich als Beispiel die­se Seite die kein JavaScript ent­hält im IE öff­ne dann funk­tio­niert, zumin­dest bei mir, die Tab-Navigation eben­falls nicht. Somit sehe ich das Problem all­ge­mein bei IE und nicht direkt im Script.

  22. @Wolfgang Weber:

    Das soll­te ich noch hin­zu­fü­gen: Für ein ein­fa­ches “nach oben” bzw. “Zum Seitenanfang” klappt das Script von Marcel auch im IE. Aber es geht uns ja um die kor­rek­te Fokus-Zuweisung über den gesam­ten Vorgang der Tab-Navigation hin­weg.

    @Gerd:
    Vielen Dank für den Hinweis auf Dein Script. Leider besteht hier das­sel­be Manko wie beim Script von Marcel: Auch hier­mit klappt die Tab-Navigation im IE nicht (außer dem ein­fa­chen “nach oben”-Link). Auch hier erfolgt der Sprung zum Sprungziel, aber beim nächs­ten Tab gehts nicht von da aus wei­ter, son­dern zurück zum ers­ten Link. Also hapert es noch mit der Fokus-Zuweisung.

    Mal sehen, viel­leicht fin­det doch noch ein Spezialist die Lösung für den IE.

  23. Nur zur Info für Interessierte. So etwas Ähnliches wur­de ohne JQuery bereits vor eini­gen Jahren von uns gemacht: http://www.kryogenix.org/code/browser/smoothscroll

    Ist ein net­ter und oft nütz­li­cher Effekt, den ich schon mehr­fach auf Wunsch ein­ge­setzt habe.

  24. @Sven:

    Danke für die Info bezüg­lich Internet Explorer 8! Wenn die Accessibility lei­det, kommt das Script natür­lich nicht in Frage. Schade, denn das ani­mier­te Scrollen ist wirk­lich ein net­ter Effekt.

    Ich habe übri­gens der­zeit eine ande­re Variante im Einsatz, und theo­re­tisch soll­te das auch im IE kei­ne Probleme machen (habe es aller­dings noch nicht getes­tet):

    $(‘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 ele­ment scrol­ling using jQuery” von Ariel Flesler.

    Das Problem dabei ist, dass obi­ges Code-Schnippsel halt nur für “nach oben”- bzw. “zum Seitenanfang”-Links gedacht ist, wäh­rend Marcels Code viel all­ge­mei­ner funk­tio­niert. Wenn nur die Nebenwirkungen nicht wären…

    @David:

    Der Sinn des von mir genann­ten Links ist leicht erklärt. Und zwar han­delt es sich dabei um inter­ne Links zur Glossar-Seite, wobei die Links halt auch einen Anker besit­zen.

    Ich habe mir ein klei­nes Templatesystem pro­gram­miert, sodass ich in der Templatedatei, wenn ich auf einen Glossar-Eintrag ver­wei­sen möch­te, z.B. nur

    T_GLOSSAR#Zu_erklärendes_Wort–

    schrei­ben muss, und das Templatesystem bas­telt mir den Link zum ent­spre­chen­den Eintrag mit­tels preg_replace_callback() zusam­men – ein­schließ­lich eines Links auf der Glossar-Seite, der zu der Stelle, von wel­cher der Eintrag auf­ge­ru­fen wur­de, zurück­führt.
    Und damit das Ganze auch ohne JavaScript (history.back()) funk­tio­niert, wer­den bestimm­te Parameter in der URL über­ge­ben.

    Die Links sehen also so aus:

    href= “glossar.php?QUERYSTRING#ANKER”

    Und die­se Art von Links funk­tio­nie­ren mit Marcels Script ($(‘a[href*=#]’)) auf­grund des * halt nicht. Das ist aber kein wirk­li­ches Problem.

    Es wäre nur toll, wenn jenes Element, zu dem gescrollt wird, auch ver­läss­lich den Focus bekä­me, und zwar auch in IE 6–8.

    LG, Wolfgang

  25. @Pert (#35)
    Gib statt der 2000 mal test­wei­se z.B. 1200 ein, dann geht’s schnel­ler. Mir ging’s ähn­lich wie Dir.

    @David
    Danke für Deine freund­li­chen Erläuterungen und Tipps!

    @Wolfgang (#33)
    Gute Frage bzgl. der Tabnavigation im IE, die ich in #15 ja auch schon andeu­te­te: Zumindest im IE8 klappt die Tabnavigation in Verbindung mit dem ani­mier­ten Scrollen nicht; wer es aus­pro­bie­ren will, füge in der Demo in jedem Abschnitt mal ein paar Links ein und tes­te dann das Verhalten der Tabnavigation im IE: lei­der unzu­mut­bar. Solange das nicht auch im IE klappt, ist das Script für mich im Produktivbetrieb lei­der nicht ein­setz­bar. Sehr scha­de…

    Falls jemand in der Lage ist, das Script für den IE so zu ändern, dass die Tabnavigation beim ani­mier­ten Scrollen so wie beim Firefox klappt, wäre das sen­sa­tio­nell!

  26. Schööön… aber mir wird dabei schwin­de­lig!

  27. Hi Wolfgang,

    Ich ver­ste­he den Sinn des von dir ange­ge­ben Links nicht so ganz…: “glossar.php?dies=5&das=6#Test”

    Wenn du dem PHP-Script Parameter über­gibst, möch­test du doch in der Regel einen Seitenreload oder sehe ich das falsch? Wenn du also einen Reload willst, dann greift das im Artikel beschrie­be­ne Script ohne­hin nicht mehr, da es ja nicht bei einem Pageload auto­ma­tisch prüft, ob sich in der URL ein Anker befin­det (ein Vorschlag, wie man das umset­zen könn­te, habe ich wei­ter oben geposted).

    Wenn es dir CMS-bedingt nicht anders mög­lich ist, die Links zu gestal­ten, kann ich das natür­lich ver­ste­hen. Habe dir mal das Script so umge­schrie­ben, dass es für dei­ne Zwecke funk­tio­niert:


    $(document).ready(function() {
    $('a[href*=#]').bind("click", function(event) {
    event.preventDefault();
    var linkHref=$(this).attr("href");
    //Sprungmarke extrahieren
    var ziel=linkHref.substr(linkHref.lastIndexOf("#"));
    $('html,body').animate({
    scrollTop: $(ziel).offset().top
    }, 2000 , function (){location.hash = ziel;});
    });
    return false;
    });

  28. Links der fol­gen­den Art funk­tio­nie­ren bei mir damit über­haupt nicht mehr (Firefox 3.0.13, die aktu­el­le Version für Ubuntu 8.04):

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

    Dem kann aber ein­fach abge­hol­fen wer­den, indem man das * in $(‘a[href*=#]’) durch ein ^ ersetzt.

    Nun mei­ne 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 hin­sol­len, wenn man zuvor einen sei­ten­in­ter­nen Link mit­tels ani­mier­tem Scrollen ange­steu­ert hat? Oder gerät die Reihenfolge kom­plett durch­ein­an­der?

    Mein Firefox 3.0.13 ver­hält sich dies­be­züg­lich kor­rekt. Interessieren wür­den mich ins­be­son­de­re die Internet Explorer Versionen 7, 8 und 6.

    Danke und Grüße aus der Steiermark!
    Wolfgang

  29. Vielen Dank für eure Hilfe.

    Liebe Grüsse.

  30. @Thomas St.: Versthe ich das rich­tig, du gibst die kom­plet­te URL als Ankerziel an?

    Scrolle zu Anker 2

    Dann musst du die­sen String wie­der kür­zen, da jQuery ja nicht den off­set der Kompletten Seite berech­nen kann.

    var ziel = $(this).attr("href");
    var raute = ziel.indexOf("#");
    var ziel = ziel.substr(raute, ziel.length);
    

    So funk­tio­niert dass dann auch mit der kom­plet­ten URL, jedoch ver­ste­he ich den Sinn dahin­ter nicht wirk­lich. Ausser natür­lich dass es CMS bedingt kei­ne ande­re Möglichkeit gibt.

  31. @Frank: Ich habe den Artikel soeben am Ende ergänzt.

    @David Müller: Du meinst den Selektor in der else Anweisung? Der zusätz­li­chen body wird für Safari benö­tigt. Opera hin­ge­gen erkennt body nicht rich­tig. Man könn­te natür­lich auch eine Browserweiche für Safari schrei­ben.

  32. Bei ein­fa­chen 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

    ver­sagt das Ganze (zumin­dest bei mir).
    Solche Links sind ja bei dyna­mi­schen Seiten abso­lut nor­mal.

    Aber href*=# soll­te doch eigent­lich immer grei­fen sobald sich ein “#” im href befin­det – oder sehe ich das falsch?

  33. @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 schlei­er­haft ist, war­um man sowohl html als auch body als Selector ver­wen­den soll­te. Täte es denn nicht der body allei­ne auch?

  34. Vielen Dank für das tol­le Script.

    ICh bin lei­der ein abso­lu­ter Neuling, hun hab auch das Problem mit Opera, du hast ja schon die Lösung für die­ses Problem gepos­tet. Könntest du mir bit­te den kom­plet­ten Code (mit Browserweiche) vie­leicht noch ein­mal pos­ten. Vielen herz­li­chen Dank.

    Liebe Grüsse
    Frank

  35. @NightWalker: Ich habe das Opera Problem gelöst. Opera kommt mit $('html,body').animate({ nicht klar, da er bei­de Selektoren kennt und bei­de zu ani­mie­ren ver­sucht.

    Wenn man nur ‘html’ ver­wen­det funk­tio­niert alles, jedoch nicht mehr in Safari.

    Deshalb habe ich auf die schnel­le ein­fach eine Browserweiche ein­ge­fügt, und den ent­spre­chen­den Selektor in eine Variable geschrie­ben.

    if ($.browser.opera) {
    var target = 'html';
    }else{
    var target = 'html,body';
    }

    $(target).animate({

    Mit die­sem Code funk­tio­niert nun alles auch in Opera.

    Ich wer­de es gleich noch im Artikel ergän­zen.

  36. Hi Björn,

    man könn­te das gan­ze noch etwas wei­ter­spin­nen und direkt onload schau­en, ob ein Anker mit über­ge­ben wur­de, um so direkt das scrol­len zu initia­li­sie­ren.

    Ich stel­le mir das etwa so vor, das man den sel­ben Code wel­cher für die Links benutzt wird gleich wie­der­ver­wen­den kann:


    if (location.hash) sprung();

    Das wür­de zwar in der Form nicht funk­tio­nie­ren, ist aber mit wenig Arbeit schnell umzu­ge­stal­ten. Und dann hät­te auch der *=-Selektor sei­ne Daseinsberechtigung. Nichtsdestotrotz hast du natür­lich recht, das man bei page­in­ter­nen Verweißen auf den Pagename getrost ver­zich­ten kann (und soll­te).

    lg

  37. @Sven: David hat den unter­schied ja schon erklärt. Es han­delt sich hier­bei ja ledig­lich um CSS3 Selektoren, wel­che mit jQuery schon heu­te nutz­bar sind.
    Der ande­re Selektor hat aller­dings kei­ne Auswirkungen auf die Validierung.

    @David: Hatte den Selektor nur vor­ge­schla­gen, da im Artikel von der Auswahl aller Links mit einer Raute AM ANFANG war. :)

    IMHO macht es kei­nen Sinn, z. B. auch exter­ne Links wie etwa http://www.andere-domain.tld/home.html#anker mit aus­zu­wäh­len, da das Script dort dann sowie­so nicht mehr aus­ge­führt wird.

    Dein Beispiel macht natür­lich auch Sinn. Es kommt eben dar­auf an, wie das HTML der Seite auf­ge­baut ist. :)

    lg

  38. @Klawischnigg:
    Naja, Mehrwert für Benutzer ist schon vor­han­den.

    Er sieht näm­lich, was pas­siert.

    Beim Klick-und-schwupp-ist-der-neue-Inhalt-sicht­bar ist nicht offen­sicht­lich, dass der Inhalt sich auf der glei­chen Seite befin­det, beim wei­chen Scrollen wird es ihm dage­gen mit ein­fa­chen, selbst­er­klä­ren­den Mitteln klar ver­deut­licht.

    Du kannst die­se Visualisierung natür­lich auch ohne das Framework machen, ist dann halt ein wenig mehr indi­vi­du­el­ler Code. Aber war­um das Rad noch­mal neu erfin­den?

  39. @NightWalker: Das Problem mit Opera war mir lei­der nicht bekannt, da ich nur mit Firefox, Safari und IE getes­tet habe.

    Opera ermit­telt den .offset().top-Wert kor­rekt, jedoch springt Opera bei einem klei­ne­ren Wert als der Aktuellen Position wie­der zum Seitenanfang und ver­sucht dann um den klei­ne­ren Wert wie­der nach unten zu Scrollen, dies führt zu dem Flackern.

    Jedoch fällt mir auf die schnel­le kei­ne Lösung ein die­ses Problem zu behe­ben.

  40. Naja – Mehrwert für Benutzer – Null.
    Viel mehr gibts dazu nicht zu sagen, aus­ser daß man sich zusätz­lich noch den Speicher mit nie­mals gebrauch­ten im Framework ver­bo­ge­nen Funktionen voll­müllt.

  41. Seit wann ist jQuery eigent­lich so fett? 55 Kb fin­de ich schon hef­tig.

  42. @Sven: Ich habe (FF3.52, ver­sucht mit Webdev-Toolbar, Firebug und FF-inter­ner Fehlerkonsole (die ja letzt­end­lich alle auf dem glei­chen Error-Modell basie­ren) kei­ner­lei Fehlermeldungen / Warnungen. Bezüglich dem von Björn ange­spro­che­nen Seletor wür­de ich die­se Seite emp­feh­len: http://docs.jquery.com/Selectors (unter “Attributes”).

    $(‘a[href*=#]’) matcht alle Links mit einer Raute irgend­wo im href-Attribut.

    $(‘a[href^=#]’) (Björns Vorschlag) matcht alle Links mit einer Raute AM ANFANG des href-Attributs.

    Allerdings wür­de ich auch eher zum ursprüng­li­chen Selektor *= grei­fen, weil du somit sowohl auch href=“index.html#Eintrag15” als auch auf href=“#Eintrag15” ver­wei­sen kannst. Performancetechnisch ist da kaum ein Unterschied zu erwar­ten, gera­de bei nicht selbst­ge­schrie­be­nem Code ist man so zumin­dest für alle Eventualitäten gewapp­net.

    lg

  43. @ NightWalker: Ich denk mal, dass das bei dir am Anker “#top” liegt, der (genau wie #bot­tom) nicht fest defi­niert wer­den muss, son­dern ein­fach ver­wen­det wer­den kann. Logischerweise hat die­ser auch kei­ne “rea­le” Position, d.h. jQuery kann den .offset().top-Wert nicht ermit­teln. Wenn du bei­nem aller­dings die id=“top” gibst, soll­te das wie­der funk­tio­nie­ren.

    lg

  44. Ich per­sön­lich sehe dar­in kei­nen wirk­li­chen Usability gewinn. Ausserdem scheint es mit Opera nicht zu funk­tio­nie­ren. Runter scrol­len klappt aber wenn man auf “wie­der nach oben” klickt sprint er sofort nach oben aber das Bild fla­ckert noch ein paar sekun­den

  45. Schönes Tutorial, dan­ke!

    Björn, könn­test Du viel­leicht Deinen Vorschlag kurz einem JS-Neuling erklä­ren? Ich hat­te schon gehofft, es könn­te die Lösung für das Validierungsproblem sein, war aber nicht so. Die Webdeveloper-Toolbar zeigt (auch auf der Demoseite) fol­gen­de Warnung:

    Warnung: Indentifikator oder String für Wert in Attribut-Selektor erwar­tet, aber ‘#’ gefun­den.
    Quelldatei: http://www.drweb.de/magazin/wp-content/uploads/animiertesscrollen.html
    Zeile: 0

    Oder je nach aus­ge­wähl­tem Anker:

    Warnung: Indentifikator oder String für Wert in Attribut-Selektor erwar­tet, aber ‘#’ gefun­den.
    Quelldatei: http://www.drweb.de/magazin/wp-content/uploads/animiertesscrollen.html#anker4
    Zeile: 0

    Hat jemand einen Tipp, wie man das JS ver­än­dert, um kei­ne Warnung mehr zu bekom­men, oder ist das unver­meid­lich, weil eine rich­ti­ge URL erwar­tet wird?

    Noch eine ande­re Frage:

    A pro­pos Zugänglichkeit: Im Firefox 3.5.2 klappt das wun­der­bar mit der Tab-Navigation – Fokus auf Sprungmarke, Sprung zum Anker, wie­der auf TAB drü­cken, Fokus auf Sprungmarke zurück nach oben. Oder man tabbt wei­ter zum nächs­ten Link unter dem Sprungziel. Besser gehts nicht.

    Im IE8 ist das mit der Tab-Navigation eher sub­op­ti­mal (ein­fach mal aus­pro­bie­ren), sodass man z.B. nicht vom Sprungziel direkt zum nächs­ten Link tab­ben kann. Hat da jemand eine Lösung oder ist das beim IE unver­meid­lich?

  46. Möchte man nur Links aus­wäh­len die mit einer Raute begin­nen, soll­te man bes­ser $(‘a[href^=#]’) ver­wen­den.

  47. Ich fin­de es einen net­ten Effekt. Mag ihn pers. auch. Allerdings ist es das auch – ein Effekt – und nicht mehr. Einen Vorteil gegen­über der ’nor­ma­len’ Anker Nutzung sehe ich nicht. Allerdings auch kei­nen Nachteil, abge­se­hen davon das es halt ein paar ms ‘dau­ert’ :-)

  48. Die vor­ge­stell­te Lösung ist aber bei einer Seite, die exzes­si­ven Gebrauch von Sprungmarken macht, noch opti­mie­rungs­fä­hig.

    Durch $('a[href*=#]').bind("click", function(event) { wird an die Event-Listener jedes ent­spre­chen­den Links eine neue Funktion gebun­den. Bei 100 Sprungmarken ent­ste­hen so 100 iden­ti­sche Funktionen. Sinnvoller ist es also die Funktion erst zu defi­nie­ren und der Bind-Methode des­sen Namen zu über­ge­ben:

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

    Grüße,
    Dominik

  49. Wollt ich nur mal los­wer­den: Ich fin­de Deine Artikel rund um jque­ry echt klas­se! Eine Bereicherung!

  50. @Andreas: Anker wer­den häu­fig auch bei JavaScript-Tabs genutzt, um z.B. über die URL einen bestimm­ten Tab direkt “anzu­sprin­gen”. Anker sind IMHO alles ande­re als ver­al­tet, im Gegenteil.

  51. Ist noch nie­man­den der lus­ti­ge Tippfehler auf­ge­fal­len?

    Erkläuterung

  52. Sehr nütz­lich sind da auch die plugins
    jQuery.LocalScroll
    jQuery.SerialScroll

    http://flesler.blogspot.com/2007/10/jqueryscrollto.html

    Da sieht es so aus, dass wenn du den “body” zu einem Element scrol­len willst:
    $.scrollTo($(ziel), 800);

  53. @Jens:

    Der Vorteil von “bind” ist, dass du dem Element einen Event-Handler anhängst. Der Unterschied ist also, dass du mit einem jque­ry-plugin – was man für die­sen Zweck schrei­ben könn­te – nicht die vom User des Plugins even­tu­ell an ande­rer Stelle bereits per “click()” defi­nier­ten Funktionen über­schreibt, son­dern das neue Verhalten ein­fach “anhängt”. Ganz gut zu sehen ist das mit window.onload: Wenn jeder Javascript ent­wick­ler die window.onload-Funktion mit sei­ner eige­nen Funktion bele­gen wür­de, wäre ein “Gerangel” vor­pro­gram­miert. Darum anstel­le von “window.onload=function() { … }” ein­fach

    window.addEventListener(“load”, fnc1, fal­se);
    window.addEventListener(“load”, fnc2, fal­se);

    (gut beschrie­ben hier: http://www.mediaevent.de/javascript/event_listener.html).

    Hoffe, das­ses ver­ständ­lich ist;).

    lg

  54. Schön erklärt, dan­ke! Ich mag die­se Usability-Verbesserung.

    Was spricht dage­gen, anstatt bind() das eben­so exis­ten­te click() zu neh­men? Das erscheint mir kür­zer. Oder ist bind() per­for­man­ter?

  55. Besonders schön ist, dass das gan­ze unobstrusiv funk­tio­niert, der Benutzer mit aus­ge­schal­te­tem Javascript also von dem gan­zen Spaß gar­nix mit­be­kommt und der Sprung dann eben nicht mehr “smooth” son­dern so wie gewohnt – in einem Rutsch – ver­läuft. So soll­te Javascript auch immer zum Einsatz kom­men: Als “Aufhübscher” und Accessibility ver­bes­se­ren­der Faktor, der aber nie­mals für eine Benutzung essen­ti­ell ist.

  56. Sehe ich auch durch­aus posi­tiv!
    Eines der weni­gen Gimmicks mit hohem Wert für die Usability.
    Eigentlich soll­te das fast schon ein Standard-Browser-Verhalten sein.

  57. Tja, ent­we­der Paging oder Scrolling. Jedes Prinzip hat sei­ne Vor- und Nachteile. Ich fin­de über­flüs­si­ge Klickerei (Paging) ner­vig. Ob die User sich an den sanf­ten Scrolllauf gewöh­nen? Hier gibts auch noch die »har­te« Lösung.

  58. Ich dach­te bis­her eigent­lich, exzes­si­ve Ankernutzung inner­halb einer Seite sei so lang­sam aus der Mode, weil man oft bes­ser sol­che Inhalte auf meh­re­re Seiten auf­teilt.

  59. In mei­nen Augen ist dies eine sinn­vol­le Ergänzung. Wikipedia nutzt die­se Funktion gele­gent­lich auch. Ich als Anwender kann so genau­er auf einen Bereich ver­wei­sen.

Schreibe einen Kommentar zu NightWalker Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.