kybela: scrollIntoView() geht mit Firefox/IE, aber nicht mit Chrome

Der Browser soll zum Element mit der id="a1" springen. Firefox und IE klappt, Chrome nicht. Warum nicht?

Denn Chrome soll seit v29 klappen (ich hab v72):

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView


<br> <!-- hunderte br -->

<b id="a1" />a1</b>

<script>
var foo = document.getElementById('a1');
foo.scrollIntoView();
</script>
  1. Tach!

    Der Browser soll zum Element mit der id="a1" springen. Firefox und IE klappt, Chrome nicht. Warum nicht?

    Das kann ich dir ganz genau sagen: Es liegt an der Ursache. 😉

    Welches allerdings die Ursache ist, kann ich dir nicht sagen, denn bei mir tut dein Codeausschnitt was er soll. Aber vielleicht sagt dir der Chrome selbst etwas hilfreicheres, was in deinem Fall nicht passt. Schau mal in die Console der Entwicklertools. Die sollte man beim Entwickeln immer geöffnet haben, schon um angezeigte Fehlermeldungen nicht zu übersehen.

    Dein Code ist nicht Javascript sondern HTML mit eingebettetem Javascript. Wenn der Syntaxhighlighter des Forum das korrekt auszeichnen soll, muss man bei verschachtelten Dingen immer die Sprache angeben, die außen liegt, hier also HTML.

    <b id="a1" />a1</b>
    

    Das sieht defekt aus. Das erste b-Element schließt sich selbst. Vielleicht hast du noch andere Syntaxfehler in deiner Seite, die die Browser unterschiedlich interpretieren.

    dedlfix.

    1. Der b Tag wird jetzt richtig geschlossen: Keine Änderung. Ich hab jetzt auch Edge probiert: klappt.

      Hier das Sample online (nur ein paar <br> mehr und 1 console.log("fertig") hinzugefügt):

      http://wilmaed.bplaced.net/scrollIntoView.html

      Die Konsole im Chrome bringt kein Error/Warning. nur einmal die Meldung console.log("fertig") Das JavaScript wird also ausgeführt ...

      1. @@kybela

        http://wilmaed.bplaced.net/scrollIntoView.html

        Bitte das nächste Mal selbst als Link auszeichnen, danke.

        Bei mir (MacOS) kein Unterschied zwischen Firefox und Chrome, beide scrollen ans Ende.

        Wofür brauchst du das eigenlich? Warum nicht mit Anker http://wilmaed.bplaced.net/scrollIntoView.html#a1?

        LLAP 🖖

        --
        „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
      2. Tach!

        Hier das Sample online (nur ein paar <br> mehr und 1 console.log("fertig") hinzugefügt):

        http://wilmaed.bplaced.net/scrollIntoView.html

        Die Konsole im Chrome bringt kein Error/Warning. nur einmal die Meldung console.log("fertig") Das JavaScript wird also ausgeführt ...

        Ja, sieht soweit in Ordnung aus. Der Chrome springt auch bei mir wie gewünscht zum Anker, allerdings nur einmal beim Aufrufen der Seite in einem neuen Tab. Bei Reloads passiert nichts mehr, die Ansicht bleibt an der Stelle, zu der man sich händisch bewegt hat. Lösung dafür kenne ich keine.

        dedlfix.

        1. Hallo dedlfix,

          ich habe mal einen Button oben auf eine Seite gesetzt, in Reaktion auf click funktioniert scrollIntoView.

          Was auch geht, ist ein Verschieben in den nächsten Makrotask (Wasn das?)

          setTimeout(function () {
             document.getElementById("foo").scrollIntoView();
          }, 0);
          

          Das bewirkt, dass der scrollIntoView-Aufruf nicht im gleichen Umlauf der Eventqueue ausgeführt wird, sondern erst im nächsten (oder noch später, je nach Inhalt der Queue).

          Ein Mikrotask (z.B. Promise.resolve().then() reicht nicht. Offenbar unterdrückt der Browser während des Events, das den Refresh behandelt, Seitenpositionierungen. Meine Annahme wäre, dass man damit Ruckeln vermeiden will.

          Rolf

          --
          sumpsi - posui - clusi
          1. Tach!

            Ein Mikrotask (z.B. Promise.resolve().then() reicht nicht.

            Bei einem sofort erfüllten Promise wird wohl auch ein direkt danach ausgeführtes then() sofort ausgeführt werden, so dass die Eventqueue gar nicht zum Zuge kommt.

            dedlfix.

            1. Hallo dedlfix,

              Bei einem sofort erfüllten Promise wird wohl auch ein direkt danach ausgeführtes then() sofort ausgeführt werden

              Das habe ich auch mal geglaubt, aber es stimmt nicht. Der then-Callback ist immer asynchron und wird als Microtask ausgeführt (d.h. sobald der JavaScript-Stack leer ist - das ist nicht das gleiche wie „fertig mit dem aktuellen Event“). Das ist auch gut so, denn andernfalls wäre die Ausführungsreihenfolge deines Codes ggf. vom Timing des Promise-Callback abhängig, und das wäre ganz schwer zu testen.

              Hast Du den verlinkten Blog-Beitrag von Jake Archibald angeschaut? Da ist ein sehr schönes Beispiel (abgesehen von der Tatsache dass er ein div click-able macht).

              Kleineres Beispiel:

              function logValue(v) { console.log("logging " + v); }
              
              console.log("Promise 1");
              Promise.resolve(1).then(logValue);
              
              console.log("Promise 2");
              new Promise((good,bad) => 
                    good(2))
              .then(logValue);
              
              console.log("Promise 3");
              new Promise((good,bad) => 
                   setTimeout(() => { logValue(3000); good(3); }, 1000) )
              .then(logValue);
              
              console.log("Fertig!");
              

              Die Ausgabe in einem Spec-konformen Browser ist:

              Promise 1, Promise 2, Promise 3, Fertig!, logging1, logging 2, (kurze Pause), logging 3000, logging 3

              Einige ältere Browser sind nicht Spec-konform, die machen das ggf. nicht richtig. Jake Archibald hat in seinem Blog Chrome, FF, Safari und Edge verglichen, und alle außer Chrome waren falsch. Der Blog ist aber schon 2 Jahre alt, die heutigen Versionen von FF und Edge machen es richtig (gestern Abend getestet). Safari habe ich nicht da.

              Rolf

              --
              sumpsi - posui - clusi