The Calculus Behind Web Vitals
LCP is a supremum. CLS is an integral. INP is a quantile. Here is the math beneath the metrics.
The Calculus Behind Web Vitals
How derivatives, integrals, and rate-of-change thinking underpin every Core
Every time Chrome records a Core Web Vital, it's doing something that looks suspiciously like a calculus operation. It's measuring rates of change, accumulating displacement over time, finding maximum values on continuous curves, and computing percentiles across distributions. We just don't call it calculus because the marketing copy says "user experience metrics." But strip back the abstraction and you'll find that This post assumes you're comfortable with Web Vitals at a practical level and vaguely remember what a derivative is. If you remember that a derivative measures how fast something is changing and an integral measures how much of something has accumulated — you're good. We'll rebuild the rest from there. Largest Contentful Paint is deceptively simple on the surface: find the largest image or text block that renders in the viewport, record the timestamp. But "largest" is doing a lot of work. The browser is continuously evaluating a candidate function — a monotonically non-decreasing step function of rendered element areas over time. The supremum — the least upper bound — is the calculus operation hiding inside LCP. The browser doesn't just find the largest element; it tracks the running maximum of a set that grows over time. Every time a new element paints, the candidate set If you model the render timeline as a step function where each step is a new contentful paint, LCP is the x-coordinate of the final step in the staircase of the maximum-area candidate. This gives us a crucial insight: LCP is sensitive to paint order, not just paint speed. If your hero image renders at 2.4s but a larger carousel image renders at 3.8s, LCP jumps to 3.8s — even though you "optimized" the hero. The key optimization heuristic follows directly from the math: minimize Cumulative Layout Shift is the most overtly mathematical Web Vital. The name itself contains the word "cumulative" — and accumulation is what integrals do. CLS sums up every unexpected layout shift that occurs during the page's lifetime, where each shift has a score computed from two factors: the impact fraction (how much viewport area was affected) and the distance fraction (how far elements moved). If we think of the layout as a vector field — every element has a position, and shifts are displacement vectors — then CLS is the discrete integral of the magnitude of displacement, weighted by the area each displaced element occupies. The "session window" constraint (5s maximum window, 1s gap) acts as a windowing function on the integral, preventing a single late shift from dominating the entire score. Consider every visible element as a point in 2D space. When a layout shift occurs, some subset of these points move. The distance fraction captures the magnitude of the largest displacement vector in that shift, normalized by the viewport diagonal. The impact fraction captures the area of influence — the union of the element's old and new bounding rectangles divided by viewport area. This is structurally identical to computing work in physics: force (impact) multiplied by displacement (distance), summed over all events. CLS is the total work done by layout instability on the user's visual field. Interaction to Next Paint replaced First Input Delay in March 2024, and the mathematical upgrade is significant. FID measured a single point — the delay of the first input event. INP measures the near-worst-case of all interactions: specifically, the interaction at the 98th percentile of the latency distribution (or the worst interaction, if fewer than 50 interactions occur). This is a quantile function — the inverse of the cumulative distribution function (CDF) of interaction latencies. If User frustration doesn't scale linearly with latency. Research from Google's UX team and the original RAIL model suggests that frustration is closer to a step function: imperceptible below 100ms, mildly annoying from 100–200ms, and sharply negative above 200ms. If we model perceived frustration as The 200ms and 500ms thresholds aren't arbitrary — they correspond to inflection points on the frustration curve where Time to First Byte isn't technically a Core Web Vital, but it's the boundary condition that governs all others. Nothing can paint, shift, or respond to interaction until the first byte of the HTML response arrives. Mathematically, TTFB is the initial condition of the performance function — the value at What's interesting about TTFB from a calculus perspective is that it's a sum of random variables. Each component — DNS lookup, TCP handshake, TLS negotiation, request transmission, server processing — is itself a stochastic process with its own distribution. The total TTFB distribution is the convolution of these individual distributions. If DNS lookup time has distribution The practical consequence: optimizing server processing time from 200ms to 150ms might be less impactful than eliminating one round trip from the chain entirely (e.g., via connection prewarming or a CDN edge that collapses DNS + TCP + TLS into a cached connection). Removing a term from the sum is always better than shrinking a term, because you eliminate both its mean and its variance contribution. Here's where things get genuinely elegant. A performance budget is, at its core, a constrained optimization problem. You want to maximize feature richness (or some utility function In this formulation, The Lagrange multiplier λ for each constraint has a concrete interpretation: it's the shadow price of a millisecond. It tells you how much utility you sacrifice per unit of budget consumed on that vital. When λLCP is large, you're tight on your LCP budget and every additional resource that delays the largest contentful paint costs you disproportionately. When λINP is near zero, you have interaction headroom to spare. This framework explains why "just remove the third-party scripts" is reductive advice. The right question isn't "how much does this script cost in milliseconds?" but "what's the marginal utility of this script relative to the shadow price of the binding constraint?" A 50ms script that powers your checkout flow has high utility relative to the same 50ms consumed by a social share widget. The Lagrangian makes that tradeoff explicit. The calculus of Web Vitals isn't about pulling out a textbook and computing derivatives by hand. It's about recognizing that the structure of these metrics maps onto classical mathematical concepts — and that those concepts come with centuries of optimization intuition for free. The next time you're staring at a Lighthouse report, try seeing through the numbers to the functions beneath. LCP isn't a timestamp — it's the supremum of a growing set. CLS isn't a score — it's the integral of a displacement field. INP isn't a latency — it's a quantile on a distribution curve. And your performance budget isn't a spreadsheet — it's a Lagrangian with shadow prices attached to every constraint. Once you see the math, you stop optimizing metrics and start optimizing the functions that generate them. And that's where the real gains live.Why Calculus? Seriously.
LCP is a supremum problem, CLS is a definite integral over a displacement function, INP is a percentile operation on a probability distribution, and TTFB is a first-derivative boundary condition. Understanding the math doesn't just satisfy curiosity — it changes how you optimize. You stop chasing numbers and start reasoning about the shape of the underlying functions.LCP — The Area Under the Render Curve
E(t) expands, and the browser re-evaluates whether the supremum has changed.Why This Matters for Optimization
// LCP as a running supremum
const observer = new PerformanceObserver((list) => {
let maxArea = 0;
let lcpTime = 0;
for (const entry of list.getEntries()) {
// sup{A(e)} — update if new candidate is larger
if (entry.size > maxArea) {
maxArea = entry.size;
lcpTime = entry.startTime;
}
}
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
tLCP by ensuring the supremum of A(e) is reached as early as possible. In practice this means: preload the largest contentful element, ensure it doesn't get displaced by a later, larger element, and eliminate render-blocking resources that delay the paint of your intended LCP candidate.performance.getEntriesByType('largest-contentful-paint') in your console and check the size property of each entry. If the final entry isn't your hero element, you have a candidate ordering problem — not a speed problem.
CLS — Displacement as a Definite Integral
The Displacement Vector Field
// CLS session windows — a sliding integral
let sessionScores = [];
let currentWindow = { score: 0, start: 0, lastShift: 0 };
function onLayoutShift(entry) {
const gap = entry.startTime - currentWindow.lastShift;
const windowDuration = entry.startTime - currentWindow.start;
// Window boundary: gap > 1s or duration > 5s
if (gap > 1000 || windowDuration > 5000) {
sessionScores.push(currentWindow.score);
currentWindow = { score: 0, start: entry.startTime };
}
// Accumulate: ∫ IF × DF dt (discrete sum)
currentWindow.score += entry.value;
currentWindow.lastShift = entry.startTime;
}
// CLS = max over all session windows
const cls = Math.max(...sessionScores, currentWindow.score);
INP — Latency Distributions & the Derivative of Frustration
F(x) is the probability that a randomly selected interaction has latency ≤ x, then INP asks: "what latency threshold captures 98% of interactions?" This is fundamentally different from measuring means or even medians.Why the 98th Percentile Is a Derivative Insight
F(d) where d is delay, the derivative F'(d) — the rate of change of frustration — spikes at the transition thresholds.
INP Range Rating F'(d) Regime User Perception ≤ 200ms Good Low, near-zero Instant — no conscious delay 200–500ms Needs Work Steep, rapidly increasing Sluggish — user notices lag > 500ms Poor Saturated plateau Broken — user assumes failure F''(d) is at its maximum. Put differently, these are the points where the acceleration of frustration is highest. INP's thresholds are chosen at the points of maximum second derivative.// Approximate INP: 98th percentile of interaction latencies
const latencies = [];
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// duration = input delay + processing + presentation
latencies.push(entry.duration);
}
}).observe({ type: 'event', durationThreshold: 16, buffered: true });
// F⁻¹(0.98) — quantile function
function getINP() {
const sorted = latencies.slice().sort((a, b) => a - b);
const idx = Math.floor(sorted.length * 0.98) - 1;
return sorted[Math.max(0, idx)];
}
TTFB — Rate of Change at t = 0
t = 0 that constrains all subsequent behavior.The Convolution Insight
f₁(t) and TCP handshake has distribution f₂(t), the combined distribution of just those two steps is the convolution (f₁ * f₂)(t). The convolution of distributions is wider than either individual distribution — meaning variance compounds. This is why TTFB is so variable in the field even when each individual component seems stable: you're stacking five sources of variance, and the tails get fat.The Performance Budget as Lagrangian Optimization
U(features)) subject to the constraint that your Web Vitals stay within acceptable thresholds. This is precisely the setup for Lagrange multipliers.x is your resource allocation vector — every JavaScript bundle, image, font file, and third-party script is a dimension. The utility function captures business value: analytics, A/B testing, interactive features, rich media. The constraint functions map resource decisions to their Web Vital impact.The Shadow Price of a Millisecond
// Performance budget as constrained optimization
//
// Decision variables: x[i] ∈ {0, 1} for each resource i
// Utility: U(x) = Σ value[i] × x[i]
// Constraints:
// Σ lcp_cost[i] × x[i] ≤ 2500 (LCP budget, ms)
// Σ cls_risk[i] × x[i] ≤ 0.1 (CLS budget)
// Σ inp_cost[i] × x[i] ≤ 200 (INP budget, ms)
//
// This is a multidimensional knapsack problem.
// The Lagrangian relaxation gives approximate λ values
// that represent the "price per ms" on each constraint.
//
// High λ_LCP → you're LCP-constrained → prioritize render path
// High λ_INP → you're INP-constrained → prioritize main thread
// High λ_CLS → you're CLS-constrained → prioritize layout stability
Putting It All Together
Metric Calculus Concept Optimization Strategy LCP Supremum of a set function Control paint order; ensure the sup is reached early CLS Definite integral (max windowed) Minimize displacement magnitude; reduce window count INP Quantile function (inverse CDF) Compress the tail of the distribution, not the median TTFB Convolution of distributions Eliminate sequential steps; reduce variance at each stage Budget Lagrangian optimization Allocate resources by shadow price of binding constraint
web-vitals library (github.com/GoogleChrome/web-vitals) is the canonical implementation of these metrics. Read the source — particularly onCLS() and onINP() — and you'll see the session windows, percentile calculations, and supremum tracking discussed in this post implemented in ~200 lines of production JavaScript.