Spis treści

Specyfikacja Resize Observer API jest wciąż we wczesnym etapie prac (obecnie w fazie Editor's Draft). Mimo tego aktualna wersja dociera do około 83.7% użytkowników. Bez przeszkód można korzystać z dobrodziejstw tego API w =< Chrome 64, =< Firefox 69 czy =< Safari 13.1. Aktualna lista wsparcia znajduje się na caniuse.

Jeżeli chcesz wspierać większą ilość wersji przeglądarek, możesz skorzystać z polyfilla znajdującego się na GitHubie. Dzięki niemu korzystanie z Resize Observer będzie możliwe nawet na Internet Explorer 9.

Zanim zaczniemy

W tym artykule rzucam wyłącznie światło na tą specyfikację, starając się przy tym zachęcić Cię do zagłębienia się w to API. Przez to nie poruszam wszystkich możliwych zachowań, właściwości oraz metod. Chcąc dowiedzieć się więcej, odsyłam do świetnej dokumentacji znajdującej się na Mozilla Developer Network.

Stwórzmy pierwszego observera

Skoro mamy pogląd na to, czym jest Resize Observer i czy możemy z niego korzystać, zacznijmy od krótkiego omówienia konstruktora. Tworząc nową instancję klasy ResizeObserver, przekazujemy w pierwszym (i jedynym) argumencie callback, który będzie wywoływany za każdym razem, gdy obserwowane elementy zmienią swoje rozmiary.

const callback = (entries, observer) => {
  for (let entry of entries) {
    /* code */
  }
};

const ro = new ResizeObserver(callback);
ro.observe(element);

Metoda callback przyjmie dwa parametry - entries, który zawiera tablicę wszystkich obserwowanych elementów oraz observer, będącym referencją do utworzonej instancji observera.

Box model

Domyślnie callback wywoływany jest wtedy, gdy content box elementu zostanie zmodyfikowany (lub bounding box, jeżeli rozmiar zmienia element SVG). Zachowanie to można zmodyfikować, podając w drugim argumencie metody observe obiekt z konfiguracją, gdzie (podając klucz box) mówimy, dla którego box model respektowane będą zmiany wielkości elementu (domyślną wartością jest content box).

ro.observe(element, {
  box: 'border-box', // border-box or content-box
});

Po więcej informacji na temat box model odsyłam do dokumentacji w serwisie MDN.

Praktyczny przykład

Przygotowałem prosty przykład, żeby pokazać działania klasy Resize Observer. Stworzyłem prosty kontener z tekstem oraz obrazkiem. Dodatkowo dopisałem funkcjonalność, która będzie zmniejszała szerokość kontenera, żeby zaprezentować działanie bez skalowania okna.

Przykład działania Resize Observer

Jak można zauważyć - informacje na temat rozmiarów elementów aktualizują się za każdym razem, gdy element zmieni swój rozmiar. Każda zmiana wykonywana na elementach DOM jest bardzo wydajna, ponieważ Resize Observer wywołuje wszystkie callbacki bezpośrednio po etapie layout, ale jeszcze przed paint. Znaczy to tyle, że nasze zmiany unieważnią tylko etap layout, co jest zdecydowanie mniej kosztowne dla przeglądarki, gdyż zmiana nie wymusza ponownego wyrenderowania strony.

Lista kroków przy renderowaniu pojedyńczej klatki w przeglądarce

Rozmiary pobierane są z obiektu contentRect, który zawiera właściwości interfejsu DOMRectReadOnly. Obiekt ten zawiera właściwości tylko do odczytu i aktualne rozmiary obserwowanego elementu, odpowiadające content box elementu. Trzeba wziąć pod uwagę, że ta właściwość jest pozostałością po wcześniejszej implementacji i może w przyszłości zostać potraktowana jako przestarzała. Obecnie przyjęto w specyfikacji, że aktualne rozmiary będą przechowywane w obiektach borderBoxSize oraz contentBoxSize. Po więcej informacji odsyłam do strony na MDN.

∞ - nieskończone pętle

Zostało jeszcze pytanie: co, jeżeli w callbacku zmienimy rozmiar obserwowanego elementu? Odpowiedź jest prosta: NIC :), a to dlatego, że Resize Observer jest zabezpieczone na taką ewentualność i unika nieskończonych pętli oraz cyklicznych zależności, które mogłyby z tego wyniknąć. Takie zmiany są wykonywane w następnej klatce. Natomiast istnieje wyjątek i obliczenia zostaną wykonane w tej samej klatce, jeżeli zmiana wielkości nastąpiła na elemencie, który znajduje się głębiej w drzewie DOM niż najpłytszy element, przetworzony w poprzednim callbacku.

Słowo na koniec

Mimo tego, że Resize Observer API jest dosyć nową funkcjonalnością w naszych przeglądarkach, to warto już teraz się nią zainteresować. Wspomniany wcześniej polyfill pokryje wszystkie nowoczesne (i także te starsze ;)) przeglądarki, więc już od teraz można korzystać z tego API bez obaw.