Professor Sloth

Free web performance master class

Learn about web performance and how to make your site faster, delivered straight to your inbox.

Measuring First Input Delay (FID)

Measuring First Input Delay (FID)

Warning. First Input Delay (FID) was retired as a Core Web Vital in 2024 due to several shortcomings in measuring interactivity. It was replaced with Interaction to Next Paint.

First Input Delay (FID) is a retired metric that measured how long the browser took to respond to the first user input event. It’s one of several Core Web Vital metrics that measure how real users perceive the performance of modern web applications. New measurements like First Input Delay are increasingly important as JavaScript and SPA’s do more work on the client side.

First Input Delay

Delays to the first user input are caused when the browser is busy downloading assets, parsing scripts, or executing blocking operations. The page appears unresponsive when the user interacts with a busy browser by either clicking or typing. FID measures this unresponsive time, but does not include the time taken in the event handlers themselves.

First Input Delay isn’t just an important measure of user experience. It and other Core Web Vital metrics impact SEO because Google will soon consider them when ranking search results.

In this example, the FID is captured and shown in the console. The page has some slow JavaScript which blocks the browser’s main thread on page load:

Largest Contentful Paint Example
First Input Delay Example. Slow JavaScript evaluation delays the user's first click (yellow).

First Input Delay will be different for every application, but Google has provided basic guidance on acceptable FID times:

First Input Delay threshold recommendations from Google.
First Input Delay threshold recommendations from Google.

What Causes First Input Delay?

Heavy JavaScript is the main cause of long first input delays. Both initial payload and ongoing execution can be culprits.

Heavy Upfront JavaScript Payloads

Large JavaScript bundles can take a long time for the browser to parse and evaluate. Inputs are delayed because they must wait for the page to load all referenced JavaScript. Large bundles are often caused by excessive third party dependencies or the inclusion of code that is not needed by the current page.

Long Running JavaScript

Long FID times occur even after all JavaScript has been loaded. Any long running task in JavaScript runs on the main thread. User inputs are blocked until the task finishes and the main thread is free to handle the input. Any poorly optimized code can cause this issue. JS frameworks like React and Angular are often culprits when coding mistakes cause excessive re-rendering.

Measuring First Input Delay With The Event Timing API

The Event Timing API exposes first input delay measurements through JavaScript. It is currently supported in Blink-based browsers, such as Chrome, Edge, and Opera. NOTE: As a draft standard, there are occasionally changes to how FID is determined.

We can test the API’s behavior with a little code:


new PerformanceObserver(entryList => {
    var fidEntry = entryList.getEntries()[0];
    var fid = fidEntry.processingStart - fidEntry.startTime;
    console.log("First Input Delay: " + fid);
    // Output:
    //   First Input Delay: 1241.0949999466538
}).observe({ type: "first-input", buffered: true });
Retrieving the First Input Delay using the Event Timing API

The buffered: true option returns the entry even if it occurred before the PerformanceObserver was configured.

First Input Delay Quirks And Gotchas

While the measurement itself is straightforward, FID measurements have several quirks that you should be aware of.

1. First Input Delay Measurements Don’t Always Occur

Not every page view results in a FID entry. If the user never interacts with the page, no first input entry will be recorded.

2. User Input Includes Clicks On Non-Interactive Elements

The First Input Delay measurement is triggered even when the user clicks non-interactive elements like the page background. This causes unintentional or frustrated user actions to be reflected in the FID measurements:

Useless user interactions still result in First Input Delay measurements
Useless user interactions still result in First Input Delay measurements

3. First Input Delay Measurements Are Highly Variable

The same page can return a wide range of FID values between different page loads and users. User interaction can happen at any time. This user variability is reflected in FID values because of the varying states of page readiness:

User interaction timing impacts First Input Delay Measurements
User interaction timing impacts First Input Delay Measurements

4. Don’t Measure Pages Loaded In The Background!

First Input Delay should not be measured when the page is loaded in a background tab. The measurement is of questionable value because the first interaction happens long after the tab is loaded. An additional check prevents measurement of background tabs:


var hiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;

document.addEventListener('visibilitychange', (event) => {
    hiddenTime = Math.min(hiddenTime, event.timeStamp);
}, { once: true });

new PerformanceObserver(entryList => {
    var fidEntry = entryList.getEntries()[0];
    if (fidEntry.startTime < hiddenTime) {
        var fid = fidEntry.processingStart - fidEntry.startTime;
        console.log("First Input Delay: " + fid);
    }
}).observe({ type: "first-input", buffered: true });
Don't measure First Input Delay in background tabs

5. Event Timing API Feature Detection

Not all browsers support the Event Timing API. Try/catch is the only reliable way to detect the feature because some browsers throw an exception when the API is used:


try {
    new PerformanceObserver(entryList => {
        var fidEntry = entryList.getEntries()[0];
        var fid = fidEntry.processingStart - fidEntry.startTime;
        console.log("First Input Delay: " + fid);
    })
    // Some browsers throw when 'type' is passed:
    .observe({ type: "first-input", buffered: true });
}
catch (e) {
    // The Event Timing API is not supported by this browser
}
Detect the Event Timing API with try/catch

Conclusion

First Input Delay helps you understand how real users perceive the performance of page interactions. Gain a more complete understanding of your frontend performance by measuring the other two Web Vitals metrics: Largest Contentful Paint and Cumulative Layout Shift.

Looking for more? Check out the Definitive Guide to Measuring Web Performance.

Jordan Griffin
VP Engineering Request Metrics