RedirectObserver: Öğeler için document.onresize gibidir

ResizeObserver, bir öğenin boyutu değiştiğinde sizi bilgilendirir.

ResizeObserver'ten önce, görüntü alanının boyutlarında yapılan değişikliklerden haberdar olmak için dokümanın resize etkinliğine bir dinleyici eklemeniz gerekiyordu. Etkinlik işleyicisinde, bu değişiklikten hangi öğelerin etkilendiğini bulmanız ve uygun şekilde yanıt vermek için belirli bir rutini çağırmanız gerekir. Yeniden boyutlandırmadan sonra bir öğenin yeni boyutlarına ihtiyacınız varsa getBoundingClientRect() veya getComputedStyle() çağrısını yapmanız gerekir. Tüm okuma ve tüm yazma işlemlerinizi toplu olarak yapmazsanız bu, düzenin bozulmasına neden olabilir.

Bu, ana pencerenin boyutu değiştirilmeden öğelerin boyutunun değiştiği durumları bile kapsamıyordu. Örneğin, yeni alt öğeler eklemek, bir öğenin display stilini none olarak ayarlamak veya benzer işlemler, bir öğenin, kardeşlerinin veya atalarının boyutunu değiştirebilir.

Bu nedenle ResizeObserver, yararlı bir ilkeldir. Değişikliğe neyin neden olduğundan bağımsız olarak, gözlemlenen öğelerden herhangi birinin boyutundaki değişikliklere tepki verir. Ayrıca, gözlemlenen öğelerin yeni boyutuna da erişim sağlar.

Tarayıcı desteği

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

Kaynak

API

Yukarıda bahsettiğimiz Observer son ekiyle biten tüm API'ler basit bir API tasarımına sahiptir. ResizeObserver de bu istisnalar arasında değildir. Bir ResizeObserver nesnesi oluşturur ve yapıcıya bir geri çağırma işlevi iletirsiniz. Geri çağırma işlevine, öğenin yeni boyutlarını içeren bir ResizeObserverEntry nesnesi dizisi (gözlenen öğe başına bir giriş) iletilir.

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);

Bazı ayrıntılar

Neler raporlanır?

Genellikle ResizeObserverEntry, bir öğenin içerik kutusunu contentRect adlı bir özellik aracılığıyla bildirir. Bu özellik, DOMRectReadOnly nesnesini döndürür. İçerik kutusu, içeriğin yerleştirilebileceği kutudur. Kenarlık kutusunun dolgu değeri çıkarılarak hesaplanır.

CSS kutu modelini gösteren şema.

ResizeObserver hem contentRect boyutlarını hem de dolguyu raporlar ancak yalnızca contentRectizler. contentRect değerini öğenin sınırlayıcı kutusuyla karıştırmayın. getBoundingClientRect() tarafından bildirilen sınırlayıcı kutu, öğenin tamamını ve alt öğelerini içeren kutudur. SVG'ler kuralın istisnası olup ResizeObserver, sınırlayıcı kutunun boyutlarını bildirir.

Chrome 84'ten itibaren ResizeObserverEntry, daha ayrıntılı bilgi sağlamak için üç yeni özelliğe sahiptir. Bu özelliklerin her biri, bir blockSize mülkü ve bir inlineSize mülkü içeren bir ResizeObserverSize nesnesi döndürür. Bu bilgiler, geri çağırma işlevi çağrılırken gözlemlenen öğeyle ilgilidir.

  • borderBoxSize
  • contentBoxSize
  • devicePixelContentBoxSize

Bu öğelerin tümü salt okunur diziler döndürür. Bunun nedeni, gelecekte çok sütunlu senaryolarda birden fazla fragmanı olan öğeleri destekleyebilecekleri umulmasıdır. Şu anda bu diziler yalnızca bir öğe içerecek.

Bu mülkler için platform desteği sınırlıdır ancak Firefox ilk ikisini zaten desteklemektedir.

Ne zaman bildiriliyor?

Spesifikasyon, ResizeObserver'ün tüm yeniden boyutlandırma etkinliklerini boyamadan önce ve düzenden sonra işlemesini zorunlu kılar. Bu nedenle, ResizeObserver geri çağırma işlevi, sayfanızın düzeninde değişiklik yapmak için ideal bir yerdir. ResizeObserver işlemenin sayfa düzeni ile boyama arasında gerçekleşmesi nedeniyle, bu işlem yalnızca sayfa düzenini geçersiz kılar, boyamayı geçersiz kılmaz.

Gotcha

Kendinize şunu soruyor olabilirsiniz: Geri çağırma işlevi içinde gözlemlenen bir öğenin boyutunu ResizeObserver olarak değiştirirsem ne olur? Yanıt: Hemen geri arama için başka bir çağrı tetiklersiniz. Neyse ki ResizeObserver, sonsuz geri çağırma döngülerini ve döngüsel bağımlılıkları önlemek için bir mekanizmaya sahiptir. Değişiklikler yalnızca yeniden boyutlandırılan öğe, önceki geri çağırma işlevinde işlenen en sığ öğeden daha derin bir DOM ağacındaysa aynı karede işlenir. Aksi takdirde, sonraki kareye ertelenirler.

Başvuru

ResizeObserver, öğe başına medya sorguları uygulamanıza olanak tanır. Öğeleri gözlemleyerek tasarım kesme noktalarınızı zorunlu olarak tanımlayabilir ve bir öğenin stillerini değiştirebilirsiniz. Aşağıdaki örnekte, ikinci kutunun kenarlığı genişliğine göre değişir.

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)'));

Bakılması gereken ilginç bir örnek de sohbet penceresidir. Tipik bir yukarıdan aşağıya görüşme düzeninde ortaya çıkan sorun, kaydırma konumlandırmasıdır. Kullanıcının kafasını karıştırmamak için pencerenin, en yeni mesajların göründüğü sohbetin en altına sabitlenmesi faydalıdır. Ayrıca, her türlü düzen değişikliği (telefonun yataydan dikeye veya tam tersi şekilde dönmesi gibi) de aynı sonucu verir.

ResizeObserver, her iki senaryoyu da dikkate alan tek bir kod parçası yazmanıza olanak tanır. Pencerenin yeniden boyutlandırılması, ResizeObserver'ün tanımı gereği yakalayabileceği bir etkinliktir. Ancak appendChild() çağrıldığında, yeni öğelere yer açması gerektiği için bu öğe de yeniden boyutlandırılır (overflow: hidden ayarlanmadığı sürece). Bu nedenle, istenilen efekti elde etmek için çok az satır gerekir:

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);

Oldukça kullanışlı, değil mi?

Buradan, kullanıcının manuel olarak yukarı kaydırdığı ve yeni bir mesaj geldiğinde kaydırma işleminin bu mesajda kalmasını istediği durumu ele almak için daha fazla kod ekleyebilirim.

Başka bir kullanım alanı da kendi düzenini yapan her türlü özel öğedir. ResizeObserver'e kadar, boyutları değiştiğinde bildirim almak için güvenilir bir yöntem yoktu. Bu nedenle, öğelerin yeniden düzenlenmesi gerekiyordu.

Sonraki Boyamayla Etkileşim (INP) üzerindeki etkiler

Interaction to Next Paint (INP), bir sayfanın kullanıcı etkileşimlerine genel yanıt verme durumunu ölçen bir metriktir. Bir sayfanın INP'si "iyi" eşiğindeyse (yani 200 milisaniye veya daha az) sayfanın, kullanıcının onunla etkileşimlerine güvenilir bir şekilde yanıt verdiği söylenebilir.

Kullanıcı etkileşimine yanıt olarak etkinlik geri çağırmalarının çalışmasının sürdüğü süre, etkileşimin toplam gecikmesine önemli ölçüde katkıda bulunabilir ancak INP'nin dikkate alınması gereken tek yönü bu değildir. INP, etkileşimin sonraki boyasının gerçekleşmesi için geçen süreyi de dikkate alır. Bu, bir etkileşime yanıt olarak kullanıcı arayüzünü güncellemek için gereken oluşturma işleminin tamamlanması için geçen süredir.

ResizeObserver söz konusu olduğunda bu önemlidir, çünkü bir ResizerObserver örneğinin çalıştırdığı geri çağırma işlevi, oluşturma işlemine hemen önce gerçekleşir. Bu, geri çağırma sırasında yapılan çalışmanın dikkate alınması gerektiğinden ve bu çalışmanın sonucu büyük olasılıkla kullanıcı arayüzünde bir değişiklik gerektireceğinden, tasarım gereğidir.

Aşırı oluşturma çalışması, tarayıcının önemli işleri geciktirmesine neden olabileceğinden, ResizeObservergeri çağırma işlevinde gerekenden az oluşturma çalışması yapmaya özen gösterin. Örneğin, herhangi bir etkileşimde ResizeObserver geri çağırmanın çalıştırılmasına neden olan bir geri çağırma varsa mümkün olan en sorunsuz deneyimi sağlamak için aşağıdakileri yaptığınızdan emin olun:

  • Aşırı stil yeniden hesaplama işlemlerini önlemek için CSS seçicilerinizin olabildiğince basit olduğundan emin olun. Stil yeniden hesaplamaları, düzenden hemen önce gerçekleşir ve karmaşık CSS seçicileri, düzen işlemlerini geciktirebilir.
  • ResizeObserver geri çağırma işlevinizde zorunlu yeniden akışı tetikleyebilecek herhangi bir işlem yapmayın.
  • Bir sayfanın düzenini güncellemek için gereken süre genellikle sayfadaki DOM öğelerinin sayısıyla birlikte artar. Bu durum, sayfaların ResizeObserver kullanıp kullanmamasından bağımsız olarak geçerlidir. Ancak sayfanın yapısal karmaşıklığı arttıkça ResizeObserver geri çağırma işlevinde yapılan çalışma önemli hale gelebilir.

Sonuç

ResizeObserver, tüm büyük tarayıcılarda kullanılabilir ve öğe düzeyinde öğe yeniden boyutlandırmalarını izlemenin etkili bir yolunu sunar. Bu güçlü API ile oluşturma işlemini çok fazla geciktirmemek için dikkatli olun.