Reflow vs Repaint
Render tree ekranga chiqishdagi uch bosqich — Layout (Reflow), Paint (Repaint), Composite — va ularning narx farqi, har bosqichni keltirib chiqaruvchi CSS xususiyatlar, Layout Thrashing (Forced Synchronous Layout) xavfi, va uni oldini olish usuli.
55-dars
Reflow vs Repaint
Render tree tayyor bo'lgach, brauzer uni ekranga chiqarish uchun yana uchta bosqichdan o'tkazadi: Layout (Reflow) → Paint (Repaint) → Composite. Bu uchtasi — narx jihatidan teng emas. Ba'zi CSS o'zgarishlar hammasini qayta ishlatadi (qimmat), ba'zilari faqat oxirgisini (arzon).
- Reflow (Layout) — har bir elementning aniq o'lchami va joylashuvi (X, Y koordinatalari, kengligi, balandligi) qayta hisoblanadi
- Repaint (Paint) — hisoblangan joylashuv asosida, har bir element piksel darajasida chiziladi (rang, soya, chegara)
- Composite — chizilgan qatlamlar (layer'lar) ekranga birlashtirilib qo'yiladi
1. Nega ikkovi ajratilgan — bitta jarayon bo'lsa bo'lmaydimi?
Sabab — narx farqi. Joylashuvni hisoblash (Reflow) — butun daraxt bo'ylab zanjirli ta'sir qiladi, chunki bitta elementning kengligi o'zgarsa, uning yonidagi, ostidagi barcha elementlar ham joyini o'zgartirishi mumkin (xuddi domino effekti kabi). Rangni o'zgartirish esa (Repaint) — joylashuvga umuman ta'sir qilmaydi, faqat "shu joyni boshqa rangda qayta chiz" degani, ancha arzon.
Brauzer dizaynerlari shuni tushunib: agar har bir CSS o'zgarishda to'liq joylashuvni qayta hisoblasa — juda sekin bo'lardi. Shuning uchun ular CSS xususiyatlarini uchta toifaga ajratdilar, va har birida faqat kerakli bosqichdan boshlanadi.
2. Uch bosqich — brauzer darajasida nima sodir bo'ladi
1. Layout (Reflow)
element.style.width = '300px';
Bu — elementning geometriyasiga tegadi. Blink engine butun Render tree bo'ylab (yoki hech bo'lmasa, ta'sirlangan qism bo'ylab) yurib, har bir node uchun aniq X, Y, width, height qiymatlarini qaytadan hisoblaydi. Bu — CPU'da og'ir matematik hisoblash: har bir element o'z ota-elementiga, birodar elementlariga bog'liq (masalan, flexbox, grid hisob-kitoblari).
Reflow'ni keltirib chiqaruvchi narsalar:
width,height,padding,margin,borderdisplay,position,top/left/right/bottom- Elementni DOM'ga qo'shish/olib tashlash
- Oyna o'lchamini o'zgartirish (window resize)
- Shrift o'lchamini o'zgartirish
2. Paint (Repaint)
Layout tugagach, brauzer har bir elementni piksel darajasida chizadi — qaysi rangda, qaysi soya bilan, qaysi chegara bilan. Bu — Layout'dan arzonroq, chunki koordinatalar allaqachon aniq, faqat "shu joyni shu rangda bo'ya" degan amal.
Faqat Repaint keltirib chiqaruvchi narsalar (joylashuv o'zgarmaydi):
color,background-colorvisibility(eslatma:display: none— Reflow,visibility: hidden— faqat Repaint!)box-shadow,outline
3. Composite
Zamonaviy brauzerlar sahifani bir nechta **qatlam (layer)**ga bo'ladi (masalan, position: fixed bo'lgan element, transform qo'llangan element — ko'pincha o'z alohida qatlamiga chiqariladi). Composite bosqichida bu qatlamlar GPU yordamida, to'g'ri tartibda ustma-ust qo'yilib, yakuniy tasvir hosil qilinadi.
Faqat Composite kerak bo'ladigan narsalar (eng arzon!):
transform(translate, scale, rotate)opacity
Bu ikkovi — Layout'ni ham, Paint'ni ham chetlab o'tadi, to'g'ridan-to'g'ri GPU orqali, alohida qatlam sifatida qayta joylashtiriladi yoki shaffofligi o'zgartiriladi. Shuning uchun animatsiyalarda left/top o'rniga transform: translateX() ishlatish tavsiya qilinadi — natija bir xil ko'rinsa ham, narxi butunlay boshqacha.
3. Zanjirli ta'sir — nega Reflow eng qimmat
Layout o'zgardi → Paint albatta qayta ishlaydi (chunki joylashuv o'zgargan, eski rasm noto'g'ri) → Composite ham qayta ishlaydi
Ya'ni: Reflow → Paint → Composite hammasini ishga tushiradi. Lekin Composite yolg'iz — hech narsani ishga tushirmaydi (Layout ham, Paint ham qayta hisoblanmaydi). Shu sababli tezlik tartibi:
Reflow (eng qimmat) > Repaint (o'rtacha) > Composite (eng arzon)
4. V8/JS darajasida — "Layout Thrashing" degan xavfli holat
Bu joyda JS bilan brauzer engine orasidagi muvofiqlashtirish muhim bo'lib qoladi. Odatda brauzer DOM o'zgarishlarni darhol qayta hisoblamaydi — ularni to'playdi va bitta frame oxirida (taxminan har 16ms'da, 60fps uchun) bir martada Layout qiladi. Bu — optimallashtirish.
Lekin agar siz JS orqali DOM'ni o'zgartirib, keyin shu zahoti geometriya so'rasangiz — brauzer to'plangan o'zgarishlarni majburiy, sinxron ravishda hisoblab berishga majbur bo'ladi (bu "Forced Synchronous Layout" deyiladi):
// YOMON: har iteratsiyada Forced Reflow
for (let i = 0; i < boxes.length; i++) {
boxes[i].style.width = boxes[i].offsetWidth + 10 + 'px';
// .offsetWidth O'QISH — bu brauzerni "hoziroq Layout qil" deb majburlaydi,
// chunki eski, to'plangan qiymat noto'g'ri bo'lishi mumkin
}
Bu yerda muammo: .style.width = ... (yozish) va .offsetWidth (o'qish) navbatma-navbat, har iteratsiyada aralashtirilgan. Brauzer har safar "yoz → oldingi yozuvlar asosida joylashuvni hoziroq hisobla → o'qi" qilishga majbur bo'ladi — bu "Layout Thrashing" deb ataladi, va sahifa sezilarli darajada sekinlashadi (ayniqsa, ko'p elementlar bilan loop ichida).
To'g'ri yechim — avval hamma o'qishlarni, keyin hamma yozishlarni alohida qilish:
// YAXSHI: avval o'qi, keyin yoz — bitta Reflow yetarli
const widths = boxes.map(box => box.offsetWidth); // hammasini o'qib olamiz
boxes.forEach((box, i) => {
box.style.width = widths[i] + 10 + 'px'; // hammasini yozamiz
});
Bu — brauzerga bitta, yig'ma Reflow qilish imkonini beradi, har iteratsiyada emas.
Xulosa jadvali
| Bosqich | Nima hisoblanadi | Narxi | Misol xususiyat |
|---|---|---|---|
| Layout (Reflow) | Joylashuv, o'lcham | Eng qimmat | width, top, display |
| Paint (Repaint) | Piksel ranglari | O'rtacha | color, background |
| Composite | Qatlamlarni birlashtirish | Eng arzon (GPU) | transform, opacity |