Start · Sprachen · JavaScript · Referenz · PerformanceLongAnimationFrameTiming.styleAndLayoutStart

PerformanceLongAnimationFrameTiming.styleAndLayoutStart

Eigenschaft

Liefert einen <code>DOMHighResTimeStamp</code>, der angibt, wann innerhalb eines langen Animationsframes die Stil- und Layoutberechnung begonnen hat.

seit JavaScript Chrome/Edge 123+ (Long Animation Frames API, exper Kategorie: webapi

Signatur

PerformanceLongAnimationFrameTiming.styleAndLayoutStart

Beschreibung

Die schreibgeschützte Eigenschaft styleAndLayoutStart gehört zu PerformanceLongAnimationFrameTiming, dem Eintragstyp "long-animation-frame" der Long Animation Frames API (LoAF). Sie gibt den Zeitpunkt in Millisekunden relativ zu performance.timeOrigin an, an dem der Browser im betroffenen Frame mit der Neuberechnung von Stilen und Layout begonnen hat.

Zusammen mit startTime, renderStart und duration lässt sich ein langer Frame in Phasen zerlegen:

  • Skript-/Aufgabenphase: von startTime bis renderStart
  • Vorbereitung des Renderings (requestAnimationFrame-Callbacks, ResizeObserver usw.): von renderStart bis styleAndLayoutStart
  • Stil und Layout: von styleAndLayoutStart bis startTime + duration

Die Eigenschaft eignet sich, um herauszufinden, ob ein ruckelnder Frame oder eine schlechte INP-Metrik (Interaction to Next Paint) durch aufwendige CSS-Selektoren, große DOM-Bäume oder erzwungene Layout-Neuberechnungen verursacht wird. Hat im Frame kein Rendering stattgefunden, ist der Wert 0.

Rückgabewert

Typ
DOMHighResTimeStamp (number)
Beschreibung
Zeitstempel in Millisekunden relativ zu performance.timeOrigin, an dem die Stil- und Layoutphase begonnen hat, oder 0, wenn im Frame nicht gerendert wurde.

Beispiele

Stil- und Layoutdauer langer Frames messen

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.styleAndLayoutStart) continue; // kein Rendering im Frame
    const frameEnde = entry.startTime + entry.duration;
    const layoutDauer = frameEnde - entry.styleAndLayoutStart;
    console.log(`Frame: ${entry.duration.toFixed(1)} ms, davon Stil/Layout: ${layoutDauer.toFixed(1)} ms`);
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
Frame: 142.3 ms, davon Stil/Layout: 38.7 ms

Frame in Phasen aufschlüsseln

const phasen = (entry) => {
  const ende = entry.startTime + entry.duration;
  const renderStart = entry.renderStart || ende;
  const layoutStart = entry.styleAndLayoutStart || ende;
  return {
    skripte: Math.round(renderStart - entry.startTime),
    renderVorbereitung: Math.round(layoutStart - renderStart),
    stilUndLayout: Math.round(ende - layoutStart)
  };
};

new PerformanceObserver((list) => {
  list.getEntries().forEach((e) => console.table(phasen(e)));
}).observe({ type: 'long-animation-frame', buffered: true });
┌────────────────────┬────────┐ │ skripte │ 91 │ │ renderVorbereitung │ 12 │ │ stilUndLayout │ 39 │ └────────────────────┴────────┘

Layout-lastige Frames mit Feature-Erkennung an ein Monitoring senden

if (PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame')) {
  new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (!entry.styleAndLayoutStart) continue;
      const layoutMs = entry.startTime + entry.duration - entry.styleAndLayoutStart;
      if (layoutMs > 50) {
        navigator.sendBeacon('/rum/layout', JSON.stringify({
          url: location.pathname,
          layoutMs: Math.round(layoutMs),
          frameMs: Math.round(entry.duration)
        }));
      }
    }
  }).observe({ type: 'long-animation-frame', buffered: true });
} else {
  console.log('Long Animation Frames API wird nicht unterstützt.');
}

// Wichtig · Fallstricke

  • Kompatibilität: Nur in Chromium-Browsern (Chrome/Edge ab 123) verfügbar; Firefox und Safari unterstützen die Long Animation Frames API nicht. Vorher immer PerformanceObserver.supportedEntryTypes prüfen.
  • Der Wert ist 0, wenn im Frame kein Rendering stattfand – ohne Prüfung entstehen unsinnig große Dauern.
  • Erzwungene synchrone Layouts (z. B. Lesen von offsetHeight direkt nach DOM-Änderungen) fallen nicht in diese Phase, sondern in die Skriptzeit; siehe dazu forcedStyleAndLayoutDuration der einzelnen PerformanceScriptTiming-Einträge in scripts.
  • Einträge werden nur für Frames über 50 ms erzeugt; kurze Frames lassen sich damit nicht analysieren.
  • Die Zeitauflösung kann aus Sicherheitsgründen (Schutz vor Timing-Angriffen) reduziert sein, besonders ohne Cross-Origin-Isolation.