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

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

ResizeObserver tarihinden önce, görüntü alanının boyutlarında herhangi bir değişiklik olduğunda bildirim almak için dokümanın resize etkinliğine bir işleyici eklemeniz gerekiyordu. Ardından, etkinlik işleyicide bu değişiklikten hangi öğelerin etkilendiğini bulmanız ve uygun şekilde tepki vermesi için belirli bir rutini çağırmanız gerekir. Yeniden boyutlandırma sonrasında bir öğenin yeni boyutlarına ihtiyacınız olursa getBoundingClientRect() veya getComputedStyle() yöntemini çağırmanız gerekti. Tüm okumalarınızı ve tüm yazmalarınızı toplu olarak işleme almazsanız düzenin bozulmasına yol açabilir.

Bu, ana pencere yeniden boyutlandırılmadan öğelerin boyutlarının değiştiği durumları bile kapsamadı. Örneğin, yeni alt öğeler eklemek, bir öğenin display stilini none olarak ayarlamak veya benzer işlemler bir öğenin, kardeş öğelerinin veya üst öğelerinin boyutunu değiştirebilir.

Bu nedenle ResizeObserver kullanışlı bir temel öğedir. Gözlemlenen öğelerden herhangi birinin boyutundaki değişikliklere, değişimin nedeninden bağımsız olarak tepki verir. Ayrıca, gözlemlenen öğelerin yeni boyutuna erişim sağlar.

Tarayıcı Desteği

  • 64
  • 79
  • 69
  • 13.1

Kaynak

API

Yukarıda bahsettiğimiz Observer son ekine sahip tüm API'ler basit bir API tasarımına sahiptir. ResizeObserver için de durum farklı değildir. Bir ResizeObserver nesnesi oluşturur ve kurucuya bir geri çağırma iletirsiniz. Geri çağırma, öğe için yeni boyutları içeren ResizeObserverEntry nesne dizisinden (gözlenen öğe başına bir giriş) geçirilir.

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?

Genel olarak ResizeObserverEntry, bir öğenin içerik kutusunu DOMRectReadOnly nesnesi döndüren contentRect adlı bir özellik aracılığıyla bildirir. İçerik kutusu, içeriğin yerleştirilebileceği kutudur. Bu, kenarlık kutusundan dolgunun çıkarılmasıyla elde edilen değerdir.

CSS kutu modelinin diyagramı.

ResizeObserver işlevinin hem contentRect hem de dolgu boyutunu bildirdiği, ancak yalnızca contentRect öğesini izlediği unutulmamalıdır. contentRect öğesini öğenin sınırlayıcı kutusuyla karıştırmayın. getBoundingClientRect() tarafından bildirildiği gibi sınırlayıcı kutu, öğenin tamamını ve alt öğelerini içeren kutudur. SVG'ler bu kuralın bir istisnasıdır. ResizeObserver, sınırlayıcı kutunun boyutlarını bildirir.

Chrome 84 sürümünden itibaren ResizeObserverEntry, daha ayrıntılı bilgi sağlayacak üç yeni özelliğe sahip. Bu özelliklerin her biri, blockSize özelliği ve inlineSize özelliği içeren bir ResizeObserverSize nesnesi döndürür. Bu bilgi, geri çağırma işlevinin çağrıldığı sırada gözlemlenen öğeyle ilgilidir.

  • borderBoxSize
  • contentBoxSize
  • devicePixelContentBoxSize

Bu öğelerin tümü, gelecekte çok sütunlu senaryolarda meydana gelen birden fazla parçaya sahip öğeleri destekleyebileceği için salt okunur diziler döndürür. Şimdilik bu diziler yalnızca bir öğe içerir.

Bu özelliklere ilişkin platform desteği sınırlıdır ancak ilk ikisini Firefox zaten desteklemektedir.

Ne zaman bildiriliyor?

Spesifikasyon, ResizeObserver ürününün tüm yeniden boyutlandırma etkinliklerini boyamadan önce ve düzenden sonra işlemesini gerektirir. Bu, bir ResizeObserver geri çağırmasını sayfanızın düzeninde değişiklik yapmak için ideal bir yer haline getirir. ResizeObserver işlemi düzen ile boyama arasında gerçekleştiğinden bu işlem yalnızca düzeni geçersiz kılar, boyamayı geçersiz kılar.

Anladım

Kendinize, geri çağırma içindeki gözlemlenen bir öğenin boyutunu ResizeObserver olarak değiştirirsem ne olacağını soruyor olabilirsiniz. Cevap, geri arama için hemen başka bir aramayı tetiklersiniz. Neyse ki ResizeObserver, sonsuz geri çağırma döngülerini ve döngüsel bağımlılıkları önleyen bir mekanizmaya sahiptir. Değişiklikler yalnızca yeniden boyutlandırılan öğe, DOM ağacında önceki geri çağırmada işlenen shallowest öğesinden daha derindeyse aynı çerçevede işlenir. Aksi takdirde sonraki kareye ertelenir.

Başvuru

ResizeObserver ile öğe başına medya sorguları uygulayabilirsiniz. Öğeleri gözlemleyerek zorunlu olarak tasarım ayrılma noktalarınızı tanımlayabilir ve bir öğenin stillerini değiştirebilirsiniz. Aşağıdaki örnekte, ikinci kutunun kenarlık yarıçapı genişliğine göre değiştirilecektir.

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 bir diğer ilginç örnek de sohbet penceresi. 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 çok yararlı olur. Ayrıca, herhangi bir düzen değişikliğinin de (bir telefonu yatay, dikey veya tam tersi yönde) aynı şekilde sonuç vermesi gerekir.

ResizeObserver, her iki senaryoyu da halleden tek bir kod parçası yazmanıza olanak tanır. Pencerenin yeniden boyutlandırılması, bir ResizeObserver öğesinin tanım olarak yakalayabileceği bir etkinliktir. Ancak appendChild() çağrısı, yeni öğelere yer açılması gerektiğinden (overflow: hidden ayarlanmamışsa) söz konusu öğeyi de yeniden boyutlandırır. Bu göz önünde bulundurulduğunda, istenen etkiyi elde etmek için çok birkaç satır yeterli:

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

Çok şık, değil mi?

Buradan, kullanıcının manuel olarak yukarı kaydırdığı ve yeni bir mesaj geldiğinde bu mesajda kalmak için kaydırma yapmak istediği durumu halletmek için daha fazla kod ekleyebilirim.

Başka bir kullanım alanı da kendi düzenini oluşturan herhangi bir özel öğe türüne yöneliktir. ResizeObserver tarihine kadar, alt öğelerinin tekrar sıralanabilmesi için boyutları değiştiğinde bildirim almanın güvenilir bir yolu yoktu.

Sonraki boyamayla etkileşim (INP) üzerindeki etkiler

Sonraki Boyamayla Etkileşim (INP), sayfanın kullanıcı etkileşimlerine genel duyarlılığını ölçen bir metriktir. Bir sayfanın INP'si "iyi" eşik aralığındaysa (yani 200 milisaniye veya daha kısaysa) bir sayfanın, kullanıcının sayfayla olan etkileşimlerine güvenilir bir şekilde yanıt verdiği belirtilebilir.

Etkinlik geri çağırmalarının bir kullanıcı etkileşimine yanıt olarak çalışması için gereken 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 bir sonraki boyamanın gerçekleşmesi için gereken süreyi de dikkate alır. Bu, bir etkileşimin tamamlanmasına yanıt olarak kullanıcı arayüzünü güncellemek için gereken oluşturma işi için gereken süredir.

ResizeObserver söz konusu olduğunda bu önemlidir, çünkü bir ResizerObserver örneğinin çalıştırıldığı geri çağırma, oluşturma işleminden hemen önce gerçekleşir. Bu tasarım gereğidir, çünkü geri çağırma işleminde gerçekleşen çalışmanın dikkate alınması gerekir, çünkü bu çalışmanın sonucu olarak büyük olasılıkla kullanıcı arayüzünde değişiklik yapılması gerekir.

Aşırı oluşturma işlemi, tarayıcının önemli işleri yaparken gecikmesine neden olabilecek durumlara neden olabileceğinden ResizeObserver geri çağırma işleminde gereken kadar az oluşturma işlemi yapmaya özen gösterin. Örneğin, herhangi bir etkileşim ResizeObserver geri çağırmasının çalışması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:

  • Aşırı düzeyde stil yeniden hesaplama işlemi yapılmasını önlemek için CSS seçicilerinizin mümkün olduğunca basit olduğundan emin olun. Stille ilgili yeniden hesaplama işlemleri düzenden hemen önce yapılır ve karmaşık CSS seçiciler düzen işlemlerini geciktirebilir.
  • ResizeObserver geri çağırma işleminizde, zorunlu yeniden akışları tetikleyebilecek işler yapmaktan kaçının.
  • Bir sayfanın düzenini güncellemek için gereken süre genellikle sayfadaki DOM öğelerinin sayısıyla birlikte artar. Sayfalar ResizeObserver özelliğini kullansa da kullanmasa da bu doğru olsa da, bir sayfanın yapısal karmaşıklığı arttıkça ResizeObserver geri çağırmasında yapılan iş önemli hale gelebilir.

Sonuç

ResizeObserver, başlıca tüm tarayıcılarda kullanılabilir ve öğe düzeyindeki öğe yeniden boyutlandırmalarını izlemek için etkili bir yol sağlar. Bu güçlü API ile oluşturma işlemini çok fazla ertelememeye dikkat edin.