Merhaba arkadaşlar, bugün başımı çok ağrıtan ve performans iyileştireyim derken tam tersine sayfayı yavaşlatan bir konudan bahsedeceğim: will-change özelliği. Bu özelliği ilk öğrendiğimde, "Harika, tarayıcıya önden haber verip animasyonları süper akıcı yapabilirim!" diye düşünmüştüm. Meğer ne büyük yanılgıymış. Kontrolsüz kullanımı, bellek tüketimini uçurup sayfa hızını düşürebiliyormuş. İşte benim bu tuzağa düşüp sonra öğrendiğim, sadece gerekli durumlarda nasıl uyguladığım.
Karşılaştığım Sorun ve Yanlış Kullanım
Projede, kullanıcı fareyle üzerine geldiğinde hafifçe büyüyen ve renk değiştiren yüzlerce kart bileşeni vardı. Amacım, bu animasyonları 60 fps'de, kesintisiz çalıştırmaktı. İlk başta, "Hadi tüm kartlara `will-change` ekleyeyim, tarayıcı hazırlıklı olsun" mantığıyla aşağıdaki gibi bir CSS yazmıştım. Bu hatayı ilk gördüğümde kafayı yemiştim, çünkü sayfa ilk açılışta bile donmalar yaşanıyordu.
Bu kodu uyguladıktan sonra, Chrome DevTools'taki Performance sekmesinde profilleme yaptım. Gördüğüm şey, layout ve paint işlemlerinin gereksiz yere arttığı ve bellek (RAM) kullanımının yükseldiğiydi. Tarayıcı, bu yüzlerce elementi sürekli olarak "değişecekmiş" gibi ön belleğe alıp kaynak ayırmaya çalışıyordu. Performans iyileştirmesi yapmak isterken, tam bir performans cezası yemiştim.
Doğru Yaklaşım: Sadece Gerektiğinde ve Geçici Olarak
Araştırmalarım sonucunda öğrendim ki, `will-change` bir "sihirli değnek" değil, bir "son çare" aracı. Kullanım kılavuzu şu: Sadece yakın gelecekte değişeceğini kesin olarak bildiğin ve zaten performans sorunu yaşanan öğelere, geçici olarak uygula. Benim çözümüm, bu özelliği sadece hover sırasında, JavaScript ile dinamik olarak ekleyip kaldırmak oldu.
İşte benim kullandığım en temiz çözüm:
Ve CSS'im artık çok daha sade:
Bu yöntemle, tarayıcıya sadece animasyon başlamadan hemen önce (fare üzerine gelince) bir uyarı gönderiyoruz. Animasyon bittikten sonra da bu özel kaynak ayırma işlemini sonlandırıyoruz. Böylece, sayfadaki diğer yüzlerce kart için sürekli bir bellek yükü oluşturmuyoruz.
Hangi Durumlarda Kullanmalı?
Artık `will-change` özelliğini sadece aşağıdaki gibi durumlarda, çok dikkatli kullanıyorum:
- Kullanıcı etkileşimi (tıklama, hover) ile tetiklenen kompleks 3D transformlar (rotate3d, matrix3d).
- Sayfa kaydırılırken sabitlenmiş (fixed) bir elementin konumunun sürekli hesaplanması gereken durumlar.
- Gerçekten gözle görülür bir titreme (jank) olan ve diğer optimizasyonların (translateZ hack'i gibi) çözmediği animasyonlar.
Özetle, `will-change` özelliği güçlü bir araç ama ateşle oynamak gibi. Kontrolsüz kullanımı performansı düşürür. En iyi performans için, CSS'inizi mümkün olduğunca basit tutun, `will-change`'i ise sadece kanıtlanmış darboğazlarda ve geçici olarak kullanın.
Siz projelerinizde `will-change` özelliğini hiç kullandınız mı? Yaşadığınız performans sorunları veya farklı bir kullanım şekliniz var mı? Yorumlarda deneyimlerinizi paylaşın, tartışalım!
Projede, kullanıcı fareyle üzerine geldiğinde hafifçe büyüyen ve renk değiştiren yüzlerce kart bileşeni vardı. Amacım, bu animasyonları 60 fps'de, kesintisiz çalıştırmaktı. İlk başta, "Hadi tüm kartlara `will-change` ekleyeyim, tarayıcı hazırlıklı olsun" mantığıyla aşağıdaki gibi bir CSS yazmıştım. Bu hatayı ilk gördüğümde kafayı yemiştim, çünkü sayfa ilk açılışta bile donmalar yaşanıyordu.
CSS:
.card {
transition: transform 0.3s ease, background-color 0.3s ease;
will-change: transform, background-color; / YANLIŞ! /
}
.card:hover {
transform: scale(1.05);
background-color: #f0f0f0;
}
Bu kodu uyguladıktan sonra, Chrome DevTools'taki Performance sekmesinde profilleme yaptım. Gördüğüm şey, layout ve paint işlemlerinin gereksiz yere arttığı ve bellek (RAM) kullanımının yükseldiğiydi. Tarayıcı, bu yüzlerce elementi sürekli olarak "değişecekmiş" gibi ön belleğe alıp kaynak ayırmaya çalışıyordu. Performans iyileştirmesi yapmak isterken, tam bir performans cezası yemiştim.
Araştırmalarım sonucunda öğrendim ki, `will-change` bir "sihirli değnek" değil, bir "son çare" aracı. Kullanım kılavuzu şu: Sadece yakın gelecekte değişeceğini kesin olarak bildiğin ve zaten performans sorunu yaşanan öğelere, geçici olarak uygula. Benim çözümüm, bu özelliği sadece hover sırasında, JavaScript ile dinamik olarak ekleyip kaldırmak oldu.
İşte benim kullandığım en temiz çözüm:
JavaScript:
// Tüm kartları seç
const cards = document.querySelectorAll('.card');
cards.forEach(card => {
// Fare kartın üzerine geldiğinde will-change ekle
card.addEventListener('mouseenter', (e) => {
e.target.style.willChange = 'transform, background-color';
});
// Animasyon bittikten sonra will-change'ı kaldır
card.addEventListener('transitionend', (e) => {
// Sadece transform veya background-color animasyonu bittiğinde temizle
if (e.propertyName === 'transform' || e.propertyName === 'background-color') {
e.target.style.willChange = 'auto';
}
});
});
Ve CSS'im artık çok daha sade:
CSS:
.card {
transition: transform 0.3s ease, background-color 0.3s ease;
/ will-change artık burada YOK! /
}
.card:hover {
transform: scale(1.05);
background-color: #f0f0f0;
}
Bu yöntemle, tarayıcıya sadece animasyon başlamadan hemen önce (fare üzerine gelince) bir uyarı gönderiyoruz. Animasyon bittikten sonra da bu özel kaynak ayırma işlemini sonlandırıyoruz. Böylece, sayfadaki diğer yüzlerce kart için sürekli bir bellek yükü oluşturmuyoruz.
Artık `will-change` özelliğini sadece aşağıdaki gibi durumlarda, çok dikkatli kullanıyorum:
- Kullanıcı etkileşimi (tıklama, hover) ile tetiklenen kompleks 3D transformlar (rotate3d, matrix3d).
- Sayfa kaydırılırken sabitlenmiş (fixed) bir elementin konumunun sürekli hesaplanması gereken durumlar.
- Gerçekten gözle görülür bir titreme (jank) olan ve diğer optimizasyonların (translateZ hack'i gibi) çözmediği animasyonlar.
Özetle, `will-change` özelliği güçlü bir araç ama ateşle oynamak gibi. Kontrolsüz kullanımı performansı düşürür. En iyi performans için, CSS'inizi mümkün olduğunca basit tutun, `will-change`'i ise sadece kanıtlanmış darboğazlarda ve geçici olarak kullanın.
Siz projelerinizde `will-change` özelliğini hiç kullandınız mı? Yaşadığınız performans sorunları veya farklı bir kullanım şekliniz var mı? Yorumlarda deneyimlerinizi paylaşın, tartışalım!