ResizeObserver, bir öğenin boyutu değiştiğinde sizi bilgilendirir.
ResizeObserver öncesinde, görünüm alanının boyutlarındaki değişikliklerden haberdar olmak için dokümanın resize etkinliğine bir dinleyici eklemeniz gerekiyordu. Etkinlik işleyicide, bu değişiklikten hangi öğelerin etkilendiğini bulmanız ve uygun şekilde tepki 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 gerekiyordu. Bu da okuma ve yazma işlemlerinizin tümünü gruplandırmazsanız düzenin aşırı bellek kullanımına neden olabiliyordu.
Bu, öğelerin ana pencere yeniden boyutlandırılmadan boyutlarını değiştirdiği durumları bile kapsamadı. Örneğin, yeni alt öğeler ekleme, bir öğenin display stilini none olarak ayarlama veya benzer işlemler, bir öğenin, kardeş öğelerinin ya da üst öğelerinin boyutunu değiştirebilir.
Bu nedenle ResizeObserver kullanışlı bir temeldir. Değişikliğe neyin neden olduğundan bağımsız olarak, gözlemlenen öğelerin boyutundaki değişikliklere tepki verir.
Gözlemlenen öğelerin yeni boyutuna da erişim sağlar.
API
Yukarıda bahsettiğimiz Observer sonekine sahip tüm API'ler basit bir API tasarımına sahiptir. ResizeObserver da bu durumun bir istisnası değildir. ResizeObserver nesnesi oluşturup oluşturucuya geri çağırma işlevi iletirsiniz. Geri çağırma işlevine, gözlemlenen her öğe için bir giriş içeren ve öğenin yeni boyutlarını içeren bir ResizeObserverEntry nesne dizisi 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 bildiriliyor?
Genellikle bir
ResizeObserverEntry
öğesi, contentRect adlı bir özellik aracılığıyla öğenin içerik kutusunu bildirir. Bu özellik, bir
DOMRectReadOnly
nesnesi döndürür. İçerik kutusu, içeriğin yerleştirilebileceği kutudur. Kenarlık kutusundan dolgu çıkarılarak elde edilir.
ResizeObserver hem contentRect hem de dolgunun boyutlarını raporlasa da yalnızca contentRect'ü izlediğini unutmayın.
contentRect ile öğenin sınırlayıcı kutusunu karıştırmayın. getBoundingClientRect() tarafından bildirilen sınırlayıcı kutu, öğenin tamamını ve alt öğelerini içeren kutudur. SVG'ler bu kuralın istisnasıdır. Bu tür dosyalarda 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 sahip. Bu özelliklerin her biri, blockSize özelliği ve inlineSize özelliği içeren bir ResizeObserverSize nesnesi döndürür. Bu bilgiler, geri çağırma işlemi başlatıldığında gözlemlenen öğe hakkındadır.
borderBoxSizecontentBoxSizedevicePixelContentBoxSize
Bu öğelerin tümü salt okunur diziler döndürür. Bunun nedeni, gelecekte çok sütunlu senaryolarda oluşan birden fazla parçaya sahip öğeleri destekleyebilmelerinin beklenmesidir. Şimdilik bu diziler yalnızca bir öğe içerecek.
Bu özellikler için platform desteği sınırlıdır ancak Firefox ilk ikisini zaten desteklemektedir.
Ne zaman bildiriliyor?
Spesifikasyon, ResizeObserver öğesinin tüm yeniden boyutlandırma etkinliklerini boyamadan önce ve düzenden sonra işlemesini zorunlu kılar. Bu nedenle, ResizeObserver geri çağırması, sayfanızın düzeninde değişiklik yapmak için ideal yerdir. ResizeObserver
işleme düzen ve boyama arasında gerçekleştiğinden bu işlem yalnızca düzeni geçersiz kılar, boyamayı değil.
Anladım
Kendinize şu soruyu soruyor olabilirsiniz: Geri çağırma işlevinin içindeki gözlemlenen bir öğenin boyutunu ResizeObserver olarak değiştirirsem ne olur? Yanıt: Geri arama için hemen başka bir arama 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ğırmada işlenen en sığ öğeden daha derin bir DOM ağacındaysa aynı karede işlenir.
Aksi takdirde, bir sonraki kareye ertelenirler.
Uygulama
ResizeObserver, öğe bazında medya sorguları uygulamanıza olanak tanır. Öğeleri gözlemleyerek tasarımınızın kesme noktalarını zorunlu olarak 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ş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)'));
İncelenebilecek bir diğer ilginç örnek ise 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 alt kısmında kalması faydalıdır. Ayrıca, her türlü düzen değişikliği (ör. telefonun yataydan dikeyye veya dikeyden yataya geçmesi) de aynı sonucu vermelidir.
ResizeObserver, her iki senaryoyu da ele alan tek bir kod parçası yazmanıza olanak tanır. Pencereyi yeniden boyutlandırma, ResizeObserver tarafından tanımı gereği yakalanabilen bir etkinliktir ancak appendChild() işlevi de yeni öğelere yer açması gerektiğinden bu öğeyi yeniden boyutlandırır (overflow: hidden ayarlanmadığı sürece). Bu nedenle, istenen 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);
Çok güzel, değil mi?
Buradan, kullanıcının manuel olarak yukarı kaydırdığı ve yeni bir mesaj geldiğinde kaydırmanın bu mesajda kalmasını istediği durumu işlemek için daha fazla kod ekleyebilirim.
Bir diğer kullanım alanı ise kendi düzenini oluşturan her türlü özel öğe içindir.
ResizeObserver tarihine kadar, boyutları değiştiğinde alt öğelerinin yeniden düzenlenebilmesi için bildirim almanın güvenilir bir yolu yoktu.
Interaction to Next Paint (INP) üzerindeki etkiler
Interaction to Next Paint (INP), bir sayfanın kullanıcı etkileşimlerine genel olarak yanıt verme oranını ölçen bir metriktir. Bir sayfanın INP değeri "iyi" eşiğinde (200 milisaniye veya daha az) ise sayfanın, kullanıcının etkileşimlerine güvenilir bir şekilde yanıt verdiği söylenebilir.
Etkinlik geri çağırmalarının kullanıcı etkileşimine yanıt olarak çalışması için gereken süre, etkileşimin toplam gecikmesine önemli ölçüde katkıda bulunsa da INP'nin dikkate alınması gereken tek yönü bu değildir. INP, etkileşimin sonraki boyamasının gerçekleşmesi için gereken süreyi de dikkate alır. Bu, 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 ile ilgili olarak, bir ResizerObserver örneğinin çalıştırdığı geri çağırma, oluşturma işleminden hemen önce gerçekleştiği için bu önemlidir. Geri çağırmada yapılan işin dikkate alınması gerektiğinden bu durum tasarımdan kaynaklanmaktadır. Çünkü bu işin sonucu, kullanıcı arayüzünde çok büyük olasılıkla bir değişiklik yapılmasını gerektirecektir.
Aşırı oluşturma çalışması, tarayıcının önemli işleri yapmasını geciktirebileceğinden ResizeObserver
geri çağırmada gerektiği kadar oluşturma çalışması yapmaya özen gösterin. Örneğin, herhangi bir etkileşimde ResizeObserver geri arama işleminin çalışmasına neden olan bir geri arama 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 çalışmasını önlemek 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çiciler düzen işlemlerini geciktirebilir.
ResizeObservergeri çağırma işlevinizde zorunlu yeniden akışları tetikleyebilecek işlemler yapmaktan kaçının.- Bir sayfanın düzenini güncellemek için gereken süre genellikle sayfadaki DOM öğelerinin sayısıyla artar. Bu durum, sayfaların
ResizeObserverkullanıp kullanmadığına bakılmaksızın geçerli olsa da birResizeObservergeri çağırma işleminde yapılan çalışma, 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ı izlemek için verimli bir yol sağlar. Bu güçlü API ile oluşturmayı çok fazla geciktirmemeye dikkat edin.