ब्राउज़र रेंडरिंग के चार चरणों को समझें ताकि आपको ठीक-ठीक पता चले कि कौन-सी CSS प्रॉपर्टीज़ महंगी हैं और will-change अंदरूनी तौर पर कैसे काम करता है।
इस पाठ को Kodokon में खोलेंब्राउज़र आपकी CSS को चार-चरणों वाली पाइपलाइन के ज़रिए पिक्सेल में बदलता है: Style (वैल्यू की गणना), Layout (ज्यामिति, जिसे reflow भी कहते हैं), Paint (पिक्सेल में रैस्टराइज़ करना, यानी repaint) और Composite (GPU पर लेयर्स को जोड़ना)। सुनहरा नियम: आप जितने पहले के चरण को छूते हैं, बिल उतना ही बड़ा होता है, क्योंकि उसके बाद का हर चरण फिर से चलाया जाता है। width या top बदलने से layout + paint + composite ट्रिगर होता है। color या box-shadow बदलने से layout छूट जाता है पर repaint होता है। केवल transform और opacity को अकेले compositor thread द्वारा संभाला जा सकता है: एनिमेशन तब भी सहज रहता है जब मुख्य थ्रेड JavaScript से अवरुद्ध हो।
.slide-bad {
position: absolute;
transition: left 0.3s ease;
}
.slide-bad:hover { left: 120px; }
.slide-good {
transition: transform 0.3s ease;
}
.slide-good:hover { transform: translateX(120px); }ब्राउज़र आलसी होता है: यह आपके style राइट्स को बैच करता है और अगले रिफ़्रेश पर ही layout दोबारा गणना करता है। पर कुछ JavaScript रीड्स - offsetHeight, getBoundingClientRect(), scrollTop, किसी ज्यामितीय प्रॉपर्टी पर getComputedStyle() - अद्यतन वैल्यू की माँग करते हैं। अगर कोई राइट लंबित हो, तो ब्राउज़र को तुरंत और सिंक्रोनस रूप से दोबारा गणना करनी पड़ती है: यही एक forced reflow है। किसी लूप के भीतर रीड्स और राइट्स को बारी-बारी करने से layout thrashing होता है: पूरे बैच के लिए एक की जगह हर पुनरावृत्ति पर एक पूरा reflow।
const items = document.querySelectorAll('.item');
items.forEach((item) => {
const h = item.offsetHeight;
item.style.height = h * 2 + 'px';
});
const heights = [...items].map((i) => i.offsetHeight);
items.forEach((item, index) => {
item.style.height = heights[index] * 2 + 'px';
});Compositing पेज को लेयर्स में काटता है जिन्हें स्वतंत्र रूप से रैस्टराइज़ किया जाता है और GPU द्वारा जोड़ा जाता है। will-change: transform एनिमेशन से पहले एलिमेंट को उसकी अपनी लेयर में पदोन्नत करने का अनुरोध करता है, जिससे पहले फ़्रेम पर महंगी रैस्टराइज़ेशन से बचा जा सके। एक स्पेक बारीकी जो अक्सर अनदेखी रह जाती है: will-change को उसी प्रॉपर्टी जैसे साइड इफ़ेक्ट पैदा करने चाहिए जिसकी वह घोषणा करता है। इसलिए will-change: transform एक stacking context बनाता है और एलिमेंट को उसके position: fixed वंशजों के लिए एक containing block में बदल देता है - ठीक किसी असली transform की तरह। इसलिए एक साधारण परफ़ॉर्मेंस संकेत आपके stacking क्रम या आपके fixed एलिमेंट्स को तोड़ सकता है।
const panel = document.querySelector('.panel');
panel.addEventListener('pointerenter', () => {
panel.style.willChange = 'transform';
});
panel.addEventListener('transitionend', () => {
panel.style.willChange = 'auto';
});