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.
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.
È 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 callbackResizeObserver
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.