Nico R.: Browser-Erfrierung in ResizeObserver

Hallo zusammen,

ich überwache das Resizen eines Elements bzw. des Screens und möchte - je nachdem, ob es im Quer- oder Hochformat dargestellt wird - eine Klasse einbinden. Nur leider zittert das ganze beim Ändern des Browserfenster (mit eingeblendeten Developer Tools) furchtbar herum, der Observer macht sich anscheinend fest. Oder liegt es an etwas anderem? Hier das betreffende JS-Problemstück:

const observer = new ResizeObserver(entries => {
  entries.forEach(entry => {
    let width = entry.contentRect.width;
    let height = entry.contentRect.height;
    let neu = (height > width) ? "hoch" : "quer";			

    if(neu != ausrichtung) {
      console.log(neu);
      // Problemteil: /////////////////////////////////
      img.classList.remove("hoch", "quer");
      /////////////////////////////////////////////////
      img.classList.add(neu);
      ausrichtung = neu;
    }
  });
});

Es sollen also bei jeder "Lageänderung" (auf Mobilgeräten) erst einmal die Klasse "hoch" und "quer" entfernt und dann, je nach Lage, neu gesetzt werden. Aber damit kommt der Observer offenbar nicht klar. Ich habe, um einen anderen Fehler auszuschließen, das Klassenaustauschen (das ja eigentlich nichts besonderes ist) sicherheitshalber mal mit diesem Script getestet, da friert nichts ein:

figure.addEventListener("click", function() {
  let neu = Math.floor(Math.random() * 2);
  const arr = ["hoch", "quer"];

  if(neu != ausrichtung) {
    console.log(neu);
    img.classList.remove("hoch", "quer");
    img.classList.add(arr[neu]);
    ausrichtung = neu;
  }			
});

Meine Frage war ursprünglich eigentlich eine andere (die folgt, dann hoffentlich in Kürze). Jetzt muss ich mich erst einmal um dieses unvorhergesehene Problem kümmern. Hier liegt das komplette Testscript. Aber Vorsicht! Der Oberserver zittert wie gesagt beim Verschieben ins Hochformat, also keinen Schreck kriegen :-)

https://fsv-optik.de/tests/test_img.html

Vielleicht hat ja jemand eine Idee.

Gute Nacht

  1. Lieber Nico,

    vermutlich feuert Dein Observer dermaßen oft beim aktiven Resizing, dass der Browser vor lauter Abarbeiten einen Stau erzeugt, der sich Dir als Einfrieren darstellt. Du suchst nach einer Lösung, die viele Aufrufe zusammenfasst.

    Liebe Grüße

    Felix Riesterer

    1. @@Felix Riesterer

      Du suchst nach einer Lösung, die viele Aufrufe zusammenfasst.

      Nein. Er sucht nach einer Lösung, die gar nicht erst viele Aufrufe erzeugt.

      Kwakoni Yiquan

      --
      Ad astra per aspera
  2. Servus!

    Hallo zusammen,

    ich überwache das Resizen eines Elements bzw. des Screens und möchte - je nachdem, ob es im Quer- oder Hochformat dargestellt wird - eine Klasse einbinden. Nur leider zittert das ganze beim Ändern des Browserfenster (mit eingeblendeten Developer Tools) furchtbar herum, der Observer macht sich anscheinend fest.

    JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren

    Dort steht, warum ein resizeObserver oft die falsche Wahl ist.

    Du willst ja nur 2 Zustände abfragen. So etwas klappt mit Window.matchMedia():

    Medienabfragen_mit_matchMedia

    Herzliche Grüße

    Matthias Scharwies

    --
    Was ist eine Signatur?
    1. @@Matthias Scharwies

      JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren

      Dort steht, warum ein resizeObserver oft die falsche Wahl ist.

      Steht dort auch, warum JavaScript oft die falsche Wahl ist?

      Kwakoni Yiquan

      --
      Ad astra per aspera
      1. Servus!

        @@Matthias Scharwies

        JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren

        Dort steht, warum ein resizeObserver oft die falsche Wahl ist.

        Steht dort auch, warum JavaScript oft die falsche Wahl ist?

        Ei freilich: JavaScript und CSS

        Bis nach unten scrollen:

        Bevor du die verschiedenen Möglichkeiten kennenlernst, wie man CSS-Formatierungen durch JavaScript verändern kann, solltest du dir die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.

        • HTML ist für die Strukturierung der Inhalte zuständig. … …

        Herzliche Grüße

        Matthias Scharwies

        --
        Was ist eine Signatur?
        1. @@Matthias Scharwies

          Bevor du die verschiedenen Möglichkeiten kennenlernst, wie man CSS-Formatierungen durch JavaScript verändern kann, solltest du dir die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.

          Es ging hier nicht um unobtrusive JavaScript, sondern um gar kein JavaScript.

          • HTML ist für die Strukturierung der Inhalte zuständig. …

          Eben. „Das picture-Element ist ein Container-Element für ein img-Kindelement, das zusätzlich verschiedene Bildvarianten anzeigen kann.“

          Steht auch im Wiki, Hervorhebung von mir.

          Kwakoni Yiquan

          --
          Ad astra per aspera
  3. @@Nico R.

    ich überwache das Resizen eines Elements bzw. des Screens

    Ja, was denn nun?

    In dem Teil des Code, den du hier nicht gezeigt hattest:

    const figure = document.getElementById("figure");
    
    observer.observe(figure);
    

    Aha: eines Elements.

    Es sollen also bei jeder "Lageänderung" (auf Mobilgeräten)

    Äh, warum überwachst du ein Element, wenn dich der Screen interessiert?

    Aber damit kommt der Observer offenbar nicht klar.

    Wie soll er auch? Wenn die Bedingung height > width erfüllt ist, schaltest du was um, sodass die Bedingung nicht mehr erfüllt ist, sodass wieder umgeschaltet wird, woraufhin die Bedingung wieder erfüllt ist, also wieder umgeschaltet wird, sodass …

    Vielleicht hat ja jemand eine Idee.

    Wenn dich die Orientierung des Bildschirms interessiert, solltest du nicht die Größe irgendeines Elements überwachen.

    Aber auch nicht die des Screens mit ResizeObserver.

    Wenn dich die Orientierung des Bildschirms eines Mobilgeräts interessiert, interessiert dich die Orientierung des Bildschirms.

    Und bei deren Änderung interessiert dich deren Änderung.

    Oder interessiert dich gar nicht die Orientierung des Bildschirms eines Mobilgeräts? Sondern auch die bei Desktopgeräten, die auch beim Handtuchformat landscape-primary ist? ☞ Testseite

    Aber wozu überhaupt das JavaScript??[1]

    Was willst du erreichen, was mit orientation media query und picture-Element nicht zu erreichen wäre?

    Mir schwant, du willst genau das dort im Beispiel Gezeigte.

    Kwakoni Yiquan

    --
    Ad astra per aspera

    1. Nein, multiple Fragezeichen sind kein Ausdruck eines kranken Geistes. Und falls doch, dann nicht meines. 😝 ↩︎

    1. Dieser Beitrag wurde gelöscht: Beitrag ist Spam.
    2. Hallo Gunnar (und alle anderen),

      ich antworte mal nur hier, da hier der entscheidende Hinweis war.

      Wie soll er auch? Wenn die Bedingung height > width erfüllt ist, schaltest du was um, sodass die Bedingung nicht mehr erfüllt ist, sodass wieder umgeschaltet wird, woraufhin die Bedingung wieder erfüllt ist, also wieder umgeschaltet wird, sodass …

      Ich hatte nicht auf dem Schirm, dass meine Klassenumschaltung ja Einfluss auf das Objekt hatte, dass ich überwacht habe. Mannomann...

      Aber wozu überhaupt das JavaScript??[^1]

      Was willst du erreichen, was mit orientation media query und picture-Element nicht zu erreichen wäre?

      Mir schwant, du willst genau das dort im Beispiel Gezeigte.

      Nicht genau das gezeigte. Aber die Erkennung Landscape/Portrait, die ich kompliziert mit JS zurechtwürgen wollte, funktioniert damit hervorragend :-)

      Damit können wir sogar schon zu meinem eigentlichen Problem kommen. Und zwar suche ich im Prinzip eine equivalente Funktion von background-size: contain für img. Ich möchte also, dass der (Handy-)Bildschirm immer optimal ausgenutzt wird. Das hab ich mit diesem CSS-Fragment versucht nachzubilden:

      @media (orientation: portrait) {	
        img {
          max-width: 100%;
          height: auto;
        }
      }
      @media (orientation: landscape) {			
        img {
          width: auto;
          max-height: 100%;
        }
      }
      

      Aber man kann offenbar nur die width eines img mit Prozent beeinflussen. Für height funktioniert das nur, wenn ich px eintrage (da müsste dann wieder JS ran). object-fit: contain hatte ebenfalls keinen Einfluss. Hab ich das falsch angewendet?

      Hier mal der neue Test plus Quelltext:

      https://fsv-optik.de/tests/test_img_media.html

       <!DOCTYPE html>
      <html>
      	<head>
      		<meta charset="utf-8">
      		<style>
      			img {
      				object-fit: contain;
      			}
      			@media (orientation: portrait) {	
      			img {
      				max-width: 100%;
      				height: auto;
      			}
      			}
      			@media (orientation: landscape) {			
      			img {
      				width: auto;
      				max-height: 100%;
      			}
      			}
      		</style>
      	</head>
      	
      	<body>
      		<picture>
      			<img src="test_img_media.jpg">
      		</picture>
      	</body>
      
      </html>	
      

      Schöne Grüße

      Nico

      1. Danke erstmal noch für eure Hilfe. Ich werde sobald ich Zeit habe, zu meinem Problem nochmal weiter testen und gegebenenfalls nochmal einen neuen Beitrag schreiben.

        Schöne Grüße

        Nico

      2. @@Nico R.

        Aber man kann offenbar nur die width eines img mit Prozent beeinflussen. Für height funktioniert das nur, wenn ich px eintrage (da müsste dann wieder JS ran).

        Nö, es gibt Einheiten, die sich auf die Viewporthöhe beziehen.

        dvh sollte die passende sein: Codepen 🐘 🦒

        Oder wegen der Note doch besser svh?

        Kwakoni Yiquan

        --
        Ad astra per aspera
        1. Hallo Gunnar,

          danke für den Hinweis. Ich benutze vh ja auch schon in einigen anderen Fällen. Im Zusammenhang mit einem img ist es mir aber irgendwie nicht in den Sinn gekommen.

          In jedem Fall funktioniert das, was ich wollte, offensichtlich (wenn ich nichts übersehen habe) mit dieser simplen Angabe:

          img {
          	max-width: 100%;
          	max-height: 100vh;
          }
          

          Je nach Viewport wird das Bild entweder in der kompletten Breite oder der kompletten Höhe angezeigt, im Prinzip also ein Verhalten wie bei background-size: contain. Es ist anscheindend weder ein @media (orientation) und schon gar kein ResizeObserver nötig.

          Schöne Grüße

          Nico