RidimensionaObservationr: è come document.onresize per gli elementi

ResizeObserver ti informa quando le dimensioni di un elemento cambiano.

Prima del giorno ResizeObserver, dovevi allegare un listener al file resize del documento per ricevere una notifica ogni volta che vengono apportate modifiche alle dimensioni dell'area visibile. Nell'evento , dovresti quindi capire quali elementi sono stati influenzati che cambiano e chiamano una routine specifica per reagire in modo appropriato. Se avevi bisogno le nuove dimensioni di un elemento dopo il ridimensionamento, getBoundingClientRect() o getComputedStyle(), che possono causare layout eseguire il thrashing se non ti occupi di raggruppare tutte le tue letture e tutte scrive.

Ciò non riguardava nemmeno i casi in cui gli elementi cambiavano le loro dimensioni senza finestra è stata ridimensionata. Ad esempio, aggiungere nuovi elementi secondari, impostare stile display dell'elemento in none o azioni simili possono modificare la dimensione un elemento, i suoi fratelli o sorelle o i suoi predecessori.

Questo è il motivo per cui ResizeObserver è un elemento primitivo utile. Reagisce ai cambiamenti dimensioni di qualsiasi elemento osservato, indipendentemente da ciò che ha causato il cambiamento. Fornisce anche accesso alle nuove dimensioni degli elementi osservati.

Supporto dei browser

  • Chrome: 64.
  • Edge: 79.
  • Firefox: 69.
  • Safari: 13.1.

Origine

API

Tutte le API con il suffisso Observer sopra menzionato condividono un'API semplice la progettazione. ResizeObserver non fa eccezione. Crei un oggetto ResizeObserver e passiamo un callback al costruttore. Il callback viene passato un array di ResizeObserverEntry oggetti, una voce per elemento osservato, che contiene le nuove dimensioni dell'elemento.

var ro = new ResizeObserver(entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;

    console.log('Element:', entry.target);
    console.log(`Element size: ${cr.width}px x ${cr.height}px`);
    console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
  }
});

// Observe one or multiple elements
ro.observe(someElement);

Alcuni dettagli

Che cosa viene segnalato?

In genere, un ResizeObserverEntry segnala il riquadro dei contenuti di un elemento tramite una proprietà denominata contentRect, che restituisce un DOMRectReadOnly . La casella dei contenuti è la casella in cui è possibile inserire i contenuti. È la casella di bordo meno la spaziatura interna.

Diagramma del modello box CSS.

È importante notare che, anche se ResizeObserver genera report su entrambe le dimensioni di contentRect e della spaziatura interna, guarda solo contentRect. Non confondere contentRect con il riquadro di delimitazione dell'elemento. I limiti come riportato da getBoundingClientRect(), è la casella che contiene l'intero elemento e i suoi discendenti. Gli SVG costituiscono un'eccezione alla regola, nel senso che ResizeObserver segnalerà le dimensioni del riquadro di delimitazione.

A partire da Chrome 84, ResizeObserverEntry ha tre nuove proprietà per fornire più informazioni informazioni dettagliate. Ognuna di queste proprietà restituisce un ResizeObserverSize contenente una proprietà blockSize e una proprietà inlineSize. Questo Le informazioni riguardano l'elemento osservato nel momento in cui viene richiamato il callback.

  • borderBoxSize
  • contentBoxSize
  • devicePixelContentBoxSize

Tutti questi elementi restituiscono array di sola lettura perché in futuro si spera che possono supportare elementi con più frammenti, che si trovano in o scenari a più colonne. Per ora, questi array contengono un solo elemento.

Il supporto della piattaforma per queste proprietà è limitato, ma l'utilizzo di Firefox è già supportato supporta i primi due.

Quando viene segnalato?

La specifica prevede che ResizeObserver debba elaborare tutti gli eventi di ridimensionamento prima del disegno e dopo il layout. In questo modo il callback di un ResizeObserver il punto ideale in cui apportare modifiche al layout della pagina. Perché ResizeObserver l'elaborazione avviene tra il layout e la colorazione; in questo modo, del layout, non di colorare.

Ecco

Forse ti starai chiedendo cosa succede se modifico le dimensioni di un all'interno del callback per ResizeObserver? La risposta è: attiverai immediatamente un'altra chiamata al callback. Fortunatamente, ResizeObserver ha per evitare loop di callback infiniti e dipendenze cicliche. Le modifiche possono essere elaborati nello stesso frame solo se l'elemento ridimensionato si trova a una posizione più interna nel DOM rispetto all'elemento shallowest elaborato nel callback precedente. In caso contrario, verranno differiti al frame successivo.

Applicazione

Una cosa che ResizeObserver consente di implementare è implementare query supporti. Osservando gli elementi, puoi definire in modo imperativo il tuo progettare punti di interruzione e modificare lo stile di un elemento. Nel seguente example, la seconda casella modificherà il raggio del bordo in base alla larghezza.

const ro = new ResizeObserver(entries => {
  for (let entry of entries) {
    entry.target.style.borderRadius =
        Math.max(0, 250 - entry.contentRect.width) + 'px';
  }
});
// Only observe the second box
ro.observe(document.querySelector('.box:nth-child(2)'));

Un altro esempio interessante è rappresentato dalla finestra di una chat. Il problema che si presenta in un tipico layout di conversazione dall'alto verso il basso è il posizionamento tramite scorrimento. Da evitare confondere l'utente, è utile se la finestra si attacca alla parte inferiore del conversazione in cui appaiono i messaggi più recenti. Inoltre, qualsiasi tipo di layout (pensa a un telefono che passa dall'orientamento orizzontale a quello verticale o viceversa) ottenere lo stesso risultato.

ResizeObserver ti consente di scrivere una singola porzione di codice che si occupa entrambi gli scenari. Il ridimensionamento della finestra è un evento a cui ResizeObserver può cattura per definizione, ma richiamando appendChild() anche l'elemento viene ridimensionato (a meno che non sia impostato overflow: hidden), perché deve liberare spazio per i nuovi elementi. Tenendo conto di questo, sono necessarie pochissime righe per ottenere effetto:

const ro = new ResizeObserver(entries => {
  document.scrollingElement.scrollTop =
    document.scrollingElement.scrollHeight;
});

// Observe the scrollingElement for when the window gets resized
ro.observe(document.scrollingElement);

// Observe the timeline to process new messages
ro.observe(timeline);

Piuttosto comodo, no?

Da qui, potrei aggiungere altro codice per gestire il caso in cui l'utente ha fatto scorrere la pagina. manualmente e vuole che lo scorrimento rimanga impostato su quel messaggio quando viene entra in gioco.

Un altro caso d'uso è per qualsiasi tipo di elemento personalizzato che esegue il proprio layout. Fino al giorno ResizeObserver, non c'era un modo affidabile per ricevere notifiche quando le dimensioni cambiano in modo che le dimensioni secondarie possano essere riordinate.

Effetti sull’interazione con Next Paint (INP)

Interazione con Next Paint (INP) è una metrica che misura il reattività complessiva di una pagina alle interazioni degli utenti. Se l'INP di una pagina è in il "buono" minima, ovvero 200 millisecondi o meno, può dire che una pagina risponde in modo affidabile le interazioni dell'utente con quest'ultimo.

Mentre il tempo necessario per l'esecuzione dei callback di eventi in risposta a un l'interazione dell'utente può contribuire significativamente alla latenza totale di un'interazione, questo non è l'unico aspetto di INP da considerare. L'INP considera anche la quantità il tempo necessario per la visualizzazione successiva dell'interazione. Questo è il la quantità di tempo necessaria per il lavoro di rendering necessario per aggiornare l'utente a riga di comando in risposta a un'interazione.

Per quanto riguarda ResizeObserver, questo è importante perché il callback che l'esecuzione di un'istanza ResizerObserver avviene poco prima del lavoro di rendering. Questo è progettato, in quanto il lavoro che viene svolto nel callback deve essere account. Di conseguenza, molto probabilmente sarà necessario modificare a riga di comando.

Svolgi il minimo lavoro di rendering richiesto in ResizeObserver perché un eccessivo lavoro di rendering può creare situazioni in cui viene ritardato nello svolgimento di un lavoro importante. Ad esempio, se un'interazione ha un che causa l'esecuzione di un callback ResizeObserver, assicurati di eseguire la per rendere l'esperienza più fluida possibile:

  • Assicurati che i selettori CSS siano il più semplici possibile per evitare un eccessivo ricalcolo dello stile. I ricalcoli degli stili avvengono poco prima del layout e i selettori CSS complessi possono ritardare le operazioni di layout.
  • Evita di svolgere nel callback ResizeObserver operazioni che possono attivarsi ripetizioni forzate.
  • Il tempo necessario per aggiornare il layout di una pagina aumenta in genere con il di elementi DOM su una pagina. Questo vale indipendentemente dal fatto che le pagine utilizzino o meno ResizeObserver, il lavoro svolto in un callback ResizeObserver può diventare sono significativi man mano che aumenta la complessità strutturale di una pagina.

Conclusione

ResizeObserver è disponibile in tutti i principali browser e consente di monitorare in modo efficiente il ridimensionamento di un elemento livello. Fai attenzione a non ritardare troppo il rendering con questa potente API.