Gunnar Bittersmann: Yet another IntersectionObserver mystery

problematische Seite

Ich habe einen Prototypen Codepen mit spread syntax gebastelt: unten ein fixed positioniertes Element (Überschrift „Allgemeine Erklärung der Menschenrechte“), das verschwinden soll, wenn andere Elemente in den Viewport scrollen (die Box zum Logo für Menschen­rechte und die Infobox darunter). Wobei diese Boxen nicht auftreten müssen. Ein Array observedElements der zu beobachtenden Elemente erstellt und einen IntersectionObserver drauf angesetzt:

observer.observe(...observedElements);

Funktioniert – im Prototypen. In the real thing (eine Vue-Anwendung) eingebaut – funktioniert nicht.

Anstelle der spread syntax eine Schleife über die zu beobachtenden Elemente, wie auch im Beispiel in MDN gezeigt:

observedElements.forEach(observedElement => {
	observer.observe(observedElement);
});

Codepen mit forEach loop – und so funktioniert’s dann auch in der Vue-Anwendung.

Warum funktioniert die spread syntax nicht in der Vue-Anwendung? (Ja, das mag für euch schwer zu beantworten sein, ohne die Anwendung zu sehen.)

Warum funktioniert die spread syntax im Prototypen?

Kwakoni Yiquan

--
Ad astra per aspera
  1. problematische Seite

    Hallo Gunnar,

    Im Codepen funktioniert es doch auch nicht. Mach den Darstellungsbereich mal niedriger als den Footer. Sobald der aside rausrollt, erscheint die Überschrift wieder. Frage ist aber, ob das ein relevanter Usecase ist, ein solcher Viewport ist schon sehr klein.

    Warum?

    Vue ist Typescript, vielleicht greift da der TS-Precompiler ein, weil er die Methodensignatur von observe besser kennt als Du? Oder Du hast TypeScript auf IE-Kompatibilität eingestellt und er zermaggelt das irgendwie? Dazu müsstest Du gucken, was Typescript Dir ausspuckt.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. problematische Seite

      @@Rolf B

      Du hast dein Posting editiert‽ Gut, dass ich die ursprüngliche Version noch auf dem Schirm hatte, wo da stand

      Bzw. in Codepen solltest Du schauen, ob er mehr als den ersten Arrayeintrag observiert.

      Geschaut. Mal die Reihenfolge im Array zu [footerElement, asideElement] geändert. Bei spread syntax scrollt nun das asideElement durch, die Überschrift verschwindet erst, wenn das footerElement kommt. Es wird also tatsächlich nur das erste Array-Element observiert.

      Bei der Schleife ist das natürlich nicht der Fall. Die Reihenfolge im Array spielt keine Rolle, alle Array-Elemente werden observiert.

      Spread syntax ist also falsch. Keine Ahnung, wie ich auf den Gedanken kam.

      Was aber noch nicht erklärt, warum im Codepen das erste Array-Element observiert wird, in der Vue-Anwendung aber nicht. Oder doch:

      Vue ist Typescript, vielleicht greift da der TS-Precompiler ein, weil er die Methodensignatur von observe besser kennt als Du?

      Vue verwendet intern TypeScript, auch wenn wir selbst gewöhnliches JavaScript schreiben?


      Im Codepen funktioniert es doch auch nicht. Mach den Darstellungsbereich mal niedriger als den Footer.

      Oder den Footer höher als den Darstellungsbereich.

      Sobald der aside rausrollt, erscheint die Überschrift wieder. Frage ist aber, ob das ein relevanter Usecase ist, ein solcher Viewport ist schon sehr klein.

      In the real thing können die Elemente durchaus höher werden; also ist es ein relevanter Usecase, da muss ich nochmal ran.

      Geht das dann überhaupt mit IntersectionObserver? Oder muss ich da mit der Scroll-Position ran? 🤔

      Kwakoni Yiquan

      --
      Ad astra per aspera
      1. problematische Seite

        Hallo Gunnar,

        Du hast dein Posting editiert‽

        Ja, weil ich selbst geschaut und die Bestätigung gefunden hatte. Er observiert nur den ersten. Zusammen mit dem Link auf die Spec sollte das dann klar gewesen sein. Ich kann einer Methode, die genau einen Parameter erwartet, jederzeit drölf oder mehr mitgeben, das ist ihr aber völlig einerlei.

        Vue verwendet intern TypeScript, auch wenn wir selbst gewöhnliches JavaScript schreiben?

        Keine Ahnung. Es war eine Hypothese. Ich habe keine Ahnung, ob man als Vue-Nutzer normales JS verwendet - ich weiß nur, dass Vue in TS verbrochen wurde. Musst Du in deinem Original herausfinden.

        Geht das dann überhaupt mit IntersectionObserver?

        Ja. Hast Du doch mit der Schleife herausgefunden. Observiere beide. Oder mach ein div um die beiden - sofern das im Original praktikabel ist - und observiere das.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. problematische Seite

          @@Rolf B

          Ich kann einer Methode, die genau einen Parameter erwartet, jederzeit drölf oder mehr mitgeben, das ist ihr aber völlig einerlei.

          Klingt einleuchtend.

          ich weiß nur, dass Vue in TS verbrochen wurde. Musst Du in deinem Original herausfinden.

          Werde ich vielleicht tun, wenn ich die großen Boxen in Griff habe.

          Geht das dann überhaupt mit IntersectionObserver?

          Ja. Hast Du doch mit der Schleife herausgefunden. Observiere beide. Oder mach ein div um die beiden - sofern das im Original praktikabel ist - und observiere das.

          Wie soll das helfen? Das Problem ist doch, dass isIntersecting nicht mehr true ist, wenn die Oberkante des beobachteten Elements nach oben aus dem Viewport rausscrollt.

          Kwakoni Yiquan

          --
          Ad astra per aspera
          1. problematische Seite

            Hallo Gunnar Bittersmann,

            du beobachtest doch 2. Wenn sich der Status von einem ändert, feuert der Observer. Eventuell bekommst du in einem Aufruf auch beide.

            Mach dir ein Objekt, das den intersecting-Status für beide speichert. Update im Observercallback zuerst die geänderten Status und frage dann ab, ob einer davon true ist. Wenn ja, mach die Überschrift weg. Lässt sich auch für n Elemente generalisieren.

            Oder übersehe ich was und denke zu einfach?

            Rolf

            --
            sumpsi - posui - obstruxi
            1. problematische Seite

              @@Rolf B

              du beobachtest doch 2. Wenn sich der Status von einem ändert, feuert der Observer. Eventuell bekommst du in einem Aufruf auch beide.

              Mach dir ein Objekt, das den intersecting-Status für beide speichert. Update im Observercallback zuerst die geänderten Status und frage dann ab, ob einer davon true ist. Wenn ja, mach die Überschrift weg. Lässt sich auch für n Elemente generalisieren.

              Oder übersehe ich was und denke zu einfach?

              Nö, ich glaube nicht. So denn? final 😉

              Kwakoni Yiquan

              --
              Ad astra per aspera
              1. problematische Seite

                Hallo Gunnar,

                ein simples Schleifen-OR zu empfehlen habe ich mich nicht getraut, weil sich ja immer nur das Element meldet, das sich verändert hat. Es scheint zu funktionieren, aber da muss ich noch nach toxischen Viewportgrößen suchen.

                Rolf

                --
                sumpsi - posui - obstruxi
              2. problematische Seite

                @@Gunnar Bittersmann

                Oder übersehe ich was und denke zu einfach?

                Oder übersehe ich was und denke zu kompliziert?

                Nö, ich glaube nicht. So denn? final 😉

                Nach final kommt final final. (alte Designerweisheit; Entwickler nutzen git)

                Dabei kann es doch so einfach sein: zwei unabhängige IntersectionObserver, die verschiedene Klassen ans auszublendende Element setzen. CSS macht die Veroderung.

                Kwakoni Yiquan

                --
                Ad astra per aspera
                1. problematische Seite

                  Hallo Gunnar,

                  sind zwei Observer mit je einem observe einfacher als ein Observer mit zwei observes und eine entsprechenden Abfrage im Callback? Aus Programmierersicht wahrscheinlich schon, aus Browsersicht würde ich zumindest ein Vorsicht! anmerken wollen.

                  Das verODERn mit CSS hatte ich mir auch schon überlegt. Aber ist es Layout oder Behaviour, wenn die h1 bei Ankunft am Seitenende ausgeblendet wird? Da war ich mir nicht so sicher und habe eher auf Behaviour getippt - also JS.

                  Rolf

                  --
                  sumpsi - posui - obstruxi
                  1. problematische Seite

                    @@Rolf B

                    sind zwei Observer mit je einem observe einfacher als ein Observer mit zwei observes und eine entsprechenden Abfrage im Callback? Aus Programmierersicht wahrscheinlich schon

                    Überraschung! Kollege findet die erste Variante leichter verständlich.

                    aus Browsersicht würde ich zumindest ein Vorsicht! anmerken wollen.

                    Das ist aber Mikro-Optimierung, oder?

                    Das verODERn mit CSS hatte ich mir auch schon überlegt. Aber ist es Layout oder Behaviour, wenn die h1 bei Ankunft am Seitenende ausgeblendet wird? Da war ich mir nicht so sicher und habe eher auf Behaviour getippt - also JS.

                    Kann man auch anders sehen: JavaScript kümmert sich darum, wofür es da ist: um dynamische Änderungen. Element scrollt rein – schlag Alarm! Na, nicht gleich Alarm, sondern mach das im DOM (durch eine Klasse) kenntlich.

                    Wofür das bei der Darstellung im UI verwendet wird, geht JavaScript nichts an.

                    Kwakoni Yiquan

                    --
                    Ad astra per aspera
                    1. problematische Seite

                      @@Gunnar Bittersmann

                      Wofür das bei der Darstellung im UI verwendet wird, geht JavaScript nichts an.

                      Das beißt sich jetzt ein Bisschen mit dem vorher gesagtem „IntersectionObserver, die verschiedene Klassen ans auszublendende Element setzen.“ – wegen „ans auszublendende Element“.

                      Aber nur ein Bisschen. Man könnte die Klassen auch ganz oben ans html-Element (oder body) setzen und das Ding per Nachfahrenselektor ein-/ausblenden. Dann wär’s wirklich entkoppelt.

                      Die Klassen sollten dann freilich nicht obscured-by-footer u.dgl. heißen, sondern footer-scrolled-into-view oder so ähnlich.

                      Kwakoni Yiquan

                      --
                      Ad astra per aspera