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.
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.
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çaResizeObserver
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.