CINXE.COM
Optimize input delay | Articles | web.dev
<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="157101835696-ooapojlodmuabs2do2vuhhnf90bccmoi.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="web.dev"> <meta property="og:type" content="website"><meta name="theme-color" content="#3740ff"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/web/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/css/app.css"> <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/css/dark-theme.css" disabled> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/favicon.png"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/touchicon-180.png"><link rel="canonical" href="https://web.dev/articles/optimize-input-delay"><link rel="search" type="application/opensearchdescription+xml" title="web.dev" href="https://web.dev/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://web.dev/articles/optimize-input-delay" /><link rel="alternate" hreflang="x-default" href="https://web.dev/articles/optimize-input-delay" /><link rel="alternate" hreflang="ar" href="https://web.dev/articles/optimize-input-delay?hl=ar" /><link rel="alternate" hreflang="bn" href="https://web.dev/articles/optimize-input-delay?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://web.dev/articles/optimize-input-delay?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://web.dev/articles/optimize-input-delay?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://web.dev/articles/optimize-input-delay?hl=fa" /><link rel="alternate" hreflang="fr" href="https://web.dev/articles/optimize-input-delay?hl=fr" /><link rel="alternate" hreflang="de" href="https://web.dev/articles/optimize-input-delay?hl=de" /><link rel="alternate" hreflang="he" href="https://web.dev/articles/optimize-input-delay?hl=he" /><link rel="alternate" hreflang="hi" href="https://web.dev/articles/optimize-input-delay?hl=hi" /><link rel="alternate" hreflang="id" href="https://web.dev/articles/optimize-input-delay?hl=id" /><link rel="alternate" hreflang="it" href="https://web.dev/articles/optimize-input-delay?hl=it" /><link rel="alternate" hreflang="ja" href="https://web.dev/articles/optimize-input-delay?hl=ja" /><link rel="alternate" hreflang="ko" href="https://web.dev/articles/optimize-input-delay?hl=ko" /><link rel="alternate" hreflang="pl" href="https://web.dev/articles/optimize-input-delay?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://web.dev/articles/optimize-input-delay?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://web.dev/articles/optimize-input-delay?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://web.dev/articles/optimize-input-delay?hl=es-419" /><link rel="alternate" hreflang="th" href="https://web.dev/articles/optimize-input-delay?hl=th" /><link rel="alternate" hreflang="tr" href="https://web.dev/articles/optimize-input-delay?hl=tr" /><link rel="alternate" hreflang="vi" href="https://web.dev/articles/optimize-input-delay?hl=vi" /><link rel="alternate" hreflang="en-cn" href="https://web.developers.google.cn/articles/optimize-input-delay" /><link rel="alternate" hreflang="x-default" href="https://web.developers.google.cn/articles/optimize-input-delay" /><link rel="alternate" hreflang="ar-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=ar" /><link rel="alternate" hreflang="bn-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=bn" /><link rel="alternate" hreflang="zh-Hans-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=zh-tw" /><link rel="alternate" hreflang="fa-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=fa" /><link rel="alternate" hreflang="fr-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=fr" /><link rel="alternate" hreflang="de-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=de" /><link rel="alternate" hreflang="he-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=he" /><link rel="alternate" hreflang="hi-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=hi" /><link rel="alternate" hreflang="id-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=id" /><link rel="alternate" hreflang="it-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=it" /><link rel="alternate" hreflang="ja-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=ja" /><link rel="alternate" hreflang="ko-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=ko" /><link rel="alternate" hreflang="pl-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=pl" /><link rel="alternate" hreflang="pt-BR-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=pt-br" /><link rel="alternate" hreflang="ru-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=ru" /><link rel="alternate" hreflang="es-419-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=es-419" /><link rel="alternate" hreflang="th-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=th" /><link rel="alternate" hreflang="tr-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=tr" /><link rel="alternate" hreflang="vi-cn" href="https://web.developers.google.cn/articles/optimize-input-delay?hl=vi" /><title>Optimize input delay | Articles | web.dev</title> <meta property="og:title" content="Optimize input delay | Articles | web.dev"><meta name="description" content="Input delay can contribute significantly to total interaction latency and negatively affect your page&#39;s INP. In this guide, learn what input delay is, and how you can reduce it for faster interactivity."> <meta property="og:description" content="Input delay can contribute significantly to total interaction latency and negatively affect your page&#39;s INP. In this guide, learn what input delay is, and how you can reduce it for faster interactivity."><meta property="og:url" content="https://web.dev/articles/optimize-input-delay"><meta property="og:image" content="https://web.dev/static/articles/optimize-input-delay/image/thumbnail.jpg"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="675"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "dateModified": "2023-05-09", "headline": "Optimize input delay" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Articles", "item": "https://web.dev/articles" },{ "@type": "ListItem", "position": 2, "name": "Optimize input delay", "item": "https://web.dev/articles/optimize-input-delay" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="web-theme" type="article" appearance layout="docs" display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="webDev" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="web.dev"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg" class="devsite-site-logo" alt="web.dev"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab > <a href="https://web.dev/about" track-metadata-eventdetail="https://web.dev/about" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - about" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: About" track-name="about" > About </a> </tab> <tab > <a href="https://web.dev/html" track-metadata-eventdetail="https://web.dev/html" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - html" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: HTML" track-name="html" > HTML </a> </tab> <tab > <a href="https://web.dev/css" track-metadata-eventdetail="https://web.dev/css" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - css" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: CSS" track-name="css" > CSS </a> </tab> <tab > <a href="https://web.dev/javascript" track-metadata-eventdetail="https://web.dev/javascript" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - javascript" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: JavaScript" track-name="javascript" > JavaScript </a> </tab> <tab > <a href="https://web.dev/blog" track-metadata-eventdetail="https://web.dev/blog" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - blog" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" > Blog </a> </tab> <tab > <a href="https://web.dev/learn" track-metadata-eventdetail="https://web.dev/learn" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - learn" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" > Learn </a> </tab> <tab class="devsite-active"> <a href="https://web.dev/explore" track-metadata-eventdetail="https://web.dev/explore" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - explore" track-metadata-module="primary nav" aria-label="Explore, selected" data-category="Site-Wide Custom Events" data-label="Tab: Explore" track-name="explore" > Explore </a> </tab> <tab > <a href="https://web.dev/patterns" track-metadata-eventdetail="https://web.dev/patterns" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - patterns" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Patterns" track-name="patterns" > Patterns </a> </tab> <tab > <a href="https://web.dev/case-studies" track-metadata-eventdetail="https://web.dev/case-studies" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - case studies" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Case studies" track-name="case studies" > Case studies </a> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="Articles" tenant-name="web.dev" > <form class="devsite-search-form" action="https://web.dev/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-appearance-selector></devsite-appearance-selector> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <devsite-user enable-profiles id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://web.dev/explore" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Collections </a> </li> </ul> </div> </div> <div class="devsite-doc-set-nav-row"> <devsite-tabs class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://web.dev/explore/learn-core-web-vitals" track-metadata-eventdetail="https://web.dev/explore/learn-core-web-vitals" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - core web vitals" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Core Web Vitals" track-name="core web vitals" > Core Web Vitals </a> </tab> <tab > <a href="https://web.dev/explore/metrics" track-metadata-eventdetail="https://web.dev/explore/metrics" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - metrics" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Metrics" track-name="metrics" > Metrics </a> </tab> <tab > <a href="https://web.dev/explore/fast" track-metadata-eventdetail="https://web.dev/explore/fast" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - fast load times" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Fast load times" track-name="fast load times" > Fast load times </a> </tab> <tab > <a href="https://web.dev/explore/ai" track-metadata-eventdetail="https://web.dev/explore/ai" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - ai" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: AI" track-name="ai" > AI </a> </tab> <tab class="devsite-active"> <a href="https://web.dev/explore/how-to-optimize-inp" track-metadata-eventdetail="https://web.dev/explore/how-to-optimize-inp" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - optimize interaction to next paint (inp)" track-metadata-module="primary nav" aria-label="Optimize Interaction to Next Paint (INP), selected" data-category="Site-Wide Custom Events" data-label="Tab: Optimize Interaction to Next Paint (INP)" track-name="optimize interaction to next paint (inp)" > Optimize Interaction to Next Paint (INP) </a> </tab> <tab > <a href="https://web.dev/explore/progressive-web-apps" track-metadata-eventdetail="https://web.dev/explore/progressive-web-apps" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - progressive web apps" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Progressive Web Apps" track-name="progressive web apps" > Progressive Web Apps </a> </tab> <tab > <a href="https://web.dev/accessibility" track-metadata-eventdetail="https://web.dev/accessibility" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - accessible to all" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Accessible to all" track-name="accessible to all" > Accessible to all </a> </tab> <tab > <a href="https://web.dev/explore/reliable" track-metadata-eventdetail="https://web.dev/explore/reliable" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - network reliability" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Network reliability" track-name="network reliability" > Network reliability </a> </tab> <tab > <a href="https://web.dev/explore/secure" track-metadata-eventdetail="https://web.dev/explore/secure" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - safe and secure" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Safe and secure" track-name="safe and secure" > Safe and secure </a> </tab> <tab > <a href="https://web.dev/explore/discoverable" track-metadata-eventdetail="https://web.dev/explore/discoverable" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - easily discoverable" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Easily discoverable" track-name="easily discoverable" > Easily discoverable </a> </tab> <tab > <a href="https://web.dev/explore/payments" track-metadata-eventdetail="https://web.dev/explore/payments" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - web payments" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Web Payments" track-name="web payments" > Web Payments </a> </tab> <tab > <a href="https://web.dev/explore/media" track-metadata-eventdetail="https://web.dev/explore/media" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - media" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Media" track-name="media" > Media </a> </tab> <tab > <a href="https://web.dev/explore/devices" track-metadata-eventdetail="https://web.dev/explore/devices" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - devices" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Devices" track-name="devices" > Devices </a> </tab> <tab > <a href="https://web.dev/explore/animations" track-metadata-eventdetail="https://web.dev/explore/animations" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - animations" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Animations" track-name="animations" > Animations </a> </tab> <tab > <a href="https://web.dev/explore/identity" track-metadata-eventdetail="https://web.dev/explore/identity" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - identity" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Identity" track-name="identity" > Identity </a> </tab> <tab > <a href="https://web.dev/explore/webassembly" track-metadata-eventdetail="https://web.dev/explore/webassembly" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - webassembly" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: WebAssembly" track-name="webassembly" > WebAssembly </a> </tab> <tab > <a href="https://web.dev/explore/test-automation" track-metadata-eventdetail="https://web.dev/explore/test-automation" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - test automation" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Test automation" track-name="test automation" > Test automation </a> </tab> <tab > <a href="https://web.dev/explore/react" track-metadata-eventdetail="https://web.dev/explore/react" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - react" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: React" track-name="react" > React </a> </tab> <tab > <a href="https://web.dev/explore/angular" track-metadata-eventdetail="https://web.dev/explore/angular" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - angular" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Angular" track-name="angular" > Angular </a> </tab> <tab > <a href="https://web.dev/explore/mini-apps" track-metadata-eventdetail="https://web.dev/explore/mini-apps" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - mini apps" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Mini apps" track-name="mini apps" > Mini apps </a> </tab> </nav> </devsite-tabs> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" hidden> <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="webDev" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="web.dev"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg" class="devsite-site-logo" alt="web.dev"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: About" track-name="about" data-category="Site-Wide Custom Events" data-label="Responsive Tab: About" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > About </span> </a> </li> <li class="devsite-nav-item"> <a href="/html" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: HTML" track-name="html" data-category="Site-Wide Custom Events" data-label="Responsive Tab: HTML" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > HTML </span> </a> </li> <li class="devsite-nav-item"> <a href="/css" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: CSS" track-name="css" data-category="Site-Wide Custom Events" data-label="Responsive Tab: CSS" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > CSS </span> </a> </li> <li class="devsite-nav-item"> <a href="/javascript" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: JavaScript" track-name="javascript" data-category="Site-Wide Custom Events" data-label="Responsive Tab: JavaScript" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > JavaScript </span> </a> </li> <li class="devsite-nav-item"> <a href="/blog" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Blog" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Blog </span> </a> </li> <li class="devsite-nav-item"> <a href="/learn" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Explore" track-name="explore" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Explore" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Explore </span> </a> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/explore/learn-core-web-vitals" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Core Web Vitals" track-name="core web vitals" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Core Web Vitals" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Core Web Vitals </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/metrics" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Metrics" track-name="metrics" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Metrics" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Metrics </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/fast" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Fast load times" track-name="fast load times" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Fast load times" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Fast load times </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/ai" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: AI" track-name="ai" data-category="Site-Wide Custom Events" data-label="Responsive Tab: AI" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > AI </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/how-to-optimize-inp" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Optimize Interaction to Next Paint (INP)" track-name="optimize interaction to next paint (inp)" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Optimize Interaction to Next Paint (INP)" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip menu="_book"> Optimize Interaction to Next Paint (INP) </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="_book"> </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/progressive-web-apps" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Progressive Web Apps" track-name="progressive web apps" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Progressive Web Apps" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Progressive Web Apps </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/accessibility" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Accessible to all" track-name="accessible to all" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Accessible to all" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Accessible to all </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/reliable" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Network reliability" track-name="network reliability" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Network reliability" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Network reliability </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/secure" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Safe and secure" track-name="safe and secure" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Safe and secure" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Safe and secure </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/discoverable" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Easily discoverable" track-name="easily discoverable" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Easily discoverable" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Easily discoverable </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/payments" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Web Payments" track-name="web payments" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Web Payments" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Web Payments </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/media" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Media" track-name="media" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Media" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Media </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/devices" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Devices" track-name="devices" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Devices" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Devices </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/animations" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Animations" track-name="animations" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Animations" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Animations </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/identity" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Identity" track-name="identity" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Identity" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Identity </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/webassembly" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: WebAssembly" track-name="webassembly" data-category="Site-Wide Custom Events" data-label="Responsive Tab: WebAssembly" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > WebAssembly </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/test-automation" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Test automation" track-name="test automation" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Test automation" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Test automation </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/react" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: React" track-name="react" data-category="Site-Wide Custom Events" data-label="Responsive Tab: React" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > React </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/angular" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Angular" track-name="angular" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Angular" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Angular </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/mini-apps" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Mini apps" track-name="mini apps" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Mini apps" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Mini apps </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/patterns" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Patterns" track-name="patterns" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Patterns" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Patterns </span> </a> </li> <li class="devsite-nav-item"> <a href="/case-studies" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Case studies" track-name="case studies" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Case studies" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Case studies </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Familiarize yourself with INP and how to optimize it</span> </div></li> <li class="devsite-nav-item"><a href="/articles/inp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/inp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/inp" ><span class="devsite-nav-text" tooltip>Interaction to Next Paint (INP)</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-inp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-inp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-inp" ><span class="devsite-nav-text" tooltip>Optimize Interaction to Next Paint</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Troubleshooting</span> </div></li> <li class="devsite-nav-item"><a href="/articles/find-slow-interactions-in-the-field" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/find-slow-interactions-in-the-field" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/find-slow-interactions-in-the-field" ><span class="devsite-nav-text" tooltip>Find slow interactions in the field</span></a></li> <li class="devsite-nav-item"><a href="/articles/manually-diagnose-slow-interactions-in-the-lab" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/manually-diagnose-slow-interactions-in-the-lab" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/manually-diagnose-slow-interactions-in-the-lab" ><span class="devsite-nav-text" tooltip>Manually diagnose slow interactions in the lab</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize poor INP caused by JavaScript</span> </div></li> <li class="devsite-nav-item"><a href="/articles/optimize-long-tasks" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-long-tasks" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-long-tasks" ><span class="devsite-nav-text" tooltip>Optimize long tasks</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-input-delay" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-input-delay" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-input-delay" ><span class="devsite-nav-text" tooltip>Optimize input delay</span></a></li> <li class="devsite-nav-item"><a href="/articles/script-evaluation-and-long-tasks" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/script-evaluation-and-long-tasks" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/script-evaluation-and-long-tasks" ><span class="devsite-nav-text" tooltip>Script evaluation and long tasks</span></a></li> <li class="devsite-nav-item"><a href="/articles/off-main-thread" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/off-main-thread" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/off-main-thread" ><span class="devsite-nav-text" tooltip>Use web workers to run JavaScript off the browser's main thread</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize poor INP caused by rendering</span> </div></li> <li class="devsite-nav-item"><a href="/articles/avoid-large-complex-layouts-and-layout-thrashing" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/avoid-large-complex-layouts-and-layout-thrashing" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/avoid-large-complex-layouts-and-layout-thrashing" ><span class="devsite-nav-text" tooltip>Avoid large, complex layouts and layout thrashing</span></a></li> <li class="devsite-nav-item"><a href="/articles/reduce-the-scope-and-complexity-of-style-calculations" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/reduce-the-scope-and-complexity-of-style-calculations" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/reduce-the-scope-and-complexity-of-style-calculations" ><span class="devsite-nav-text" tooltip>Reduce the scope and complexity of style calculations</span></a></li> <li class="devsite-nav-item"><a href="/articles/dom-size-and-interactivity" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/dom-size-and-interactivity" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/dom-size-and-interactivity" ><span class="devsite-nav-text" tooltip>How large DOM sizes affect interactivity, and what you can do about it</span></a></li> <li class="devsite-nav-item"><a href="/articles/client-side-rendering-of-html-and-interactivity" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/client-side-rendering-of-html-and-interactivity" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/client-side-rendering-of-html-and-interactivity" ><span class="devsite-nav-text" tooltip>Client-side rendering of HTML and interactivity</span></a></li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" has-book-nav has-sidebar > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars ></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://web.dev/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Home </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/articles" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Articles" > Articles </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/explore" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="" > Explore </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/explore/how-to-optimize-inp" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="4" track-type="globalNav" track-name="breadcrumb" track-metadata-position="4" track-metadata-eventdetail="" > Optimize Interaction to Next Paint (INP) </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <h1 class="devsite-page-title" tabindex="-1"> Optimize input delay </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <p>Find out what input delay is, and learn techniques to reduce it for faster interactivity.</p> <p> <div class="wd-authors" translate="no"> <div class="wd-author"> <img class="devsite-landing-row-item-icon" alt="Jeremy Wagner" src="https://web.dev/images/authors/jlwagner-v3.jpg" decoding="async" height="64" loading="lazy" width="64"> <div> <span> Jeremy Wagner </span> <div class="wd-author__links"> <a href="https://github.com/malchata" aria-label="Jeremy Wagner on GitHub" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 32.6 31.8"> <title>GitHub</title> <path d="M16.3 0C7.3 0 0 7.3 0 16.3c0 7.2 4.7 13.3 11.1 15.5.8.1 1.1-.4 1.1-.8v-2.8c-4.5 1-5.5-2.2-5.5-2.2-.7-1.9-1.8-2.4-1.8-2.4-1.5-1 .1-1 .1-1 1.6.1 2.5 1.7 2.5 1.7 1.5 2.5 3.8 1.8 4.7 1.4.1-1.1.6-1.8 1-2.2-3.6-.4-7.4-1.8-7.4-8.1 0-1.8.6-3.2 1.7-4.4-.1-.3-.7-2 .2-4.2 0 0 1.4-.4 4.5 1.7 1.3-.4 2.7-.5 4.1-.5 1.4 0 2.8.2 4.1.5 3.1-2.1 4.5-1.7 4.5-1.7.9 2.2.3 3.9.2 4.3 1 1.1 1.7 2.6 1.7 4.4 0 6.3-3.8 7.6-7.4 8 .6.5 1.1 1.5 1.1 3V31c0 .4.3.9 1.1.8 6.5-2.2 11.1-8.3 11.1-15.5C32.6 7.3 25.3 0 16.3 0z" fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" /> </svg></a> <a href="https://www.linkedin.com/in/malchata" aria-label="Jeremy Wagner on LinkedIn" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 200 200"> <title>LinkedIn</title> <path d="M185.2 0H14.8C6.6 0 0 6.4 0 14.3v171.3c0 7.9 6.6 14.3 14.8 14.3h170.4c8.1 0 14.8-6.4 14.8-14.3V14.3C199.9 6.4 193.3 0 185.2 0zM60.6 167.3H30.4V77.1h30.2v90.2zM45.5 64.8h-.2c-10.1 0-16.7-6.9-16.7-15.6 0-8.8 6.7-15.6 17.1-15.6 10.3 0 16.7 6.7 16.9 15.6 0 8.6-6.5 15.6-17.1 15.6zm124 102.5h-30.2V119c0-12.1-4.4-20.4-15.3-20.4-8.4 0-13.3 5.6-15.5 11-.8 1.9-1 4.6-1 7.3v50.4H77.3s.4-81.8 0-90.3h30.2v12.8c4-6.1 11.2-14.9 27.2-14.9 19.9 0 34.8 12.9 34.8 40.6v51.8zm-62.2-77.1c0-.1.1-.2.2-.3v.3h-.2z" fill="currentColor" /> </svg></a> <a href="https://jlwagner.net/" aria-label="Jeremy Wagner's homepage" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 30 30"> <title>Homepage</title> <circle cx="14.5" cy="14.5" r="13.5" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> <ellipse cx="14.5" cy="14.5" rx="6.1" ry="13.5" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> <path d="M1.6 9.6h25.8M1.6 19.4h25.8" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> </svg></a> </div> </div> </div> </div></p> <p>Interactions on the web are complicated things, with all sorts of activity occurring in the browser to drive them. What they all have in common, though, is that they incur some input delay before their event callbacks begin to run. In this guide, you'll learn what input delay is, and what you can do to minimize it so your website's interactions run faster.</p> <h2 id="what_is_input_delay" data-text="What is input delay?" tabindex="-1">What is input delay?</h2> <p><em>Input delay</em> is the period of time beginning from when the user first interacts with a page—such as tapping on a screen, clicking with a mouse, or pressing a key—up to when the event callbacks for the interaction begin to run. Every interaction begins with some amount of input delay.</p> <figure> <img src="/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec.png" alt="A simplified visualization of input delay. At left, there is line art of a mouse cursor with a starburst behind it, signifying the start of an interaction. To the right is line art of a cogwheel, signifying when the event handlers for an interaction begin to run. The space in between is noted as the input delay with a curly brace." width="736" height="303" srcset="https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_36.png 36w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_48.png 48w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_72.png 72w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_96.png 96w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_480.png 480w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_720.png 720w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_856.png 856w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_960.png 960w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_1440.png 1440w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_1920.png 1920w,https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> The mechanics behind input delay. When an input is received by the operating system, it must be passed to the browser before the interaction starts. This takes a certain amount of time, and can be increased by existing main thread work. </figcaption> </figure> <p>Some portion of the input delay is unavoidable: it always takes some amount of time for the operating system to recognize an input event and pass it to the browser. However, that portion of the input delay is often not even noticeable, and there are other things that happen on the page itself that can make input delays long enough to cause problems.</p> <h2 id="how_to_think_about_input_delay" data-text="How to think about input delay" tabindex="-1">How to think about input delay</h2> <p>Generally speaking, you want to keep every part of an interaction as short as possible so that your website has the best chance of meeting <a href="/articles/inp#what_is_a_good_inp_score">the Interaction to Next Paint (INP) metric's "good" threshold</a>, regardless of the user's device. Keeping input delay in check is just one part of meeting that threshold.</p> <p>Consequently, you'll want to aim for the shortest input delay possible to meet INP's "good" threshold. You should be aware, though, you can't expect to eliminate input delays entirely. As long as you're avoiding excessive main thread work while users are attempting to interact with your page, your input delay should be low enough to avoid problems.</p> <h2 id="how_to_minimize_input_delay" data-text="How to minimize input delay" tabindex="-1">How to minimize input delay</h2> <p>As said previously, some input delay is unavoidable, but on the other hand, some input delay <em>is</em> avoidable. Here are some things to consider if you're struggling with long input delays.</p> <h3 id="avoid_recurring_timers_that_kick_off_excessive_main_thread_work" data-text="Avoid recurring timers that kick off excessive main thread work" tabindex="-1">Avoid recurring timers that kick off excessive main thread work</h3> <p>There are two commonly used timer functions in JavaScript that can contribute to input delay: <a href="https://developer.mozilla.org/docs/Web/API/setTimeout"><code translate="no" dir="ltr">setTimeout</code></a> and <a href="https://developer.mozilla.org/docs/Web/API/setInterval"><code translate="no" dir="ltr">setInterval</code></a>. The difference between the two is that <code translate="no" dir="ltr">setTimeout</code> schedules a callback to run after a specified time. <code translate="no" dir="ltr">setInterval</code>, on the other hand, schedules a callback to run every <em>n</em> milliseconds in perpetuity, or until the timer is stopped with <a href="https://developer.mozilla.org/docs/Web/API/clearInterval"><code translate="no" dir="ltr">clearInterval</code></a>.</p> <p><code translate="no" dir="ltr">setTimeout</code> is not problematic in itself—in fact, it can be helpful in <a href="#avoid_long_tasks">avoiding long tasks</a>. However, it depends on <em>when</em> the timeout occurs, and whether the user attempts to interact with the page when the timeout callback runs.</p> <p>Additionally, <code translate="no" dir="ltr">setTimeout</code> can be run in a loop or recursively, where it acts more like <code translate="no" dir="ltr">setInterval</code>, though preferably not scheduling the next iteration until the previous one is completed. While this means the loop will yield to the main thread every time <code translate="no" dir="ltr">setTimeout</code> is called, you should take care to ensure its callback doesn't end up doing excessive work.</p> <p><code translate="no" dir="ltr">setInterval</code> runs a callback on an interval, and is therefore much more likely to get in the way of interactions. This is because—unlike a single instance of a <code translate="no" dir="ltr">setTimeout</code> call, which is a one-off callback that <em>may</em> get in the way of a user interaction—<code translate="no" dir="ltr">setInterval</code>'s recurring nature makes it much more likely that it <em>will</em> get in the way of an interaction, thus increasing the interaction's input delay.</p> <figure> <img src="/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f.png" alt="A screenshot of the performance profiler in Chrome DevTools demonstrating input delay. A task fired by a timer function occurs just before a user initiates a click interaction. However, the timer extends the input delay, causing the interaction's event callbacks to run later than they otherwise would." width="800" height="291" srcset="https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_36.png 36w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_48.png 48w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_72.png 72w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_96.png 96w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_480.png 480w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_720.png 720w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_856.png 856w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_960.png 960w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_1440.png 1440w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_1920.png 1920w,https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> A timer registered by a previous <code translate="no" dir="ltr">setInterval</code> call contributing to input delay as depicted in the performance panel of Chrome DevTools. The added input delay causes the event callbacks for the interaction to run later than they otherwise could. </figcaption> </figure> <p>If timers are occurring in first-party code, then you have control over them. Evaluate whether you need them, or do your best to reduce the work in them as much as possible. However, timers in third-party scripts are a different story. You often don't have control over what a third-party script does, and fixing performance issues in third-party code often involves working with stakeholders to determine whether a given third-party script is necessary, and if so, establish contact with a third-party script vendor to determine what can done to fix performance issues they may cause on your website.</p> <h3 id="avoid_long_tasks" data-text="Avoid long tasks" tabindex="-1">Avoid long tasks</h3> <p>One way to mitigate long input delays is to avoid long tasks. When you have excessive main thread work that blocks the main thread during interactions, that will add to the input delay for them before the long tasks have had a chance to finish.</p> <figure> <img src="/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb.png" alt="A visualization of how long tasks extend input delay. At top, an interaction occurs shortly after a single long task runs, causing significant input delay that causes event callbacks to run much later than they should. At bottom, an interaction occurs at roughly the same time, but the long task is broken up into several smaller ones by yielding, allowing the interaction's event callbacks to run much sooner." width="800" height="448" srcset="https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_36.png 36w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_48.png 48w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_72.png 72w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_96.png 96w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_480.png 480w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_720.png 720w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_856.png 856w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_960.png 960w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_1440.png 1440w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_1920.png 1920w,https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> A visualization of what happens to interactions when tasks are too long and the browser can't respond quickly enough to interactions, versus when longer tasks are broken up into smaller tasks. </figcaption> </figure> <p>Besides minimizing the amount of work you do in a task—and you should <em>always</em> strive to do as little work as possible on the main thread—you can improve responsiveness to user input by <a href="/articles/optimize-long-tasks">breaking up long tasks</a>.</p> <aside class="note"><b>Note:</b> Yielding isn't foolproof, as tasks from third-party JavaScript can still make their way in between first-party tasks after yielding. This can still contribute to input delay for future interactions, and you'll need to be mindful of third-party tasks that may run on an interval, as described in the previous section. This is a problem that the <a href="https://developer.mozilla.org/docs/Web/API/Scheduler/yield"><code translate="no" dir="ltr">scheduler.yield</code> API</a> solves.</aside> <h3 id="be_mindful_of_interaction_overlap" data-text="Be mindful of interaction overlap" tabindex="-1">Be mindful of interaction overlap</h3> <p>A particularly challenging part of optimizing INP can be if you have interactions that overlap. Interaction overlap means that after you've interacted with one element, you make another interaction with the page before the initial interaction has had a chance to render the next frame.</p> <figure> <img src="/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24.png" alt="A depiction of when tasks can overlap to produce long input delays. In this depiction, a click interaction overlaps with a keydown interaction to increase the input delay for the keydown interaction." width="800" height="307" srcset="https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_36.png 36w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_48.png 48w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_72.png 72w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_96.png 96w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_480.png 480w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_720.png 720w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_856.png 856w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_960.png 960w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_1440.png 1440w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_1920.png 1920w,https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> A visualization of two concurrent interactions in the performance profiler in Chrome's DevTools. The rendering work in the initial click interaction causes an input delay for the subsequent keyboard interaction. </figcaption> </figure> <p>Sources of interaction overlap may be as simple as users making many interactions in a short period of time. This can occur when users type in form fields, where many keyboard interactions can occur in a very short period of time. If the work on a key event is especially expensive—such as in the common case of autocomplete fields where network requests are made to a back end—you have a couple of options:</p> <ul> <li>Consider <a href="/articles/debounce-your-input-handlers">debouncing</a> inputs to limit the amount of times an event callback executes in a given period of time.</li> <li>Use <a href="https://developer.mozilla.org/docs/Web/API/AbortController/abort"><code translate="no" dir="ltr">AbortController</code></a> to cancel outgoing <code translate="no" dir="ltr">fetch</code> requests so the main thread doesn't become congested handling <code translate="no" dir="ltr">fetch</code> callbacks. Note: an <code translate="no" dir="ltr">AbortController</code> instance's <code translate="no" dir="ltr">signal</code> property can also be used to <a href="https://developer.mozilla.org/docs/Web/API/AbortSignal/abort_event">abort events</a>.</li> </ul> <p>Another source of increased input delay due to overlapping interactions can be expensive animations. In particular, animations in JavaScript may fire many <a href="https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame"><code translate="no" dir="ltr">requestAnimationFrame</code></a> calls, which may get in the way of user interactions. To get around this, use CSS animations whenever possible to avoid queueing potentially expensive animation frames—but if you do this, make sure you <a href="https://developer.chrome.com/en/docs/lighthouse/performance/non-composited-animations">avoid non-composited animations</a> so that animations run mainly on the GPU and compositor threads, and not on the main thread.</p> <h2 id="conclusion" data-text="Conclusion" tabindex="-1">Conclusion</h2> <p>While input delays may not represent the majority of the time your interactions take to run, it's important to understand that every part of an interaction takes up an amount of time that you can reduce. If you're <a href="/articles/manually-diagnose-slow-interactions-in-the-lab#how_to_identify_long_input_delays">observing long input delay</a>, then you have opportunities to reduce it. Avoiding recurring timer callbacks, breaking up long tasks, and being aware of potential interaction overlap can all help you to reduce input delay, leading to faster interactivity for your website's users.</p> <p><em>Hero image from <a href="https://unsplash.com/">Unsplash</a>, by <a href="https://unsplash.com/@introspectivedsgn">Erik Mclean</a>.</em></p> </div> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> <p>Last updated 2023-05-09 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2023-05-09 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox wd-footer-promo"> <h3 class="devsite-footer-linkbox-heading no-link">web.dev</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <h3 class="devsite-footer-linkbox-heading no-link"> web.dev </h3> <div class="devsite-footer-linkbox-description">We want to help you build beautiful, accessible, fast, and secure websites that work cross-browser, and for all of your users. This site is our home for content to help you on that journey, written by members of the Chrome team, and external experts.</div> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Contribute</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://issuetracker.google.com/issues/new?component=1400680&template=1857359" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > File a bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://issuetracker.google.com/issues?q=status:open%20componentid:1400680&s=created_time:desc" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > See open issues </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Related Content</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://developer.chrome.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Chrome for Developers </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://blog.chromium.org/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Chromium updates </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/case-studies" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Case studies </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/shows" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Podcasts & shows </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Follow</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://twitter.com/ChromiumDev" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > @ChromiumDev on X </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.youtube.com/user/ChromeDevelopers" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > YouTube </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.linkedin.com/showcase/chrome-for-developers" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Chrome for Developers on LinkedIn </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/static/blog/feed.xml" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > RSS </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/terms" data-category="Site-Wide Custom Events" data-label="Footer Terms link" > Terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{"at": "True", "ga4": [], "ga4p": [], "gtm": [{"id": "GTM-MZWCJPP", "purpose": 0}], "parameters": {"internalUser": "False", "language": {"machineTranslated": "False", "requested": "en", "served": "en"}, "pageType": "article", "projectName": "Articles", "signedIn": "False", "tenant": "web", "recommendations": {"sourcePage": "", "sourceType": 0, "sourceRank": 0, "sourceIdenticalDescriptions": 0, "sourceTitleWords": 0, "sourceDescriptionWords": 0, "experiment": ""}, "experiment": {"ids": ""}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <script nonce="qD6JIpbfAcGge/GZS111MAJSdZb2kt"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/js/app_loader.js', '[27,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web","https://web-dot-devsite-v2-prod-3p.appspot.com",1,null,["/_pwa/web/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/favicon.png","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,116,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyCNm9YxQumEXwGJgTDjxoxXK6m1F-9720Q","AIzaSyCc76DZePGtoyUjqKrLdsMGk_ry7sljLbY","web.dev","AIzaSyB9bqgQ2t11WJsOX8qNsCQ6U-w91mmqF-I","AIzaSyAdYnStPdzjcJJtQ0mvIaeaMKj7_t6J_Fg",null,null,null,["Search__enable_suggestions_from_borg","Profiles__require_profile_eligibility_for_signin","TpcFeatures__enable_mirror_tenant_redirects","Cloud__enable_cloudx_experiment_ids","MiscFeatureFlags__enable_firebase_utm","MiscFeatureFlags__enable_explain_this_code","DevPro__enable_cloud_innovators_plus","MiscFeatureFlags__enable_project_variables","Cloud__enable_legacy_calculator_redirect","OnSwitch__enable","MiscFeatureFlags__emergency_css","Search__enable_dynamic_content_confidential_banner","EngEduTelemetry__enable_engedu_telemetry","Profiles__enable_awarding_url","CloudShell__cloud_code_overflow_menu","Cloud__enable_llm_concierge_chat","TpcFeatures__enable_required_headers","BookNav__enable_tenant_cache_key","Cloud__enable_cloud_facet_chat","Analytics__enable_clearcut_logging","Profiles__enable_completecodelab_endpoint","Experiments__reqs_query_experiments","Profiles__enable_public_developer_profiles","Profiles__enable_developer_profiles_callout","DevPro__enable_developer_subscriptions","Cloud__enable_cloud_shell","Profiles__enable_release_notes_notifications","MiscFeatureFlags__enable_view_transitions","Search__enable_ai_eligibility_checks","MiscFeatureFlags__developers_footer_dark_image","Cloud__enable_cloud_shell_fte_user_flow","MiscFeatureFlags__enable_variable_operator","Profiles__enable_dashboard_curated_recommendations","Search__enable_page_map","Profiles__enable_page_saving","Concierge__enable_pushui","Profiles__enable_recognition_badges","Cloud__enable_cloudx_ping","Cloud__enable_free_trial_server_call","CloudShell__cloud_shell_button","Cloud__enable_cloud_dlp_service","Profiles__enable_profile_collections","MiscFeatureFlags__developers_footer_image","Profiles__enable_complete_playlist_endpoint"],null,null,"AIzaSyA58TaKli1DculwmAmbpzLVGuWc8eCQgQc","https://developerscontentserving-pa.googleapis.com","AIzaSyDWBU60w0P9hEkr29kkksYs8Z7gvZ8u_wc","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[27,"web","web.dev","web.dev",null,"web-dot-devsite-v2-prod-3p.appspot.com",null,null,[null,null,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],null,null,null,null,[1,null,1],[1,1,null,1,1]],null,[38,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,1,1,null,null,null,null,null,null,null,null,2,null,null,null,"/images/lockup-dark-theme.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],[1,1]],[[null,null,null,null,null,["GTM-MZWCJPP"],null,null,null,null,null,[["GTM-MZWCJPP",1]],1]],null,4]]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>