Vanilla JavaScript Projects

Project 44, Hardware and performance

Performance Monitor Widget

Watch this page's Core Web Vitals update live. Press the buttons to cause a layout shift or a slow task and see exactly how the scores change.

1.2s0.08 LCPCLS
Main API
PerformanceObserver
Measures
LCP, CLS, INP, FCP, TTFB
Dependencies
None
Your browser
Checking

Core Web Vitals for this page

INP needs you to interact, so click the buttons below.

LCP, loading
-
Waiting
CLS, visual stability
0
Waiting
INP, responsiveness
-
Click something
-First paint (FCP)
-Server response (TTFB)
-Frames per second
-JS memory

This box appeared without reserved space, which moves the content below it.

Frame rate

Long tasks (over 50 ms)

  • None yet

How it works

  1. Observe entriesA PerformanceObserver subscribes to each entry type. buffered: true replays what happened before the script ran.
  2. Compute the metricCLS groups shifts into session windows. INP takes the slowest interaction. LCP takes the last large paint.
  3. Rate itEach value is compared with the official thresholds, for example LCP is good under 2.5 seconds.
new PerformanceObserver((list) => {
  const last = list.getEntries().at(-1);
  report("LCP", last.startTime);                        // good under 2500 ms
}).observe({ type: "largest-contentful-paint", buffered: true });

let cls = 0;
new PerformanceObserver((list) => {
  for (const e of list.getEntries()) if (!e.hadRecentInput) cls += e.value;
  report("CLS", cls);                                   // good under 0.1
}).observe({ type: "layout-shift", buffered: true });

new PerformanceObserver((list) => {
  for (const e of list.getEntries()) if (e.interactionId) inp = Math.max(inp, e.duration);
}).observe({ type: "event", durationThreshold: 16, buffered: true });