Das Wort "responsive" wird heutzutage in der Webentwicklung nicht mehr so oft erwähnt, es ist bereits ein Standard. Es gibt eine große und ständig wachsende Vielfalt an Bildschirmen. Wir möchten in der Lage sein, alle möglichen Größen zu unterstützen und trotzdem ein gutes Benutzererlebnis zu gewährleisten. Und CSS Media-Queries sind eine großartige Lösung für diese Herausforderung. Aber wie sieht es mit responsiven Komponenten aus? Bei der modernen Webentwicklung geht es um Komponenten, und wir brauchen eine Möglichkeit, sie ebenfalls responsiv zu machen. Heute möchte ich über die ResizeObserver API sprechen, ein neues leistungsfähiges Tool für Responsive Web, das im Gegensatz zu Media-Queries eine Größenänderung eines bestimmten Elements und nicht eines ganzen Viewports erkennt.
Eine kurze Geschichte
In der Vergangenheit gab es nur media queries- eine CSS-Lösung, die auf einer Mediengröße, einem Medientyp oder einer Medienbildschirmauflösung basiert (mit Medien meinen wir Desktop, Telefon oder Tablet). Medienabfragen sind flexibel und einfach zu verwenden. Lange Zeit war diese Lösung nur für CSS verfügbar, bis sie über window.matchMedia(mediaQueryString) auch in JS zugänglich wurde. Jetzt können wir sehen, ob das Dokument mit den Medien übereinstimmt und - mehr noch - ein Dokument beobachten, um zu erkennen, wenn sich seine Medienabfragen ändern.
Elementabfragen, wie wäre es damit?
Was uns in unserem Werkzeugkasten noch fehlt, ist eine Möglichkeit, Größenänderungen an einem einzelnen DOM-Element zu erkennen, nicht an einem Viewport. Die Entwickler sprechen schon seit Jahren über dieses Tool. Es ist eine der am häufigsten gewünschten Funktionen. Und es gibt sogar einen Vorschlag aus dem Jahr 2015 - Container-Abfragen:
In einem komplexen responsiven Layout benötigen Entwickler oft eine granulare Kontrolle über die Gestaltung von Elementen in Bezug auf die Größe ihres übergeordneten Containers und nicht auf die Größe des Ansichtsfensters. Mithilfe von Container-Abfragen kann ein Autor das Styling anhand der Größe eines enthaltenen Elements und nicht anhand der Größe des Ansichtsfensters des Benutzers steuern. Beispiel für die Verwendung in CSS:
.element:media(min-width: 30em) screen {***}
Klingt großartig, aber leider hatten die Browser einen Grund, mit einer Implementierung zu zögern - zirkuläre Abhängigkeit (wenn ein Größenänderungsereignis ein anderes auslöst, was zu einer Endlosschleife führt; klicken Sie hier, um mehr zu lesen), so dass diese Spezifikation nie zu einem W3C-Entwurf wurde. Was sind also die Optionen? Wir könnten window.resize(callback) verwenden, aber das ist eine teure Lösung - der Callback wird jedes Mal aufgerufen, wenn das Ereignis ausgelöst wird, und wir brauchen immer noch eine Menge Berechnungen, um festzustellen, ob unsere Komponente tatsächlich ihre Größe geändert hat...
Beobachten von Änderungen der Elementgröße mit der ResizeObserver API
Glücklicherweise kommt das Chrome-Team zur Rettung - willkommen ResizeObserver API:
Die ResizeObserver API ist eine Schnittstelle zur Beobachtung von Änderungen der Elementgröße. Sie ist das Gegenstück zum
window.resizeEreignis eines Elements.
Die ResizeObserver API ist ein lebendiger Entwurf. Sie funktioniert bereits in Chrome 64, Firefox und Safari für den Desktop. Die mobile Unterstützung ist weniger charmant - nur Chrome auf Android und Samsung Internet unterstützen sie. Es gibt noch eine weitere schlechte Nachricht: Sie ist nicht 100% polyfillbar. Die verfügbaren Polyfills haben in der Regel Einschränkungen (z. B. langsame Reaktion, keine Unterstützung für verzögerte Übergänge usw.), also seien Sie sich dessen bewusst. Wie auch immer, das sollte uns nicht davon abhalten, es in Aktion zu sehen, also lassen Sie uns das tun!
Beispiel: Ändern Sie den Text eines Elements auf der Grundlage seiner Größe
Betrachten wir die folgende Situation: Der Text innerhalb eines Elements soll sich in Abhängigkeit von der Größe des Elements ändern. Die ResizeObserver API bietet uns zwei Schnittstellen - ResizeObserver und ResizeObserverEntry. Die Schnittstelle ResizeObserver wird verwendet, um Änderungen der Größe eines Elements zu beobachten, und ResizeObserverEntry beschreibt ein Element, dessen Größe geändert wurde. Der Code ist sehr einfach (die klickbare Version hier):
<h1> 😊😊😊 </h1>
<h2> boring text </h2>
var ro = new ResizeObserver( entries => {
for (let entry of entries) {
const width = entry.contentBoxSize ? entry.contentBoxSize.inlineSize : entry.contentRect.width;
if (entry.target.tagName === 'H1') {
entry.target.textContent = width < 1000 ? '😱😱😱' : '😊😊😊';
}
if (entry.target.tagName === 'H2' && width < 500) {
entry.target.textContent = 'I won"t change anymore';
ro.unobserve(entry.target); // stop observing this element when it's size will reach 500px
}
}
});
// we can add more than one element to observe
ro.observe(document.querySelector("h1"));
ro.observe(document.querySelector("h2"));
Wir haben ein ResizeObserver Objekt erstellt und seinem Konstruktor einen Callback übergeben:
const resizeObserver = new ResizeObserver((entries, observer) => {
for (let entry of entries) {
// check entry dimensions and perform needed logic
}
})
Diese Funktion wird immer dann aufgerufen, wenn eines der Zielelemente, ResizeObserverEntries, seine Größe ändert. Der zweite Parameter der Callback-Funktion ist ein
Der Callback erhält ein Array von ResizeObserverEntry. Jeder Eintrag enthält neue Dimensionen für das beobachtete Element und das Element selbst (target).
for (let entry of entries) {
const width = entry.contentBoxSize ? entry.contentBoxSize.inlineSize : entry.contentRect.width;
if (entry.target.tagName === 'H1') {
entry.target.textContent = width < 1000 ? '😱😱😱' : '😊😊😊';
}
...
}
Es gibt drei Eigenschaften, die neue Dimensionen des Elements beschreiben - borderBoxSize, contentBoxSize und contentRect. Sie stellen ein Box-Modell eines Elements dar, auf das wir gleich näher eingehen werden. Zunächst einmal ein paar Worte zur Unterstützung. Ich sehe vor allem die Verwendung der Eigenschaft contentRect, da sie von allen Browsern am besten unterstützt wird:
contentRectstammt aus der Inkubationsphase von ResizeObserver und ist nur aus Gründen der aktuellen Webkompatibilität enthalten. Sie kann in zukünftigen Versionen veraltet sein.
Ich würde daher empfehlen, borderBoxSize oder contentBoxSize mit einem Fallback auf contentRect zu verwenden. Die Schnittstelle ResizeObserverSize bietet zwei Eigenschaften: inlineSize und blockSize, die Sie als width und height lesen können (vorausgesetzt, wir arbeiten in horizontaler writing-mode).
Ein Element beobachten
Der letzte Schritt besteht darin, die Beobachtung eines Elements tatsächlich zu starten. Dazu rufen wir ResizeObserver.observe() auf, das unser Element als neues Ziel zur Liste der beobachteten Elemente hinzufügt. Wir können entweder ein Element oder mehrere übergeben:
// resizeObserver.observe(target, options);
ro.observe(document.querySelector("h1"));
ro.observe(document.querySelector("h2"));
Der zweite Parameter, options, ist optional. Derzeit ist nur die Option content-box (Standard), border-box und device-pixel-content-box(nur für Chrome). Sie können nur ein Feld pro Beobachter beobachten, so dass Sie mehrere ResizeObserver verwenden müssen, wenn Sie mehrere Felder für dasselbe Element beobachten möchten.
Um die Beobachtung eines bestimmten Elements zu beenden, können wir ResizeObserver.unobserve(target) verwenden. Um die Beobachtung aller Ziele zu beenden, verwenden Sie ResizeObserver.disconnect().
Unterschied zwischen Box-Modellen
Der Inhaltsrahmen ist der Rahmen mit dem Inhalt, ohne Auffüllungen, Rahmen und Ränder. Das Rahmenfeld hingegen enthält Auffüllungen und eine Rahmenbreite, aber noch keine Ränder:

Gerätepixel-Inhaltsfeld ist ein Inhaltsfeld für ein Element in Gerätepixeln. Ich habe die Verwendung dieser Option noch nicht gesehen, aber es scheint, dass sie für ein Canvas-Element nützlich sein kann. Es gibt eine interessante Diskussion auf Github darüber, wenn Sie mehr darüber erfahren möchten, wo und warum sie verwendet werden kann.
Wann wird ein Beobachter über Änderungen informiert?
Der Callback wird immer dann ausgelöst, wenn das Zielelement seine Größe ändert. Die Spezifikation enthält die folgenden Informationen dazu:
- Die Beobachtung wird ausgelöst, wenn das beobachtete Element in das DOM eingefügt oder aus dem DOM entfernt wird;
- Die Beobachtung wird ausgelöst, wenn die Anzeige des überwachten Elements auf none gesetzt wird;
- Beobachtungen werden nicht für nicht-ersetzte Inline-Elemente ausgelöst;
- Die Beobachtungen werden nicht durch CSS-Transformationen ausgelöst;
- Die Beobachtung wird ausgelöst, wenn die Beobachtung beginnt, das Element gerendert wird und die Größe des Elements nicht 0,0 ist.
Was den ersten Punkt betrifft, so können wir jetzt die Änderung der Größe des übergeordneten Containers erkennen, wenn sich seine Kinder geändert haben. Ein schönes Beispiel dafür ist das Scrollen zum unteren Rand des Chatfensters, wenn eine neue Nachricht hinzugefügt wird. Mit ResizeObsever ist das ganz einfach! Sehen Sie hier ein Beispiel.
Erinnern Sie sich noch an den Vorschlag für Elementabfragen, den ich bereits erwähnt habe? Und das Problem der zirkulären Abhängigkeiten? Die ResizeObserver API hat eine eingebaute Lösung, um Endlosschleifen bei der Größenänderung zu verhindern. Klicken Sie hier, um alles darüber zu lesen.
Nun gut, ich hoffe, Sie sind begeistert von der Arbeit mit der ResizeObserver API! Danke, dass Sie mir bis zu diesen Worten gefolgt sind ❤ Viel Spaß und viel Erfolg beim Programmieren!
Nützliche Links:
- Spezifikation;
- MDN-Dokumentation der ResizeObserver API.
- CanIUse;
- Der erste Artikel/die erste Ankündigung des Chrome-Teams;
- Der zuverlässigste Polyfill;
- Vorschlag für Elementabfragen erklärt.
Verfasst von
Khrystyna Skvarok
Contact



