demo · v148

Forced Style Flush

The other half of the style timing story is forcedStyleDuration: time spent recalculating style inside an event handler because the script asked for a layout-affecting value. Click "trigger forced flushes" to make the page do exactly that, and watch the LoAF entry separate the natural style time from the forced flush time.

Heads up Origin trial. forcedStyleDuration appears alongside styleDuration on PerformanceLongAnimationFrameTiming. Numbers come from a real PerformanceObserver below.

styleDuration

ms total (style recalc)

forcedStyleDuration

ms inside handler

renderDuration

ms (paint/layout/etc)

the code

// "Forced flush" = read a layout/style value inside an event handler.
// The browser must update style/layout immediately to answer the read.
button.addEventListener("click", () => {
  for (const el of allCells) {
    el.classList.toggle("warm");   // queue a style invalidation
    const _ = el.offsetWidth;      // force style+layout flush right now
  }
});

// Observer surfaces the cost of those forced flushes:
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log({
      styleDuration:       entry.styleDuration,        // total recalc time
      forcedStyleDuration: entry.forcedStyleDuration,  // forced subset
      renderDuration:      entry.renderDuration,
    });
  }
}).observe({ type: "long-animation-frame", buffered: true });

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗