Jon Fletcher 2020-10-21

How to speed up First Input Delay (FID)

The TL; DR 
  • First Input Delay (FID) is the time between when a user first interacts with a page to when the browser is able to respond.
  • It's mostly caused by heavy JavaScript execution 
  • It can be improved with the use of service workers, breaking up long tasks, and reducing Javascript execution time.

Google is on a mission to clear up the metrics that really define the mobile experience. By choosing three Core Web Vitals and making them direct ranking factors, they want to make webmasters 'lives easier and users' experience better. 

This post is the second in our series on Core Web Vitals. Here you can read our posts on Largest Contentful Paint and Cumulative Layout shift.

What is First Input Delay? 

First input delay is the gap in time between when a reader first interacts with a page, say clicking a button, to the time when the browser is able to respond to the interaction. 

First input delay has been chosen as a Core Web Vital because it serves two clear purposes: 

If a user has a desired action to take on a page then this should be as fast as possible. Secondly, users need signs that the page is working behind the scenes. If a user clicks and nothing happens for long, dead seconds Google knows that we are impatient and unforgiving. Pages will get abandoned. 

This is why FID only measures the "delay" in event processing and does not measure the event processing time, or the time to update the UI after running event handlers. 

While the full load is obviously part of user experience, including it as part of FID, a direct ranking factor would incentivize developers to respond to events asynchronously

This would drastically improve the number, but would also make the real experience worse as we'd all have to wait multiple times for things to be interactive. 

It’s worth noting that Lighthouse 6.0 does not include support for FID since it is a field metric. However, Total Blocking Time (TBT) can be used in its place.

You can, however, see the metric in page speed insights as this tool can measure real-world field data.

How long should First Input Delay be?

A good first input delay is under 100ms. A nice round number, and according to famous UX lore, “0.1 second is about the limit for having the user feel that the system is reacting instantaneously’, a standard established by Jakob Nielsen in his 1993 book, Usability Engineering

A good first input delay time and your page feels instant. That’s about as close to perfect as the subjective world of the user experience ever comes to.

What causes a long First Input Delay? 

User interactions are handled by the main thread of the page, this means that the browser can't respond to user interactions while the main thread is busy. Anything that occupies the main thread is going to slow down first input delay. 

Handily...the main thread is also where Javascript is executed. This means that any conversation regarding first input delay invariably comes back to optimizing Javascript execution. 

Suspect #1: Unused Javascript

The first step for any publisher looking to improve their first input delay would be to remove any unused Javascript. Javascript libraries contain code that ends up not being used. Analyze your bundles for code that isn’t being utilized. 

To do this: 
  • Open DevTools 
  • Click Network 
  • Disable Cache 
  • Reload the page

Within Coverage, click on any URL to reveal the file in the Sources panel with a breakdown of the lines of code that executed and all the code that did not execute in red.

Bundlers such as Webpack can then analyze what constitutes each bundle, provide a treemap of the components, and allow you to see any unused or unnecessary libraries. Then you simply need to remove any unused libraries and lazyload any libraries that are not being used in the initial page load.

How to improve first input delay 

With the code that we’re not using gone, we can now address the serious business of making what we do need, faster. 

Defer any non-essential JavaScript

By default all JavaScript is render-blocking. When the browser encounters a script tag that links to an external JavaScript file, it must pause what it's doing and download, parse, compile, and execute that JavaScript. Therefore you should only load the code that's needed for the page or responding to user input. 

To cut down on unused JavaScript: 
  • Code-split your bundle into multiple chunks 
  • Defer any non-critical JavaScript, including third-party scripts, using async or defer

Break up long tasks 

Even with unused code removed, it’s likely that you will still have some long tasks on your main thread. Any piece of code that blocks the main thread for 50 ms or more can be is classed as a Long Task. 

After the first 50ms, users generally start to notice the lag where the thread is ‘blocked’ - as shown in red.

The total time that these ‘Long tasks’ take above 50ms, per task, is actually what makes up the important metric, Total Blocking Time. In the example above, the long tasks over 50ms combined gives us a Total Blocking Time of 260 ms from a total time of 500ms. 

To prevent these blocks, don’t ship all the JavaScript to your user as soon as the first page loads. Split your bundle into multiple pieces, send what's only necessary at the very beginning of the experience. 

Top tip: Learn more about code splitting with Google’s Code Lab

Preload and prefetch 

When you know the elements that make your browser interactive, you can tell the browser to fetch that resource sooner. The critical request chain is the order that these resources are prioritized and fetched.

Waiting on a waterfall of cascading fetches (e.g. JavaScript and data fetches for components) can affect interaction latency. The goal is to minimize reliance on cascading data fetches. 

Google Lighthouse classes anything on or after the third level as ‘late-discovered’. A Preload key request audit will help determine the resources to preload and stop bottlenecks that slow your first input delay.

Use a web worker 

As mentioned, blocking the main thread is one of the primary causes of input delay. What Web workers do is make it possible to run JavaScript on a separate, background thread. By moving the non-UI operations to the service worker thread will cut down on the time the main thread is blocked and improve FID. 

Web workers perform tasks without interfering with the user interface. Once created, a worker can send messages to the JavaScript code that created it by posting messages to an event handler specified by that code (and vice versa).

Get your First Input Delay under 100ms 

With these practices, you can improve your first input delay to get a ‘good rating’. Taken from a live Marfeel site, we have a FID rating of 20ms.

If you would like a mobile website that optimizes all of your core web vitals without sacrificing your content or monetization, get in touch to find out if your website is eligible for Marfeel. 

Latest Articles

‹ Back to Blog Home

Get the headlines

Sign up to get the best headlines direct to your inbox

Your name
Your email