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 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()
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.
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.
ResizeObserver
hem contentRect
boyutlarını hem de dolguyu raporlar ancak yalnızca contentRect
'ı izler.
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, ResizeObserver
geri ç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 daResizeObserver
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.