ResizeObserver

Wywołuje funkcję za każdym razem, gdy zmieni się rozmiar obserwowanego elementu, bez względu na przyczynę zmiany.

Zwraca
Nowy obiekt ResizeObserver.
Na tej stronie

Przykład

#
JavaScript
const panel = document.querySelector('#panel')

const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const border = Math.round(entry.borderBoxSize[0].inlineSize)
    const content = Math.round(entry.contentRect.width)
    console.log(`Panel: ${border} px, treść: ${content} px`)
  }
})

observer.observe(panel)
Konsola
Panel: 200 px, treść: 174 px

Pierwsze powiadomienie podaje rozmiar zaraz po rozpoczęciu obserwacji. contentRect nie obejmuje dopełnienia i ramki, dlatego jest o 26 px węższy. Przeciągnij prawy dolny róg panelu w podglądzie, a konsola pokaże każdą zmianę.

Definicja i zastosowanie

#

ResizeObserver powiadamia o zmianie rozmiaru konkretnego elementu. Zdarzenie resize na window mówi tylko o zmianie okna, a element może zmienić rozmiar także z innych powodów: po dodaniu treści, zwinięciu panelu bocznego albo zmianie klasy. Obserwator wychwyci każdy z tych przypadków.

Funkcja zwrotna dostaje tablicę obiektów ResizeObserverEntry. Pole contentRect zawiera szerokość i wysokość obszaru treści (bez dopełnienia i ramki), a borderBoxSize i contentBoxSize podają rozmiary jako tablice obiektów z polami inlineSize (szerokość przy zwykłym, poziomym tekście) i blockSize (wysokość).

Jeśli element jest wyświetlony, pierwsze wywołanie nastąpi zaraz po rozpoczęciu obserwacji, więc od razu poznasz aktualny rozmiar. Metoda observe() dodaje element, unobserve() go usuwa, a disconnect() kończy obserwację. Opcja box pozwala wybrać, który rozmiar ma być śledzony, np. { box: "border-box" }.

Uważaj na zmienianie rozmiaru obserwowanego elementu wprost w funkcji zwrotnej. Nowego rozmiaru nie da się już zgłosić w tej samej klatce, więc przeglądarka zgłasza błąd „ResizeObserver loop completed with undelivered notifications”, a powiadomienie przychodzi dopiero w następnej klatce. Takie zmiany od razu odłóż na później, np. przez requestAnimationFrame().

Składnia

#
Składnia
new ResizeObserver(callback)

observer.observe(element)
observer.observe(element, { box })
observer.unobserve(element)
observer.disconnect()

Parametry

#
  • callback

    function (entries, observer)

    Funkcja wywoływana po zmianie rozmiaru. Dostaje tablicę wpisów ResizeObserverEntry.
  • box

    opcjonalny, napis (w observe())

    Który rozmiar śledzić: "content-box" (domyślnie), "border-box" albo "device-pixel-content-box".

Więcej przykładów

#
Układ zależny od szerokości elementu
JavaScript
const card = document.querySelector('#card')
const nextWidths = ['300px', '200px']

const observer = new ResizeObserver(([entry]) => {
  const width = Math.round(entry.borderBoxSize[0].inlineSize)
  card.classList.toggle('wide', width >= 280)
  console.log(`${width} px, szeroki układ: ${card.classList.contains('wide')}`)

  const next = nextWidths.shift()
  if (next) {
    setTimeout(() => {
      card.style.width = next
    })
  }
})

observer.observe(card)
Konsola
200 px, szeroki układ: false
300 px, szeroki układ: true
200 px, szeroki układ: false

Szerokość zmieniamy automatycznie, żeby pokazać kolejne powiadomienia. Każdą zmianę odkładamy przez setTimeout(), bo zmiana rozmiaru wprost w funkcji zwrotnej wywołałaby błąd pętli. W prawdziwej aplikacji rozmiar zmienia się np. po zwinięciu panelu bocznego.

Obsługa przeglądarek

#

Szeroko dostępne · od 2020 roku

Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.

  • Chrome
  • Edge
  • Firefox
  • Safari

Dobre praktyki

#
  • Do reagowania na rozmiar elementu wybieraj ResizeObserver zamiast zdarzenia resize na window. Element może zmienić rozmiar także wtedy, gdy okno ma stały rozmiar.
  • W funkcji zwrotnej nie zmieniaj rozmiaru obserwowanego elementu bezpośrednio. Odłóż zmianę do następnej klatki albo zmieniaj tylko to, co nie wpływa na rozmiar, np. kolor.
  • Jeśli chodzi tylko o dopasowanie stylów do szerokości kontenera, rozważ zapytania kontenera w CSS (@container). Wtedy JavaScript nie jest potrzebny.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.