[{"data":1,"prerenderedAt":1206},["ShallowReactive",2],{"content:\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002F":3,"surroundings:\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002F":1197},{"id":4,"title":5,"body":6,"description":1190,"extension":1191,"meta":1192,"navigation":431,"path":1193,"seo":1194,"stem":1195,"__hash__":1196},"content\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Findex.md","Optimizing First Input Delay (FID): Engineering Strategies for Sub-100ms Responsiveness",{"type":7,"value":8,"toc":1178},"minimark",[9,13,28,33,53,59,93,97,121,125,176,180,194,198,236,240,255,259,288,292,303,307,331,335,355,359,381,384,389,394,609,613,862,866,1057,1059,1063,1129,1131,1135,1141,1159,1165,1174],[10,11,5],"h1",{"id":12},"optimizing-first-input-delay-fid-engineering-strategies-for-sub-100ms-responsiveness",[14,15,16,17,21,22,27],"p",{},"First Input Delay (FID) quantifies the time elapsed between a user's initial interaction (click, tap, keypress) and the browser's ability to process the corresponding event handlers. While the industry is transitioning toward Interaction to Next Paint (INP), FID remains a critical diagnostic baseline for initial load responsiveness. Achieving the ",[18,19,20],"code",{},"\u003C100ms"," threshold requires rigorous main thread management, strategic script deferral, and precise event listener configuration. This guide provides a deep-dive engineering workflow for ",[23,24,26],"a",{"href":25},"\u002Fcore-web-vitals-measurement\u002F","Core Web Vitals & Measurement"," compliance, focusing on actionable partitioning techniques, tooling configuration, and field-data validation.",[29,30,32],"h2",{"id":31},"_1-diagnostic-workflow-baseline-measurement","1. Diagnostic Workflow & Baseline Measurement",[14,34,35,36,39,40,43,44,48,49,52],{},"Before implementing optimizations, establish a reproducible baseline using field and lab data. Utilize the ",[18,37,38],{},"PerformanceObserver"," API and the ",[18,41,42],{},"web-vitals"," library to capture real-user FID metrics, then correlate them with lab simulations. Cross-reference your findings with ",[23,45,47],{"href":46},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002F","Measuring LCP with Chrome DevTools"," to identify overlapping resource contention during the critical rendering path. Focus on the 'Long Tasks' panel to isolate scripts exceeding ",[18,50,51],{},"50ms"," execution time, as these directly block input event processing.",[14,54,55],{},[56,57,58],"strong",{},"Diagnostic Steps:",[60,61,62,69,79,82],"ul",{},[63,64,65,66,68],"li",{},"Deploy ",[18,67,42],{}," v4+ with attribution reporting to capture exact event targets and blocking durations.",[63,70,71,72,75,76,78],{},"Capture ",[18,73,74],{},"PerformanceLongTaskTiming"," entries in production via a custom ",[18,77,38],{}," to map blocking scripts to specific bundles.",[63,80,81],{},"Map long tasks to first-party hydration code or third-party SDKs using build-time source maps.",[63,83,84,85,88,89,92],{},"Validate against 75th percentile CrUX field data thresholds; lab tools (Lighthouse) should simulate ",[18,86,87],{},"4x CPU throttling"," and ",[18,90,91],{},"Fast 3G"," to approximate real-world constraints.",[29,94,96],{"id":95},"_2-main-thread-blocking-analysis-long-task-partitioning","2. Main Thread Blocking Analysis & Long Task Partitioning",[14,98,99,100,104,105,108,109,112,113,116,117,120],{},"FID degradation is almost exclusively caused by synchronous JavaScript execution on the main thread. To maintain sub-100ms responsiveness, break monolithic initialization routines into micro-tasks. Refer to ",[23,101,103],{"href":102},"\u002Fcore-web-vitals-measurement\u002Funderstanding-core-web-vitals-thresholds\u002F","Understanding Core Web Vitals Thresholds"," to contextualize your 90th percentile field data against the ",[18,106,107],{},"100ms"," good \u002F ",[18,110,111],{},"300ms"," poor boundaries. Implement task splitting using ",[18,114,115],{},"setTimeout(..., 0)"," or the modern ",[18,118,119],{},"scheduler.yield()"," API to yield control back to the browser's event loop, allowing pending input events to be processed immediately.",[14,122,123],{},[56,124,58],{},[60,126,127,134,147,165],{},[63,128,129,130,133],{},"Audit hydration scripts for synchronous DOM manipulation or heavy reflow triggers during ",[18,131,132],{},"DOMContentLoaded",".",[63,135,136,137,139,140,143,144,133],{},"Implement cooperative scheduling with ",[18,138,119],{}," (with ",[18,141,142],{},"setTimeout"," fallback) to cap continuous execution at ",[18,145,146],{},"~50ms",[63,148,149,150,153,154,157,158,161,162,133],{},"Defer non-critical analytics, chat widgets, and tracking pixels using ",[18,151,152],{},"async","\u002F",[18,155,156],{},"defer"," or dynamic ",[18,159,160],{},"import()"," after ",[18,163,164],{},"window.load",[63,166,167,168,171,172,175],{},"Monitor main thread idle time using the ",[18,169,170],{},"Performance API"," (",[18,173,174],{},"PerformanceEntry.entryType === 'longtask'",") to verify partitioning efficacy.",[29,177,179],{"id":178},"_3-event-listener-optimization-input-prioritization","3. Event Listener Optimization & Input Prioritization",[14,181,182,183,186,187,190,191,193],{},"Inefficient event binding directly inflates input latency. Attach listeners only when necessary and utilize the ",[18,184,185],{},"passive"," flag for scroll and ",[18,188,189],{},"touchmove"," events to bypass default blocking behavior. For high-frequency inputs, Implementing debouncing and throttling for scroll events prevents queue saturation and ensures the main thread remains available for primary user interactions. Prioritize critical UI handlers (e.g., navigation toggles, form submission) by registering them during the ",[18,192,132],{}," phase, before heavy hydration begins.",[14,195,196],{},[56,197,58],{},[60,199,200,211,222,229],{},[63,201,202,203,206,207,210],{},"Audit all ",[18,204,205],{},"addEventListener"," calls for missing ",[18,208,209],{},"{ passive: true }"," on scroll\u002Ftouch handlers.",[63,212,213,214,217,218,221],{},"Replace inline ",[18,215,216],{},"on*"," handlers with delegated event listeners attached to ",[18,219,220],{},"document"," or container elements.",[63,223,224,225,228],{},"Implement ",[18,226,227],{},"requestAnimationFrame"," for visual updates triggered by input to align with the compositor's refresh cycle.",[63,230,231,232,235],{},"Verify ",[18,233,234],{},"touch-action"," CSS properties to prevent synthetic delays and unintended gesture interference.",[29,237,239],{"id":238},"_4-offloading-to-web-workers-async-scheduling","4. Offloading to Web Workers & Async Scheduling",[14,241,242,243,246,247,250,251,254],{},"Computationally heavy operations (data parsing, cryptographic hashing, complex DOM calculations) must be migrated off the main thread. Web Workers provide a dedicated execution context, completely eliminating FID impact for background processing. Use ",[18,244,245],{},"postMessage"," or ",[18,248,249],{},"SharedArrayBuffer"," for efficient data transfer. For legacy environments lacking Worker support, implement async chunking with ",[18,252,253],{},"Promise.resolve().then()"," to yield to the event loop. Monitor worker initialization overhead to ensure it doesn't introduce secondary latency spikes.",[14,256,257],{},[56,258,58],{},[60,260,261,267,278,281],{},[63,262,263,264,133],{},"Identify CPU-bound functions using Chrome Performance Profiler's \"Bottom-Up\" view and isolate functions exceeding ",[18,265,266],{},"20ms",[63,268,269,270,273,274,277],{},"Wrap heavy computations in dedicated Worker modules, leveraging Vite's ",[18,271,272],{},"?worker"," or Webpack's ",[18,275,276],{},"worker-loader"," for seamless bundling.",[63,279,280],{},"Implement message queueing for batched data processing to prevent worker thread starvation.",[63,282,283,284,287],{},"Validate fallback behavior for unsupported browsers using feature detection (",[18,285,286],{},"typeof Worker !== 'undefined'",") and graceful degradation.",[29,289,291],{"id":290},"_5-mobile-specific-latency-mitigation","5. Mobile-Specific Latency Mitigation",[14,293,294,295,298,299,302],{},"Mobile devices introduce unique latency vectors, including compositor thread handoffs, 300ms tap delays, and aggressive CPU throttling. Reducing input latency on mobile touch screens requires explicit viewport configuration (",[18,296,297],{},"width=device-width, initial-scale=1",") and CSS ",[18,300,301],{},"touch-action: manipulation"," declarations. Additionally, pre-warm the main thread by prioritizing critical CSS and deferring non-essential JavaScript until after First Contentful Paint (FCP).",[14,304,305],{},[56,306,58],{},[60,308,309,316,325,328],{},[63,310,311,312,315],{},"Verify viewport meta tag prevents synthetic tap delays; ensure ",[18,313,314],{},"user-scalable=no"," is avoided unless strictly necessary for accessibility compliance.",[63,317,318,319,321,322,324],{},"Apply ",[18,320,301],{}," to all interactive elements to disable double-tap zoom and eliminate ",[18,323,111],{}," delay.",[63,326,327],{},"Test on throttled 4G and mid-tier mobile CPUs (Moto G4 \u002F 4x slowdown) to simulate real-world hardware constraints.",[63,329,330],{},"Eliminate layout thrashing during initial touch events by batching DOM reads\u002Fwrites and avoiding forced synchronous layouts.",[29,332,334],{"id":333},"_6-transitioning-to-interaction-to-next-paint-inp","6. Transitioning to Interaction to Next Paint (INP)",[14,336,337,338,342,343,346,347,350,351,354],{},"As Google phases out FID in favor of INP, the optimization principles remain identical but expand to cover all interactions, not just the first. ",[23,339,341],{"href":340},"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Fimproving-inp-for-complex-single-page-applications\u002F","Improving INP for complex single page applications"," requires continuous monitoring of presentation delay, processing delay, and event callback duration. Maintain the ",[18,344,345],{},"\u003C200ms"," INP threshold by applying the same main thread partitioning strategies, while adding presentation optimization (e.g., ",[18,348,349],{},"content-visibility",", ",[18,352,353],{},"will-change",") to reduce paint latency.",[14,356,357],{},[56,358,58],{},[60,360,361,364,371,378],{},[63,362,363],{},"Deploy INP attribution tracking alongside legacy FID to capture processing vs. presentation delay breakdowns.",[63,365,366,367,370],{},"Analyze presentation delay vs. processing delay ratios; target ",[18,368,369],{},"\u003C16ms"," for paint operations to avoid frame drops.",[63,372,373,374,377],{},"Optimize CSS rendering paths to minimize paint blocking by leveraging ",[18,375,376],{},"contain: layout style paint"," and avoiding expensive selectors.",[63,379,380],{},"Implement progressive enhancement for route transitions to ensure interactive elements remain responsive during navigation.",[382,383],"hr",{},[385,386,388],"h3",{"id":387},"production-implementations","Production Implementations",[390,391,393],"h4",{"id":392},"fid-attribution-real-user-monitoring","FID Attribution & Real-User Monitoring",[395,396,401],"pre",{"className":397,"code":398,"language":399,"meta":400,"style":400},"language-javascript shiki shiki-themes github-dark-high-contrast github-dark-high-contrast github-light-high-contrast","import { onFID } from 'web-vitals';\n\nonFID(({ name, value, delta, id, attribution }) => {\n console.log(`FID: ${value}ms | Event Target: ${attribution.eventTarget}`);\n console.log(`Blocking Task: ${attribution.loadState}`);\n \n \u002F\u002F Send to RUM endpoint via Beacon API\n navigator.sendBeacon('\u002Fanalytics\u002Ffid', JSON.stringify({\n name, value, delta, id, \n target: attribution.eventTarget?.tagName,\n loadState: attribution.loadState\n }));\n}, { reportAllChanges: true });\n","javascript","",[18,402,403,426,433,476,509,532,538,545,573,579,585,591,597],{"__ignoreMap":400},[404,405,408,412,416,419,423],"span",{"class":406,"line":407},"line",1,[404,409,411],{"class":410},"sCJTb","import",[404,413,415],{"class":414},"s3sCt"," { onFID } ",[404,417,418],{"class":410},"from",[404,420,422],{"class":421},"sJdzJ"," 'web-vitals'",[404,424,425],{"class":414},";\n",[404,427,429],{"class":406,"line":428},2,[404,430,432],{"emptyLinePlaceholder":431},true,"\n",[404,434,436,440,443,447,449,452,454,457,459,462,464,467,470,473],{"class":406,"line":435},3,[404,437,439],{"class":438},"sGhOu","onFID",[404,441,442],{"class":414},"(({ ",[404,444,446],{"class":445},"spFnL","name",[404,448,350],{"class":414},[404,450,451],{"class":445},"value",[404,453,350],{"class":414},[404,455,456],{"class":445},"delta",[404,458,350],{"class":414},[404,460,461],{"class":445},"id",[404,463,350],{"class":414},[404,465,466],{"class":445},"attribution",[404,468,469],{"class":414}," }) ",[404,471,472],{"class":410},"=>",[404,474,475],{"class":414}," {\n",[404,477,479,482,485,488,491,493,496,498,500,503,506],{"class":406,"line":478},4,[404,480,481],{"class":414}," console.",[404,483,484],{"class":438},"log",[404,486,487],{"class":414},"(",[404,489,490],{"class":421},"`FID: ${",[404,492,451],{"class":414},[404,494,495],{"class":421},"}ms | Event Target: ${",[404,497,466],{"class":414},[404,499,133],{"class":421},[404,501,502],{"class":414},"eventTarget",[404,504,505],{"class":421},"}`",[404,507,508],{"class":414},");\n",[404,510,512,514,516,518,521,523,525,528,530],{"class":406,"line":511},5,[404,513,481],{"class":414},[404,515,484],{"class":438},[404,517,487],{"class":414},[404,519,520],{"class":421},"`Blocking Task: ${",[404,522,466],{"class":414},[404,524,133],{"class":421},[404,526,527],{"class":414},"loadState",[404,529,505],{"class":421},[404,531,508],{"class":414},[404,533,535],{"class":406,"line":534},6,[404,536,537],{"class":414}," \n",[404,539,541],{"class":406,"line":540},7,[404,542,544],{"class":543},"sXJMR"," \u002F\u002F Send to RUM endpoint via Beacon API\n",[404,546,548,551,554,556,559,561,565,567,570],{"class":406,"line":547},8,[404,549,550],{"class":414}," navigator.",[404,552,553],{"class":438},"sendBeacon",[404,555,487],{"class":414},[404,557,558],{"class":421},"'\u002Fanalytics\u002Ffid'",[404,560,350],{"class":414},[404,562,564],{"class":563},"s5hCx","JSON",[404,566,133],{"class":414},[404,568,569],{"class":438},"stringify",[404,571,572],{"class":414},"({\n",[404,574,576],{"class":406,"line":575},9,[404,577,578],{"class":414}," name, value, delta, id, \n",[404,580,582],{"class":406,"line":581},10,[404,583,584],{"class":414}," target: attribution.eventTarget?.tagName,\n",[404,586,588],{"class":406,"line":587},11,[404,589,590],{"class":414}," loadState: attribution.loadState\n",[404,592,594],{"class":406,"line":593},12,[404,595,596],{"class":414}," }));\n",[404,598,600,603,606],{"class":406,"line":599},13,[404,601,602],{"class":414},"}, { reportAllChanges: ",[404,604,605],{"class":563},"true",[404,607,608],{"class":414}," });\n",[390,610,612],{"id":611},"cooperative-task-partitioning","Cooperative Task Partitioning",[395,614,616],{"className":397,"code":615,"language":399,"meta":400,"style":400},"function partitionTask(task, chunkSize = 50) {\n let index = 0;\n function runChunk() {\n const start = performance.now();\n while (index \u003C task.length && (performance.now() - start) \u003C chunkSize) {\n task[index]();\n index++;\n }\n if (index \u003C task.length) {\n \u002F\u002F Yield to main thread to process pending input events\n if (typeof scheduler !== 'undefined' && scheduler.yield) {\n scheduler.yield().then(runChunk);\n } else {\n setTimeout(runChunk, 0);\n }\n }\n }\n runChunk();\n}\n",[18,617,618,645,661,672,691,730,735,745,750,765,770,793,810,820,834,839,844,849,856],{"__ignoreMap":400},[404,619,620,623,626,628,631,633,636,639,642],{"class":406,"line":407},[404,621,622],{"class":410},"function",[404,624,625],{"class":438}," partitionTask",[404,627,487],{"class":414},[404,629,630],{"class":445},"task",[404,632,350],{"class":414},[404,634,635],{"class":445},"chunkSize",[404,637,638],{"class":410}," =",[404,640,641],{"class":563}," 50",[404,643,644],{"class":414},") {\n",[404,646,647,650,653,656,659],{"class":406,"line":428},[404,648,649],{"class":410}," let",[404,651,652],{"class":414}," index ",[404,654,655],{"class":410},"=",[404,657,658],{"class":563}," 0",[404,660,425],{"class":414},[404,662,663,666,669],{"class":406,"line":435},[404,664,665],{"class":410}," function",[404,667,668],{"class":438}," runChunk",[404,670,671],{"class":414},"() {\n",[404,673,674,677,680,682,685,688],{"class":406,"line":478},[404,675,676],{"class":410}," const",[404,678,679],{"class":563}," start",[404,681,638],{"class":410},[404,683,684],{"class":414}," performance.",[404,686,687],{"class":438},"now",[404,689,690],{"class":414},"();\n",[404,692,693,696,699,702,705,708,711,714,716,719,722,725,727],{"class":406,"line":511},[404,694,695],{"class":410}," while",[404,697,698],{"class":414}," (index ",[404,700,701],{"class":410},"\u003C",[404,703,704],{"class":414}," task.",[404,706,707],{"class":563},"length",[404,709,710],{"class":410}," &&",[404,712,713],{"class":414}," (performance.",[404,715,687],{"class":438},[404,717,718],{"class":414},"() ",[404,720,721],{"class":410},"-",[404,723,724],{"class":414}," start) ",[404,726,701],{"class":410},[404,728,729],{"class":414}," chunkSize) {\n",[404,731,732],{"class":406,"line":534},[404,733,734],{"class":414}," task[index]();\n",[404,736,737,740,743],{"class":406,"line":540},[404,738,739],{"class":414}," index",[404,741,742],{"class":410},"++",[404,744,425],{"class":414},[404,746,747],{"class":406,"line":547},[404,748,749],{"class":414}," }\n",[404,751,752,755,757,759,761,763],{"class":406,"line":575},[404,753,754],{"class":410}," if",[404,756,698],{"class":414},[404,758,701],{"class":410},[404,760,704],{"class":414},[404,762,707],{"class":563},[404,764,644],{"class":414},[404,766,767],{"class":406,"line":581},[404,768,769],{"class":543}," \u002F\u002F Yield to main thread to process pending input events\n",[404,771,772,774,776,779,782,785,788,790],{"class":406,"line":587},[404,773,754],{"class":410},[404,775,171],{"class":414},[404,777,778],{"class":410},"typeof",[404,780,781],{"class":414}," scheduler ",[404,783,784],{"class":410},"!==",[404,786,787],{"class":421}," 'undefined'",[404,789,710],{"class":410},[404,791,792],{"class":414}," scheduler.yield) {\n",[404,794,795,798,801,804,807],{"class":406,"line":593},[404,796,797],{"class":414}," scheduler.",[404,799,800],{"class":438},"yield",[404,802,803],{"class":414},"().",[404,805,806],{"class":438},"then",[404,808,809],{"class":414},"(runChunk);\n",[404,811,812,815,818],{"class":406,"line":599},[404,813,814],{"class":414}," } ",[404,816,817],{"class":410},"else",[404,819,475],{"class":414},[404,821,823,826,829,832],{"class":406,"line":822},14,[404,824,825],{"class":438}," setTimeout",[404,827,828],{"class":414},"(runChunk, ",[404,830,831],{"class":563},"0",[404,833,508],{"class":414},[404,835,837],{"class":406,"line":836},15,[404,838,749],{"class":414},[404,840,842],{"class":406,"line":841},16,[404,843,749],{"class":414},[404,845,847],{"class":406,"line":846},17,[404,848,749],{"class":414},[404,850,852,854],{"class":406,"line":851},18,[404,853,668],{"class":438},[404,855,690],{"class":414},[404,857,859],{"class":406,"line":858},19,[404,860,861],{"class":414},"}\n",[390,863,865],{"id":864},"passive-event-listener-implementation","Passive Event Listener Implementation",[395,867,869],{"className":397,"code":868,"language":399,"meta":400,"style":400},"\u002F\u002F Feature detection for passive support\nlet passiveSupported = false;\ntry {\n const opts = Object.defineProperty({}, 'passive', {\n get() { passiveSupported = true; }\n });\n window.addEventListener('test', null, opts);\n window.removeEventListener('test', null, opts);\n} catch (e) {}\n\n\u002F\u002F Apply to scroll\u002Ftouch handlers\nconst passiveOpts = passiveSupported ? { passive: true } : false;\nwindow.addEventListener('scroll', handleScroll, passiveOpts);\nwindow.addEventListener('touchmove', handleTouch, passiveOpts);\n",[18,870,871,876,891,898,922,938,942,962,979,990,994,999,1028,1043],{"__ignoreMap":400},[404,872,873],{"class":406,"line":407},[404,874,875],{"class":543},"\u002F\u002F Feature detection for passive support\n",[404,877,878,881,884,886,889],{"class":406,"line":428},[404,879,880],{"class":410},"let",[404,882,883],{"class":414}," passiveSupported ",[404,885,655],{"class":410},[404,887,888],{"class":563}," false",[404,890,425],{"class":414},[404,892,893,896],{"class":406,"line":435},[404,894,895],{"class":410},"try",[404,897,475],{"class":414},[404,899,900,902,905,907,910,913,916,919],{"class":406,"line":478},[404,901,676],{"class":410},[404,903,904],{"class":563}," opts",[404,906,638],{"class":410},[404,908,909],{"class":414}," Object.",[404,911,912],{"class":438},"defineProperty",[404,914,915],{"class":414},"({}, ",[404,917,918],{"class":421},"'passive'",[404,920,921],{"class":414},", {\n",[404,923,924,927,930,932,935],{"class":406,"line":511},[404,925,926],{"class":438}," get",[404,928,929],{"class":414},"() { passiveSupported ",[404,931,655],{"class":410},[404,933,934],{"class":563}," true",[404,936,937],{"class":414},"; }\n",[404,939,940],{"class":406,"line":534},[404,941,608],{"class":414},[404,943,944,947,949,951,954,956,959],{"class":406,"line":540},[404,945,946],{"class":414}," window.",[404,948,205],{"class":438},[404,950,487],{"class":414},[404,952,953],{"class":421},"'test'",[404,955,350],{"class":414},[404,957,958],{"class":563},"null",[404,960,961],{"class":414},", opts);\n",[404,963,964,966,969,971,973,975,977],{"class":406,"line":547},[404,965,946],{"class":414},[404,967,968],{"class":438},"removeEventListener",[404,970,487],{"class":414},[404,972,953],{"class":421},[404,974,350],{"class":414},[404,976,958],{"class":563},[404,978,961],{"class":414},[404,980,981,984,987],{"class":406,"line":575},[404,982,983],{"class":414},"} ",[404,985,986],{"class":410},"catch",[404,988,989],{"class":414}," (e) {}\n",[404,991,992],{"class":406,"line":581},[404,993,432],{"emptyLinePlaceholder":431},[404,995,996],{"class":406,"line":587},[404,997,998],{"class":543},"\u002F\u002F Apply to scroll\u002Ftouch handlers\n",[404,1000,1001,1004,1007,1009,1011,1014,1017,1019,1021,1024,1026],{"class":406,"line":593},[404,1002,1003],{"class":410},"const",[404,1005,1006],{"class":563}," passiveOpts",[404,1008,638],{"class":410},[404,1010,883],{"class":414},[404,1012,1013],{"class":410},"?",[404,1015,1016],{"class":414}," { passive: ",[404,1018,605],{"class":563},[404,1020,814],{"class":414},[404,1022,1023],{"class":410},":",[404,1025,888],{"class":563},[404,1027,425],{"class":414},[404,1029,1030,1033,1035,1037,1040],{"class":406,"line":599},[404,1031,1032],{"class":414},"window.",[404,1034,205],{"class":438},[404,1036,487],{"class":414},[404,1038,1039],{"class":421},"'scroll'",[404,1041,1042],{"class":414},", handleScroll, passiveOpts);\n",[404,1044,1045,1047,1049,1051,1054],{"class":406,"line":822},[404,1046,1032],{"class":414},[404,1048,205],{"class":438},[404,1050,487],{"class":414},[404,1052,1053],{"class":421},"'touchmove'",[404,1055,1056],{"class":414},", handleTouch, passiveOpts);\n",[382,1058],{},[385,1060,1062],{"id":1061},"common-mistakes","Common Mistakes",[60,1064,1065,1075,1091,1108,1114],{},[63,1066,1067,1070,1071,1074],{},[56,1068,1069],{},"Executing synchronous XHR or heavy JSON parsing during initial page load:"," Blocks the main thread until network I\u002FO completes. Replace with ",[18,1072,1073],{},"fetch()"," and stream parsing or defer until post-FCP.",[63,1076,1077,1083,1084,1086,1087,1090],{},[56,1078,1079,1080,1082],{},"Omitting the ",[18,1081,185],{}," flag on scroll\u002Ftouchmove listeners:"," Forces the main thread to wait for layout recalculation before scrolling. Always use ",[18,1085,209],{}," unless ",[18,1088,1089],{},"preventDefault()"," is strictly required.",[63,1092,1093,1101,1102,1104,1105,1107],{},[56,1094,1095,1096,153,1098,1100],{},"Loading third-party analytics or marketing pixels without ",[18,1097,152],{},[18,1099,156],{}," attributes:"," Injects blocking scripts into the critical path. Use ",[18,1103,152],{}," for independent scripts or dynamic ",[18,1106,160],{}," for controlled execution.",[63,1109,1110,1113],{},[56,1111,1112],{},"Relying solely on lab tools (Lighthouse) without validating against CrUX field data:"," Lab data simulates idealized conditions. Field data (75th percentile) reflects real network variability and device fragmentation.",[63,1115,1116,1122,1123,1125,1126,1128],{},[56,1117,1118,1119,1121],{},"Overusing ",[18,1120,115],{}," without proper chunking, causing excessive event loop overhead:"," Creates microtask starvation and UI jitter. Cap execution windows at ",[18,1124,146],{}," and prefer ",[18,1127,119],{}," for modern browsers.",[382,1130],{},[385,1132,1134],{"id":1133},"faq","FAQ",[14,1136,1137,1140],{},[56,1138,1139],{},"Why does FID only measure the first interaction, and how does it differ from INP?","\nFID captures the latency of the very first user interaction after page load, which heavily reflects initial script execution and hydration blocking. INP (Interaction to Next Paint) measures responsiveness across all interactions during a page visit, providing a more holistic view of sustained interactivity. Optimizing FID establishes the foundational main thread hygiene required for INP compliance.",[14,1142,1143,1146,1147,1150,1151,88,1153,1155,1156,1158],{},[56,1144,1145],{},"What is the exact threshold for a 'good' FID score?","\nA 'good' FID score is ",[18,1148,1149],{},"100 milliseconds"," or less, measured at the 75th percentile across all page loads. Scores between ",[18,1152,107],{},[18,1154,111],{}," require improvement, while anything exceeding ",[18,1157,111],{}," is considered poor and will negatively impact user experience and search ranking signals.",[14,1160,1161,1164],{},[56,1162,1163],{},"Can Web Workers completely eliminate FID?","\nWeb Workers eliminate main thread blocking for background computations, but they cannot process DOM updates or handle direct input events. FID is triggered by the main thread's ability to execute event callbacks. Workers reduce FID indirectly by freeing the main thread, but input handlers must still be lightweight and optimized.",[14,1166,1167,1170,1171,1173],{},[56,1168,1169],{},"How do I debug FID regressions in a production SPA?","\nDeploy the ",[18,1172,42],{}," library with attribution reporting to capture the specific event target and long task duration causing the delay. Correlate this data with your CI\u002FCD deployment logs, use Chrome DevTools Performance panel to replay the exact user session, and isolate third-party script injection points that may have shifted execution timing.",[1175,1176,1177],"style",{},"html pre.shiki code .sCJTb, html code.shiki .sCJTb{--shiki-default:#FF9492;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .s3sCt, html code.shiki .s3sCt{--shiki-default:#F0F3F6;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sJdzJ, html code.shiki .sJdzJ{--shiki-default:#ADDCFF;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sGhOu, html code.shiki .sGhOu{--shiki-default:#DBB7FF;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .spFnL, html code.shiki .spFnL{--shiki-default:#FFB757;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sXJMR, html code.shiki .sXJMR{--shiki-default:#BDC4CC;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .s5hCx, html code.shiki .s5hCx{--shiki-default:#91CBFF;--shiki-dark:#91CBFF;--shiki-light:#023B95}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":400,"searchDepth":428,"depth":428,"links":1179},[1180,1181,1182,1183,1184,1185],{"id":31,"depth":428,"text":32},{"id":95,"depth":428,"text":96},{"id":178,"depth":428,"text":179},{"id":238,"depth":428,"text":239},{"id":290,"depth":428,"text":291},{"id":333,"depth":428,"text":334,"children":1186},[1187,1188,1189],{"id":387,"depth":435,"text":388},{"id":1061,"depth":435,"text":1062},{"id":1133,"depth":435,"text":1134},"First Input Delay (FID) quantifies the time elapsed between a user's initial interaction (click, tap, keypress) and the browser's ability to process the corresponding event handlers. While the industry is transitioning toward Interaction to Next Paint (INP), FID remains a critical diagnostic baseline for initial load responsiveness. Achieving the \u003C100ms threshold requires rigorous main thread management, strategic script deferral, and precise event listener configuration. This guide provides a deep-dive engineering workflow for Core Web Vitals & Measurement compliance, focusing on actionable partitioning techniques, tooling configuration, and field-data validation.","md",{},"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid",{"title":5,"description":1190},"core-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Findex","up-T3OWEClhjPl8G8XFFV6lniQTx-VimgHyo80XVlJU",[1198,1202],{"title":1199,"path":1200,"stem":1201,"children":-1},"How to fix LCP over 2.5 seconds on React apps","\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fhow-to-fix-lcp-over-25-seconds-on-react-apps","core-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fhow-to-fix-lcp-over-25-seconds-on-react-apps\u002Findex",{"title":1203,"path":1204,"stem":1205,"children":-1},"Improving INP for Complex Single Page Applications","\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Fimproving-inp-for-complex-single-page-applications","core-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Fimproving-inp-for-complex-single-page-applications\u002Findex",1777925998163]