Hint
Between macrotasks: style β layout β paint β compositing β sync code blocks it
The browser event loop interleaves JS execution with rendering. Understanding this explains why sync code freezes the UI.
// Browser event loop order:
// 1. Pick one macrotask from the queue (e.g., setTimeout callback)
// 2. Execute it to completion
// 3. Drain ALL microtasks (Promises, queueMicrotask)
// 4. β RENDER PHASE (if needed):
// a. requestAnimationFrame callbacks
// b. Style recalculation
// c. Layout (reflow)
// d. Paint
// e. Composite
// 5. Repeat
// Why sync code freezes UI:
button.onclick = () => {
// Render phase is BLOCKED until this finishes
for (let i = 0; i < 1_000_000_000; i++) {} // 1 second of CPU
updateDOM(); // user sees nothing during the loop
};
// requestAnimationFrame runs IN the render phase β perfect for animation
function animate() {
element.style.left = (x++) + 'px'; // guaranteed to paint every frame
requestAnimationFrame(animate); // schedule for NEXT render phase
}
requestAnimationFrame(animate);
// setTimeout(0) yields to render, rAF aligns WITH render
button.onclick = () => {
status.textContent = 'Loading...';
setTimeout(() => heavyWork(), 0); // allows repaint of 'Loading...' first
};