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

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

ResizeObserver öncesinde, görüntü alanının boyutlarında yapılan değişikliklerden haberdar olmak için dokümanın resizeetkinliğ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() işlevini çağırmanı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, faydalı bir temel öğedir. 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.
  • Kenar: 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, ResizeObserverEntry nesne dizisi (gözlenen her öğe başına bir giriş) iletilir. Bu dizi, öğenin yeni boyutlarını içerir.

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 bildiriliyor?

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 elde edilir.

CSS kutu modelinin şeması.

ResizeObserver hem contentRect boyutlarını hem de dolguyu raporlar ancak yalnızca contentRectizler. contentRect öğesini öğ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ğırmanın çağrıldığı anda gözlemlenen öğeyle ilgilidir.

  • borderBoxSize
  • contentBoxSize
  • devicePixelContentBoxSize

Bu öğelerin tümü, gelecekte çok sütunlu senaryolarda ortaya çıkan birden çok parçaya sahip öğeleri destekleyebilecekleri umulduğu için salt okunur diziler döndürü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 ilk ikisini Firefox 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.

Anladım

Kendinize şu soruyu soruyor olabilirsiniz: ResizeObserver olarak geri çağırmanın içindeki gözlemlenen bir öğenin boyutunu 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ını 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)'));

Göz atılması gereken diğer bir ilginç ö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üğü görüşmenin en altına sabitlenmesi faydalı olacaktı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 karşılayan tek bir kod 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 ve böylece alt öğelerinin yeniden düzenlenmesini sağlamak için güvenilir bir yöntem yoktu.

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.

Bir kullanıcı etkileşimine yanıt olarak etkinlik geri çağırmalarının çalışması için gereken süre, etkileşimin toplam gecikmesine önemli ölçüde katkıda bulunabilse de 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ü 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şim ResizeObserver geri çağırmasının çalıştırılmasına neden olan bir geri çağırma içeriyorsa mümkün olan en sorunsuz deneyimi sağlamak için aşağıdakileri yaptığınızdan emin olun:

  • Stili aşırı sayıda yeniden hesaplama işleminden kaçınmak için CSS seçicilerinizin mümkün olduğunca 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ına göre artar. Sayfalar ResizeObserver kullansa da olmasa da bu durum doğru olsa da ResizeObserver geri çağırma işleminde yapılan işler, sayfanın yapısal karmaşıklığı arttıkça ö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.