CINXE.COM
Performance | 2022 | The Web Almanac by HTTP Archive
<!doctype html> <html lang="en" > <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Performance | 2022 | The Web Almanac by HTTP Archive</title> <link rel="stylesheet" href="/static/css/normalize.css?v=3a712a3381a95c0a7b7c6ed3aa03b911"> <link rel="stylesheet" href="/static/css/almanac.css?v=1653be48f4c6c63139a92045bbc0a5c5"> <link rel="stylesheet" href="/static/css/page.css?v=09bfe6babea9027e32ffe7ccfa9f6f4c"> <link rel="preload" href="/static/fonts/Lato-Regular.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/static/fonts/Poppins-Bold.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/static/fonts/Lato-Black.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/static/fonts/Lato-Bold.woff2" as="font" type="font/woff2" crossorigin> <script nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'UA-22381566-3', { 'link_attribution': true }); gtag('config', 'G-PQ5N2MZG5M'); </script> <link rel="shortcut icon" href="/static/images/favicon.ico"> <link rel="apple-touch-icon" href="/static/images/apple-touch-icon.png"> <meta name="description" content="Performance chapter of the 2022 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and First Input Delay metrics and their diagnostics."> <meta property="og:title" content="Performance | 2022 | The Web Almanac by HTTP Archive"> <meta property="og:url" content="https://almanac.httparchive.org/en/2022/performance"> <meta property="og:image" content="https://almanac.httparchive.org/static/images/2019/performance/hero_lg.jpg"> <meta property="og:image:height" content="433"> <meta property="og:image:width" content="866"> <meta property="og:type" content="article"> <meta property="og:description" content="Performance chapter of the 2022 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and First Input Delay metrics and their diagnostics."> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@HTTPArchive"> <meta name="twitter:title" content="Performance | 2022 | The Web Almanac by HTTP Archive"> <meta name="twitter:image" content="https://almanac.httparchive.org/static/images/2019/performance/hero_lg.jpg"> <meta name="twitter:image:alt" content="Chapter image for the Performance chapter of the 2022 Web Almanac"> <meta name="twitter:description" content="Performance chapter of the 2022 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and First Input Delay metrics and their diagnostics."> <link rel="webmention" href="https://webmention.io/almanac.httparchive.org/webmention"> <link rel="pingback" href="https://webmention.io/almanac.httparchive.org/xmlrpc"> <link rel="me" href="mailto:team@httparchive.org"> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "Article", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://almanac.httparchive.org/en/2022/performance" }, "headline": "Performance | 2022 | The Web Almanac by HTTP Archive", "image": { "@type": "ImageObject", "url": "https://almanac.httparchive.org/static/images/2019/performance/hero_lg.jpg", "height": 433, "width": 866 }, "publisher": { "@type": "Organization", "name": "HTTP Archive", "logo": { "@type": "ImageObject", "url": "https://almanac.httparchive.org/static/images/ha.png", "height": 160, "width": 320 }, "sameAs": [ "https://httparchive.org", "https://x.com/HTTPArchive", "https://bsky.app/profile/httparchive.org", "https://github.com/HTTPArchive" ] }, "author": [{ "@type": "Person", "sameAs": [ "https://almanac.httparchive.org/en/2022/contributors#mel-ada" ,"https://x.com/mel_melificent" ,"https://github.com/mel-ada" ,"https://www.linkedin.com/in/mel-ada/" ], "name": "Melissa Ada" },{ "@type": "Person", "sameAs": [ "https://almanac.httparchive.org/en/2022/contributors#rviscomi" ,"https://x.com/rick_viscomi" ,"https://github.com/rviscomi" ], "name": "Rick Viscomi" }] , "description": "Performance chapter of the 2022 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and First Input Delay metrics and their diagnostics.", "datePublished": "2022-10-25T00:00:00.000Z", "dateModified": "2024-11-16T00:00:00.000Z" } </script> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "en", "item": "https://almanac.httparchive.org/en/" },{ "@type": "ListItem", "position": 2, "name": "2022", "item": "https://almanac.httparchive.org/en/2022" }] } </script> <meta name="citation_title" content="The 2022 Web Almanac: Performance"> <meta name="citation_author" content="Melissa Ada"> <meta name="citation_author" content="Rick Viscomi"> <meta name="citation_publication_date" content="2022/10/25"> <meta name="citation_journal_title" content="The 2022 Web Almanac"> <meta name="citation_volume" content="4"> <meta name="citation_issue" content="12"> <meta name="citation_publisher" content="HTTP Archive"> <meta name="citation_technical_report_institution" content="HTTP Archive"> <meta name="citation_language" content="English"> <meta name="citation_fulltext_html_url" content="https://almanac.httparchive.org/en/2022/performance"> <link rel="canonical" href="https://almanac.httparchive.org/en/2022/performance"> <link rel="alternate" type="application/rss+xml" title="Web Almanac by HTTP Archive RSS (en)" href="/en/rss.xml"> <link rel="alternate" href="https://almanac.httparchive.org/en/2022/performance" hreflang="en"> <link rel="alternate" href="https://almanac.httparchive.org/ja/2022/performance" hreflang="ja"> <link rel="alternate" href="https://almanac.httparchive.org/en/2022/performance" hreflang="x-default"> </head> <body class="year-2022"> <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" display="none"> <!-- HTTPArchive --> <symbol id="ha-logo" viewBox="0 0 432 225"> <path d="M10.626 7.433h14.5v47.5c6-7.4 13.5-11 22.5-11 4.9 0 9.2 1.2 13.1 3.7 3.9 2.4 6.7 5.8 8.6 10.1 1.9 4.3 2.9 10.7 2.9 19.1v41.6h-14.6v-45.2c0-5.3-1.3-9.6-4-12.9-2.6-3.3-6-4.9-10.3-4.9-3.2 0-6.2.8-9 2.5-2.8 1.6-5.9 4.4-9.3 8.2v52.4h-14.4V7.433m66.4 49.5l27.2-26.7v15.1h23.1v13h-23.1v35.8c0 8.4 3.5 12.6 10.4 12.6 5.2 0 10.7-1.7 16.4-5.2v13.5c-5.6 3.1-11.6 4.7-18.2 4.7s-12.1-1.9-16.5-5.8c-1.4-1.2-2.5-2.5-3.4-3.9-.9-1.5-1.7-3.4-2.3-5.7-.6-2.4-.9-6.9-.9-13.5v-32.5h-12.7v-1.4m54.3 0l27.2-26.7v15.1h23.1v13h-23.1v35.8c0 8.4 3.5 12.6 10.4 12.6 5.2 0 10.7-1.7 16.4-5.2v13.5c-5.6 3.1-11.6 4.7-18.2 4.7s-12.1-1.9-16.5-5.8c-1.4-1.2-2.5-2.5-3.4-3.9-.9-1.5-1.7-3.4-2.3-5.7-.6-2.4-.9-6.9-.9-13.5v-32.5h-12.7v-1.4M212.8 30.1l-27.2 26.7v1.4h39c6.1.2 10.6 1.5 13.9 3.1 3.5 1.6 6.3 4.3 8.3 7.9 2.1 3.7 3.1 7.9 3.1 12.7 0 7.4-2.2 13.5-6.5 18.2-4.3 4.7-9.8 7.1-16.6 7.1-2.8 0-5.5-.4-8.2-1.1v12.3c3.4.9 6.7 1.3 9.7 1.3 10.5 0 19.2-3.5 26-10.6 6.8-7 10.2-16 10.3-27 0-11.6-3.6-20.6-10.9-27.1-7.1-6.4-17.1-9.6-29.8-9.7h-.4l-10.6-.1V30.1z" fill="currentColor" /> <path d="M198 63.7c0 52.2-.1 108.8-.1 154.7h14.8v-52.5c3.4-3.8 6.1-6.4 8.9-8 2.8-1.6 5.8-2.4 9-2.4 4.3 0 7.7 1.6 10.3 4.9 2.6 3.2 4 7.5 4 12.9v45.2h14.5v-41.6c0-8.5-.9-14.9-2.8-19.2-1.9-4.3-4.7-7.7-8.6-10.1-3.9-2.4-8.3-3.7-13.1-3.7-8.8 0-16.1 3.5-22.1 10.6v-53.1c.1-12.5 0-25.1 0-37.7H198zM55.9 174.5v31.1c0 2.5.8 3.7 2.5 3.7s4.5-1.3 8.2-3.9v8.8c-3.3 2.1-5.9 3.5-7.9 4.3-2 .8-4 1.2-6.2 1.2-6.2 0-9.9-2.4-11-7.3-6.1 4.8-12.7 7.2-19.6 7.2-5.1 0-9.3-1.7-12.7-5-3.4-3.4-5.1-7.6-5.1-12.7 0-4.6 1.6-8.7 4.9-12.3 3.3-3.7 8.1-6.5 14.1-8.7l18.5-6.4v-3.9c0-8.8-4.4-13.2-13.2-13.2-7.9 0-15.6 4.1-23 12.2v-15.8c5.6-6.6 13.7-9.9 24.2-9.9 7.9 0 14.2 2.1 19 6.2 1.6 1.3 3 3.1 4.3 5.3 1.3 2.2 2.1 4.4 2.4 6.6.4 2.2.6 6.3.6 12.5m-14.2 29.4v-21.7L32 186c-4.9 2-8.4 3.9-10.5 6-2 2-3 4.4-3 7.4s1 5.5 2.9 7.4c2 1.9 4.5 2.9 7.5 2.9 4.6-.1 8.8-2 12.8-5.8M90 145.3v16.8l.8-1.3c7-11.3 14-16.9 21-16.9 5.5 0 11.1 2.8 17.1 8.3l-7.6 12.7c-5-4.8-9.7-7.2-14-7.2-4.7 0-8.7 2.2-12.2 6.7-3.4 4.4-5.1 9.7-5.1 15.8v38.2H75.5v-73.1H90m96.9 56v14.3c-7.3 2.7-14.4 4.1-21.3 4.1-11.4 0-20.6-3.4-27.4-10.2-6.8-6.8-10.2-15.9-10.2-27.3 0-11.5 3.3-20.8 9.9-27.8 6.6-7 15.3-10.6 26.1-10.6 3.8 0 7.1.4 10.1 1.1 3 .7 6.7 2 11.1 4v15.4c-7.3-4.7-14.1-7-20.3-7-6.5 0-11.9 2.3-16 6.9-4.2 4.6-6.3 10.4-6.3 17.5 0 7.5 2.3 13.4 6.8 17.8 4.6 4.4 10.7 6.6 18.4 6.6 5.5.1 11.9-1.5 19.1-4.8m93.2-86.7c2.4 0 4.4.8 6.1 2.5 1.7 1.6 2.5 3.7 2.5 6s-.8 4.3-2.5 6c-1.7 1.7-3.7 2.5-6.1 2.5-2.2 0-4.2-.8-5.9-2.5-1.7-1.7-2.5-3.8-2.5-6s.8-4.2 2.5-5.9c1.7-1.8 3.7-2.6 5.9-2.6m-7.2 30.7h14.5v73.1h-14.5v-73.1m75 0h15.7l-32.3 74.4h-4.8l-33.1-74.4h15.8l19.7 45 19-45m78.8 37.8h-51.4c.4 7 2.7 12.6 7 16.7s9.9 6.2 16.8 6.2c9.5 0 18.3-3 26.4-8.9v14.1c-4.4 3-8.9 5.1-13.3 6.4-4.3 1.3-9.5 1.9-15.3 1.9-8.1 0-14.6-1.7-19.5-5-5-3.3-9-7.8-12-13.4-3-5.7-4.4-12.2-4.4-19.6 0-11.1 3.2-20.2 9.5-27.1 6.3-7 14.5-10.5 24.6-10.5 9.7 0 17.4 3.4 23.2 10.2 5.8 6.8 8.7 15.9 8.7 27.3v1.7m-51.4-8.6h36.8c-.4-5.8-2.1-10.2-5.2-13.3-3.1-3.1-7.2-4.7-12.4-4.7s-9.5 1.6-12.8 4.7c-3.2 3-5.4 7.5-6.4 13.3" fill="currentColor" /> </symbol> <!-- GitHub --> <symbol id="github-logo" viewBox="0 0 32.6 31.8"> <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" /> </symbol> <!-- Twitter --> <symbol id="twitter-logo" viewBox="0 0 300 271"> <path xmlns="http://www.w3.org/2000/svg" d="m236 0h46l-101 115 118 156h-92.6l-72.5-94.8-83 94.8h-46l107-123-113-148h94.9l65.5 86.6zm-16.1 244h25.5l-165-218h-27.4z" fill="currentColor" /> </symbol> <!-- LinkedIn --> <symbol id="linkedin-logo" viewBox="0 0 200 200"> <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" /> </symbol> <!-- Mastodon --> <symbol id="mastodon-logo" viewBox="0 0 61 65"> <path d="M60.7539 14.3904C59.8143 7.40642 53.7273 1.90257 46.5117 0.836066C45.2943 0.655854 40.6819 0 29.9973 0H29.9175C19.2299 0 16.937 0.655854 15.7196 0.836066C8.70488 1.87302 2.29885 6.81852 0.744617 13.8852C-0.00294988 17.3654 -0.0827298 21.2237 0.0561464 24.7629C0.254119 29.8384 0.292531 34.905 0.753482 39.9598C1.07215 43.3175 1.62806 46.6484 2.41704 49.9276C3.89445 55.9839 9.87499 61.0239 15.7344 63.0801C22.0077 65.2244 28.7542 65.5804 35.2184 64.1082C35.9295 63.9428 36.6318 63.7508 37.3252 63.5321C38.8971 63.0329 40.738 62.4745 42.0913 61.4937C42.1099 61.4799 42.1251 61.4621 42.1358 61.4417C42.1466 61.4212 42.1526 61.3986 42.1534 61.3755V56.4773C42.153 56.4557 42.1479 56.4345 42.1383 56.4151C42.1287 56.3958 42.1149 56.3788 42.0979 56.3655C42.0809 56.3522 42.0611 56.3429 42.04 56.3382C42.019 56.3335 41.9971 56.3336 41.9761 56.3384C37.8345 57.3276 33.5905 57.8234 29.3324 57.8156C22.0045 57.8156 20.0336 54.3384 19.4693 52.8908C19.0156 51.6397 18.7275 50.3346 18.6124 49.0088C18.6112 48.9866 18.6153 48.9643 18.6243 48.9439C18.6333 48.9236 18.647 48.9056 18.6643 48.8915C18.6816 48.8774 18.7019 48.8675 18.7237 48.8628C18.7455 48.858 18.7681 48.8585 18.7897 48.8641C22.8622 49.8465 27.037 50.3423 31.2265 50.3412C32.234 50.3412 33.2387 50.3412 34.2463 50.3146C38.4598 50.1964 42.9009 49.9808 47.0465 49.1713C47.1499 49.1506 47.2534 49.1329 47.342 49.1063C53.881 47.8507 60.1038 43.9097 60.7362 33.9301C60.7598 33.5372 60.8189 29.8148 60.8189 29.4071C60.8218 28.0215 61.2651 19.5781 60.7539 14.3904Z" fill="currentColor"/> <path d="M50.3943 22.237V39.5876H43.5185V22.7481C43.5185 19.2029 42.0411 17.3949 39.036 17.3949C35.7325 17.3949 34.0778 19.5338 34.0778 23.7585V32.9759H27.2434V23.7585C27.2434 19.5338 25.5857 17.3949 22.2822 17.3949C19.2949 17.3949 17.8027 19.2029 17.8027 22.7481V39.5876H10.9298V22.237C10.9298 18.6918 11.835 15.8754 13.6453 13.7877C15.5128 11.7049 17.9623 10.6355 21.0028 10.6355C24.522 10.6355 27.1813 11.9885 28.9542 14.6917L30.665 17.5633L32.3788 14.6917C34.1517 11.9885 36.811 10.6355 40.3243 10.6355C43.3619 10.6355 45.8114 11.7049 47.6847 13.7877C49.4931 15.8734 50.3963 18.6899 50.3943 22.237Z" fill="white"/> </symbol> <!-- Bluesky --> <symbol id="bluesky-logo" viewBox="0 0 600 530"> <path d="m135.72 44.03c66.496 49.921 138.02 151.14 164.28 205.46 26.262-54.316 97.782-155.54 164.28-205.46 47.98-36.021 125.72-63.892 125.72 24.795 0 17.712-10.155 148.79-16.111 170.07-20.703 73.984-96.144 92.854-163.25 81.433 117.3 19.964 147.14 86.092 82.697 152.22-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.3797-3.6904-10.832-3.7077-7.8964-0.0174-2.9357-1.1937 0.51669-3.7077 7.8964-13.714 40.255-67.233 197.36-189.63 71.766-64.444-66.128-34.605-132.26 82.697-152.22-67.108 11.421-142.55-7.4491-163.25-81.433-5.9562-21.282-16.111-152.36-16.111-170.07 0-88.687 77.742-60.816 125.72-24.795z" fill="currentColor"/> </symbol> <!-- Globe --> <symbol id="globe-logo" viewBox="0 0 30 30"> <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" /> </symbol> <!-- Bar chart --> <symbol id="bar-chart-logo" viewBox="0 0 18 19"> <path d="M0 9h3v10H0V9zm5-9h3v19H5V0zm5 7h3v12h-3V7zm5-4h3v16h-3V3z" fill="currentColor" /> </symbol> <!-- Comment --> <symbol id="comment-logo" viewBox="0 0 22 22.1"> <path d="M4.4 22.1l8-5.1H22V0H0v17h4.4z" fill="currentColor" /> </symbol> <!-- SQL --> <symbol id="sql-logo" viewBox="0 0 32 14.6"> <path d="M.1 12.4V9.6c.5.4 1.1.8 1.7 1 .6.2 1.2.3 1.8.3.4 0 .7 0 .9-.1s.5-.2.7-.3c.2-.1.3-.2.4-.4.1-.2.1-.3.1-.5s-.1-.5-.2-.7c-.2-.2-.4-.4-.6-.5-.3-.2-.5-.4-.9-.5-.3-.2-.7-.3-1.1-.5-1-.4-1.7-.9-2.2-1.5S0 4.6 0 3.8c0-.7.1-1.2.4-1.7S1 1.2 1.5.9s1-.5 1.6-.7S4.3 0 5 0s1.2 0 1.8.1 1 .2 1.4.4v2.6c-.3-.1-.5-.3-.8-.4s-.5-.2-.7-.2c-.3-.1-.6-.2-.8-.2-.3 0-.5-.1-.7-.1-.3 0-.6 0-.9.1s-.5.2-.7.3c-.2.1-.4.2-.5.4-.1.2-.1.3-.1.5s.1.4.2.6c.1.2.3.3.5.5.1.1.4.3.7.4.3.1.6.3 1 .4.5.2 1 .4 1.4.7.4.2.7.5 1 .8s.5.6.7 1c.2.4.2.8.2 1.3 0 .7-.1 1.3-.4 1.8-.3.6-.7 1-1.1 1.3-.5.3-1 .5-1.6.6s-1.3.2-1.9.2c-.7 0-1.4-.1-2-.2-.6-.1-1.2-.3-1.6-.5zm16 .7c-1.8 0-3.3-.6-4.4-1.8-1.2-1.2-1.7-2.7-1.7-4.6 0-2 .6-3.6 1.7-4.9C12.9.6 14.4 0 16.3 0c1.8 0 3.3.6 4.4 1.8 1.1 1.2 1.7 2.7 1.7 4.7s-.6 3.6-1.7 4.8l-.1.1-.1.1 3.2 3.1h-4L18 12.9c-.6.1-1.2.2-1.9.2zm.1-10.6c-1 0-1.8.4-2.4 1.1-.6.7-.9 1.7-.9 3s.3 2.2.9 3c.6.7 1.4 1.1 2.3 1.1 1 0 1.8-.4 2.3-1.1.6-.7.9-1.7.9-3s-.3-2.3-.8-3.1c-.5-.7-1.3-1-2.3-1zM32 12.9h-7.5V.2h2.8v10.3H32v2.4z" fill="currentColor" /> </symbol> <!-- Search --> <symbol id="search-logo" viewBox="0 0 13 13"> <path d="m4.8495 7.8226c0.82666 0 1.5262-0.29146 2.0985-0.87438 0.57232-0.58292 0.86378-1.2877 0.87438-2.1144 0.010599-0.82666-0.28086-1.5262-0.87438-2.0985-0.59352-0.57232-1.293-0.86378-2.0985-0.87438-0.8055-0.010599-1.5103 0.28086-2.1144 0.87438-0.60414 0.59352-0.8956 1.293-0.87438 2.0985 0.021197 0.8055 0.31266 1.5103 0.87438 2.1144 0.56172 0.60414 1.2665 0.8956 2.1144 0.87438zm4.4695 0.2115 3.681 3.6819-1.259 1.284-3.6817-3.7 0.0019784-0.69479-0.090043-0.098846c-0.87973 0.76087-1.92 1.1413-3.1207 1.1413-1.3553 0-2.5025-0.46363-3.4417-1.3909s-1.4088-2.0686-1.4088-3.4239c0-1.3553 0.4696-2.4966 1.4088-3.4239 0.9392-0.92727 2.0864-1.3969 3.4417-1.4088 1.3553-0.011889 2.4906 0.45771 3.406 1.4088 0.9154 0.95107 1.379 2.0924 1.3909 3.4239 0 1.2126-0.38043 2.2588-1.1413 3.1385l0.098834 0.090049z" fill="currentColor" /> </symbol> <!-- Share Apple --> <symbol id="share-apple-logo" viewBox="0 0 24 24"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M16 5l-1.42 1.42-1.59-1.59V16h-1.98V4.83L9.42 6.42 8 5l4-4 4 4zm4 5v11c0 1.1-.9 2-2 2H6c-1.11 0-2-.9-2-2V10c0-1.11.89-2 2-2h3v2H6v11h12V10h-3V8h3c1.1 0 2 .89 2 2z" /> </symbol> <!-- Share Android --> <symbol id="share-android-logo" viewBox="0 0 24 24"> <path d="M0 0h24v24H0z" fill="none" /> <path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z" /> </symbol> </svg> <div id="skiptocontent"><a href="#maincontent">Skip navigation</a></div> <header id="header" class="alt-bg"> <div class="container"> <div class="top-header"> <a class="navigation-logo" href="/en/2022/"> <span class="wa">Web Almanac</span> <span class="line-group"> <span class="pre">By</span> <span class="ha">HTTP Archive</span> </span> </a> <nav id="header-page-navigation" aria-label="Page navigation"> <ul> <li><a href="/en/2022/contributors">Contributors</a></li> <li><a href="/en/2022/methodology">Methodology</a></li> <li> <a class="nav-dropdown-btn js-hide" href="/en/search">Search</a> <div class="nav-dropdown header search-nav js-enable hidden"> <button type="button" class="nav-dropdown-btn search-button" aria-expanded="false"> Search </button> <ul class="nav-dropdown-list align-right hidden header-search"> <li class="nav-dropdown-list-part"> <form action="/en/search"> <label for="header-search-box" class="visually-hidden">Search</label> <input id="header-search-box" class="search-input" type="search" name="q" placeholder="Search" title="Search" aria-label="Search"> <button class="search-button" type="submit"> <svg width="13" height="13" role="img" aria-labelledby="header-search-icon"> <title id="header-search-icon">Search</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#search-logo"></use> </svg> </button> </form> </li> </ul> </div> </li> <li> <a class="nav-dropdown-btn js-hide" href="/en/2022/table-of-contents">Table of Contents</a> <div class="nav-dropdown header table-of-contents js-enable hidden"> <button type="button" class="nav-dropdown-btn" aria-expanded="false" aria-label="Table of Contents" > Table of Contents </button> <ul class="nav-dropdown-list hidden header-list"> <li class="nav-dropdown-list-part"> <a href="/en/2022/">Home</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents">Table of Contents</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-1">Part I. Page Content</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/css"> Chapter 1: CSS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/javascript"> Chapter 2: JavaScript </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/markup"> Chapter 3: Markup </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/structured-data"> Chapter 4: Structured Data </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/fonts"> Chapter 5: Fonts </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/media"> Chapter 6: Media </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/webassembly"> Chapter 7: WebAssembly </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/third-parties"> Chapter 8: Third Parties </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/interoperability"> Chapter 9: Interoperability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-2">Part II. User Experience</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/seo"> Chapter 10: SEO </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/accessibility"> Chapter 11: Accessibility </a> </li> <li class="nav-dropdown-list-chapter nav-dropdown-list-current"> <span> Chapter 12: Performance </span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/privacy"> Chapter 13: Privacy </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/security"> Chapter 14: Security </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/mobile-web"> Chapter 15: Mobile Web </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/capabilities"> Chapter 16: Capabilities </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/pwa"> Chapter 17: PWA </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-3">Part III. Content Publishing</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/cms"> Chapter 18: CMS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/jamstack"> Chapter 19: Jamstack </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/sustainability"> Chapter 20: Sustainability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-4">Part IV. Content Distribution</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/page-weight"> Chapter 21: Page Weight </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/cdn"> Chapter 22: CDN </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/http"> Chapter 23: HTTP </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#appendices">Appendices</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/methodology">Methodology</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/contributors">Contributors</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/search">Search</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#ebook">Ebook</a> </li> <li class="nav-dropdown-list-chapter ebook"> <a href="https://cdn.httparchive.org/almanac/ebooks/web_almanac_2022_en.pdf" data-event="ebook-click" data-label="toc-menu">Ebook PDF (32MB)</a> </li> </ul> </div> </li> <li> <div class="nav-dropdown header"> <button type="button" class="nav-dropdown-btn js-enable" disabled aria-expanded="false" aria-label="Year Switcher">2022</button> <ul class="nav-dropdown-list hidden header-list"> <li> <a href="/en/2024/performance">2024</a> </li> <li> <a href="/en/2021/performance">2021</a> </li> <li> <a href="/en/2020/performance">2020</a> </li> <li> <a href="/en/2019/performance">2019</a> </li> </ul> </div> </li> <li> <div class="nav-dropdown header"> <button type="button" class="nav-dropdown-btn js-enable" disabled aria-expanded="false" aria-label="Language Switcher" >English</button> <ul class="nav-dropdown-list hidden header-list"> <li> <a lang="ja" href="/ja/2022/performance">日本語</a> </li> <li> <a class="help-translate" href="https://github.com/HTTPArchive/almanac.httparchive.org/wiki/Translators'-Guide"><em>Help translate</em></a> </li> </ul> </div> </li> </ul> </nav> <nav id="menu" aria-labelledby="menu-btn"> <a href="#footer" class="menu-btn js-hide" aria-label="Page menu"> <span class="menu-btn-bar"></span> <span class="menu-btn-bar"></span> <span class="menu-btn-bar"></span> </a> <button type="button" class="menu-btn js-enable hidden" disabled id="menu-btn" aria-label="Open the menu" aria-expanded="false" data-open-text="Open the menu" data-close-text="Close the menu"> <span class="menu-btn-bar"></span> <span class="menu-btn-bar"></span> <span class="menu-btn-bar"></span> </button> <ul class="menu"> <li><a href="/en/2022/contributors">Contributors</a></li> <li><a href="/en/2022/methodology">Methodology</a></li> <li> <form class="search-nav" action="/en/search"> <label for="mobile-search-box" class="visually-hidden">Search</label> <input id="mobile-search-box" class="search-input" type="search" name="q" placeholder="Search" title="Search" aria-label="Search"> <button class="search-button" type="submit"> <svg width="13" height="13" role="img" aria-labelledby="mobile-search-icon"> <title id="mobile-search-icon">Search</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#search-logo"></use> </svg> </button> </form> </li> <li> <a class="js-hide" href="/en/2022/table-of-contents">Table of Contents</a> <div class="table-of-contents-switcher js-enable hidden"> <label for="table-of-contents-switcher-mobile" class="visually-hidden"> Table of Contents Switcher </label> <select id="table-of-contents-switcher-mobile" data-label="toc-menu-mobile"> <option value="/en/2022/">Home</option> <option value="/en/2022/table-of-contents">Table of Contents</option> <option value="/en/2022/css"> Chapter 1: CSS </option> <option value="/en/2022/javascript"> Chapter 2: JavaScript </option> <option value="/en/2022/markup"> Chapter 3: Markup </option> <option value="/en/2022/structured-data"> Chapter 4: Structured Data </option> <option value="/en/2022/fonts"> Chapter 5: Fonts </option> <option value="/en/2022/media"> Chapter 6: Media </option> <option value="/en/2022/webassembly"> Chapter 7: WebAssembly </option> <option value="/en/2022/third-parties"> Chapter 8: Third Parties </option> <option value="/en/2022/interoperability"> Chapter 9: Interoperability </option> <option value="/en/2022/seo"> Chapter 10: SEO </option> <option value="/en/2022/accessibility"> Chapter 11: Accessibility </option> <option disabled selected value="/en/2022/performance"> Chapter 12: Performance </option> <option value="/en/2022/privacy"> Chapter 13: Privacy </option> <option value="/en/2022/security"> Chapter 14: Security </option> <option value="/en/2022/mobile-web"> Chapter 15: Mobile Web </option> <option value="/en/2022/capabilities"> Chapter 16: Capabilities </option> <option value="/en/2022/pwa"> Chapter 17: PWA </option> <option value="/en/2022/cms"> Chapter 18: CMS </option> <option value="/en/2022/jamstack"> Chapter 19: Jamstack </option> <option value="/en/2022/sustainability"> Chapter 20: Sustainability </option> <option value="/en/2022/page-weight"> Chapter 21: Page Weight </option> <option value="/en/2022/cdn"> Chapter 22: CDN </option> <option value="/en/2022/http"> Chapter 23: HTTP </option> <option value="/en/2022/methodology"> Methodology </option> <option value="/en/2022/contributors"> Contributors </option> <option value="/en/search"> Search </option> <option value="https://cdn.httparchive.org/almanac/ebooks/web_almanac_2022_en.pdf" data-event="ebook-click"> Ebook PDF (32MB) </option> </select> </div> </li> <li> <div class="year-switcher js-show"> <label for="year-switcher-mobile" class="visually-hidden">Year Switcher</label> <select id="year-switcher-mobile"> <option value="/en/2024/performance"> 2024 </option> <option selected="selected" value="/en/2022/performance"> 2022 </option> <option value="/en/2021/performance"> 2021 </option> <option value="/en/2020/performance"> 2020 </option> <option value="/en/2019/performance"> 2019 </option> </select> </div> </li> <li> <div class="language-switcher js-show"> <label for="language-switcher-mobile" class="visually-hidden">Language Switcher</label> <select id="language-switcher-mobile"> <option selected="selected" lang="en" value="/en/2022/performance"> English </option> <option lang="ja" value="/ja/2022/performance"> 日本語 </option> <hr> <option value="https://github.com/HTTPArchive/almanac.httparchive.org/wiki/Translators'-Guide"> Help translate </option> </select> </div> </li> <li id="mobile-misc" class="misc"> <ul class="misc"> <li> <a href="https://httparchive.org/" aria-labelledby="ha-logo-mobile"> <svg width="70" height="35" role="img"> <title id="ha-logo-mobile">HTTP Archive home</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#ha-logo"></use> </svg> </a> </li> <li> <ul class="social-media"> <li> <a href="https://x.com/HTTPArchive" aria-labelledby="twitter-logo-mobile"> <svg width="20" height="20" role="img"> <title id="twitter-logo-mobile">Twitter</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> </a> </li> <li> <a href="https://bsky.app/profile/httparchive.org" aria-labelledby="bluesky-logo-mobile"> <svg width="20" height="20" role="img"> <title id="bluesky-logo-mobile">Bluesky</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bluesky-logo"></use> </svg> </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org" aria-labelledby="github-logo-mobile"> <svg width="22" height="20" role="img"> <title id="github-logo-mobile">GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> </a> </li> </ul> </li> </ul> </li> </ul> </nav> </div> </div> </header> <script nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"> // If JS is enabled then enable menus ASAP to avoid CLS as menu items change from links to buttons (function() { document.querySelectorAll('.js-hide').forEach(element => { // Don't just hide it - delete it completely to avoid any specifity issues element.parentNode.removeChild(element); }); document.querySelectorAll('.js-enable').forEach(element => { element.classList.remove('js-enable'); element.classList.remove('hidden'); element.disabled = false; element.hidden = false; }); })(); </script> <div class="container"> <main id="chapter" class="main"> <nav aria-label="Chapter table of contents" class="index"> <div class="index-box floating-card"> <h2 class="header"> <button type="button" class="index-btn" aria-expanded="false" aria-label="Open the Table of Contents" data-close-text="Close the Table of Contents" data-open-text="Open the Table of Contents">Index</button> <span class="no-button">Index</span> </h2> <ul> <li> <a href="#introduction">Introduction</a> </li> <li> <a href="#core-web-vitals">Core Web Vitals</a> </li> <li> <a href="#largest-contentful-paint-lcp">Largest Contentful Paint (LCP)</a> <ul> <li> <a href="#time-to-first-byte-ttfb">Time to First Byte (TTFB)</a> </li> <li> <a href="#first-contentful-paint-fcp">First Contentful Paint (FCP)</a> </li> <li> <a href="#lcp-metadata-and-best-practices">LCP metadata and best practices</a> <ul> <li> <a href="#render-blocking-resources">Render-blocking resources</a> </li> <li> <a href="#lcp-content-types">LCP content types</a> </li> <li> <a href="#lcp-prioritization">LCP prioritization</a> </li> <li> <a href="#lcp-static-discoverability">LCP static discoverability</a> </li> <li> <a href="#lcp-preloading">LCP preloading</a> </li> <li> <a href="#lcp-initiator">LCP initiator</a> </li> <li> <a href="#lcp-lazy-loading">LCP lazy-loading</a> </li> <li> <a href="#lcp-size">LCP size</a> </li> <li> <a href="#lcp-format">LCP format</a> </li> <li> <a href="#lcp-image-optimization">LCP image optimization</a> </li> <li> <a href="#lcp-host">LCP host</a> </li> </ul> </li> <li> <a href="#lcp-conclusions">LCP conclusions</a> </li> </ul> </li> <li> <a href="#cumulative-layout-shift-cls">Cumulative Layout Shift (CLS)</a> <ul> <li> <a href="#cls-metadata-and-best-practices">CLS metadata and best practices</a> <ul> <li> <a href="#explicit-dimensions">Explicit dimensions</a> </li> <li> <a href="#animations">Animations</a> </li> <li> <a href="#fonts">Fonts</a> </li> <li> <a href="#bfcache-eligibility">bfcache eligibility</a> </li> </ul> </li> <li> <a href="#cls-conclusions">CLS conclusions</a> </li> </ul> </li> <li> <a href="#first-input-delay-fid">First Input Delay (FID)</a> <ul> <li> <a href="#fid-metadata-and-best-practices">FID metadata and best practices</a> <ul> <li> <a href="#disabling-double-tap-to-zoom">Disabling double-tap to zoom</a> </li> <li> <a href="#total-blocking-time-tbt">Total Blocking Time (TBT)</a> </li> <li> <a href="#long-tasks">Long tasks</a> </li> </ul> </li> <li> <a href="#interaction-to-next-paint-inp">Interaction to Next Paint (INP)</a> <ul> <li> <a href="#inp-by-rank">INP by rank</a> </li> <li> <a href="#inp-as-a-hypothetical-cwv-metric">INP as a hypothetical CWV metric</a> </li> <li> <a href="#inp-and-tbt">INP and TBT</a> </li> </ul> </li> <li> <a href="#fid-conclusions">FID conclusions</a> </li> </ul> </li> <li> <a href="#conclusion">Conclusion</a> </li> </ul> </div> </nav> <div class="content"> <article id="maincontent" class="body"> <div class="subtitle"> Part II Chapter 12 </div> <h1 class="title title-lg"> Performance </h1> <div class="article-dates"> <div class="article-date"> Date published: <time id="published-date" datetime="2022-10-25T00:00:00.000Z">2022/10/25</time> </div> <div class="article-date"> Last updated: <time id="modified-date" datetime="2024-11-16T00:00:00.000Z">2024/11/16</time> </div> <script nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"> // Update chapter dates to locale/language-specific format immeadiately with inline // script to avoid annoying shift as much as possible since this is in initial viewport. function formatDates(selector) { if (window.Intl && window.Intl.DateTimeFormat) { var publishedDateElement=document.querySelector(selector); if (!publishedDateElement) return; var publishedDate = new Date(publishedDateElement.getAttribute("datetime")); // Set up the date format - initially using the users default locale // This allows different locales in same language to be respected // (e.g. en-GB or en-US). var options = { day: "numeric", month: "short", year: "numeric", timeZone: "UTC" }; var dateFormat = new Intl.DateTimeFormat([], options) const usedOptions = dateFormat.resolvedOptions(); if (!usedOptions.locale.startsWith("en")) { // Reader is looking at a page in a language that is not their default locale // Set date format to page's language locale to avoid incorrect date translation. dateFormat = new Intl.DateTimeFormat("en", options) } publishedDateElement.textContent = dateFormat.format(publishedDate); } else { console.log("Could not format date"); } } formatDates("#published-date"); formatDates("#modified-date"); </script> </div> <!-- Show large image for large screens and high density screens and use avif and webp when supported --> <picture> <source media="(min-width: 866px)" type="image/avif" srcset="/static/images/2019/performance/hero_lg.avif"> <source media="(min-width: 866px)" type="image/webp" srcset="/static/images/2019/performance/hero_lg.webp"> <source media="(min-width: 866px)" type="image/jpeg" srcset="/static/images/2019/performance/hero_lg.jpg"> <source type="image/avif" srcset="/static/images/2019/performance/hero_sm.avif 1x, /static/images/2019/performance/hero_lg.avif 2x"> <source type="image/webp" srcset="/static/images/2019/performance/hero_sm.webp 1x, /static/images/2019/performance/hero_lg.webp 2x"> <source type="image/jpeg" srcset="/static/images/2019/performance/hero_sm.jpg 1x, /static/images/2019/performance/hero_lg.jpg 2x"> <img src="/static/images/2019/performance/hero_lg.jpg" class="content-banner" alt="Hero image of Web Almanac characters images to a web page, while another Web Almanac character times them with a stopwatch." width="866" height="433" fetchpriority="high"> </picture> <div class="bylines"> <div class="byline">Written by <a class="author" href="/en/2022/contributors#mel-ada">Melissa Ada</a> and <a class="author" href="/en/2022/contributors#rviscomi">Rick Viscomi</a> </div> <div class="byline reviewers">Reviewed by <a class="reviewer" href="/en/2022/contributors#tunetheweb">Barry Pollard</a>, <a class="reviewer" href="/en/2022/contributors#pmeenan">Patrick Meenan</a>, <a class="reviewer" href="/en/2022/contributors#25prathamesh">Prathamesh Rasam</a>, <a class="reviewer" href="/en/2022/contributors#estelle">Estelle Weyl</a>, and <a class="reviewer" href="/en/2022/contributors#konfirmed">Kanmi Obasa</a> </div> <div class="byline analysts">Analyzed by <a class="analyst" href="/en/2022/contributors#rviscomi">Rick Viscomi</a>, <a class="analyst" href="/en/2022/contributors#25prathamesh">Prathamesh Rasam</a>, <a class="analyst" href="/en/2022/contributors#siakaramalegos">Sia Karamalegos</a>, and <a class="analyst" href="/en/2022/contributors#konfirmed">Kanmi Obasa</a> </div> <div class="byline editors">Edited by <a class="editor" href="/en/2022/contributors#tunetheweb">Barry Pollard</a> </div> </div> <h2 id="introduction"><a href="#introduction" class="anchor-link">Introduction</a></h2> <p>Web performance is crucial to user experience. We’ve all bounced from a site due to slow load times, or worse, have not been able to access important information. Additionally, numerous <a hreflang="en" href="https://wpostats.com/">case studies</a> have demonstrated that an improvement in web performance results in an improvement in conversion and engagement for businesses. Surprisingly, the industry spotlight is quite elusive for web performance—why is this? Some may say web performance is tough to define and even more challenging to measure.</p> <p>How do we measure something that is hard to define in the first place? As <a href="https://x.com/sergeyche">Sergey Chernyshev</a>, creator of <a hreflang="en" href="https://github.com/ux-capture/ux-capture">UX Capture</a>, says, “<em>The best way to measure performance is to be embedded into the user’s brain to understand exactly what they’re thinking as they use the site</em>”. We can’t—and shouldn’t in case that was unclear—do this, so what are our options?</p> <p>Thankfully, there’s a way to measure some aspects of performance automatically! We know the browser is in charge of loading a page, and it goes through a checklist of steps each time. Depending on which step the browser is on, we can tell how far along the site is in the page load process. Conveniently, a <a href="https://developer.mozilla.org/docs/Web/API/Performance">number of performance timeline APIs</a> are used to fire off timestamps when the browser gets to certain page load steps.</p> <p>It’s important to note that these metrics are only our best guess at how to gauge user experience. For example, just because the browser fired an event that an element has been painted onto the screen, does that always mean it was visible to the user at that time? Additionally, as the industry grew, more and more metrics showed up while some became deprecated. It can be complicated to know where to start and understand what performance metrics are telling us about our users, especially for folks newer to the field.</p> <p>This chapter focuses on Google’s solution to the problem: <a hreflang="en" href="https://web.dev/articles/vitals">Core Web Vitals</a> (CWV), web performance metrics introduced in 2020 and made <a hreflang="en" href="https://developers.google.com/search/blog/2020/11/timing-for-page-experience">a signal in search ranking</a> during 2021. Each of the three metrics covers an important area of user experience: loading, interactivity, and visual stability. The public <a hreflang="en" href="https://developer.chrome.com/docs/crux">Chrome UX Report</a> (CrUX) dataset is Chrome’s view of how websites are performing on CWV. There’s zero setup on the developer’s part; Chrome automatically collects and publishes data from <a hreflang="en" href="https://developer.chrome.com/docs/crux/methodology#eligibility">eligible websites</a>, for users who have opted in. Using this dataset, we’re able to get insights into the web’s performance over time.</p> <p>Although the spotlight of this chapter, it’s important to note that CWV are relatively new to the field and not the only way to measure web performance. We chose to focus on these metrics because the search ranking influence was effective almost exactly one year ago, and this year’s data gives us insights on how the web is adjusting to this major shift in the industry and where room for opportunity might still exist. CWV are a common baseline that allows performance to be loosely comparable across sites, but it’s up to site owners to determine which metrics and strategies are best for their sites. As much as we wish otherwise, there’s no way to fit the entire history of the industry or all the different ways to evaluate performance in one chapter.</p> <p>The CWV program suggests a clearly defined approach to measuring how users actually experience performance—a first for the industry. Are CWV the answer to helping the web become more performant? This chapter examines where the web is currently with CWV and takes a look into the future.</p> <p class="note">Disclosure: This chapter is coauthored by an employee of Google, which created the Core Web Vitals program. This chapter and its underlying analysis were reviewed and approved by others not affiliated with Google.</p> <h2 id="core-web-vitals"><a href="#core-web-vitals" class="anchor-link">Core Web Vitals</a></h2> <p>Now that it’s been a year since CWV were added as a ranking signal in Google Search, let’s see how the program may have influenced user experiences on the web.</p> <figure id="fig-1"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-core-web-vitals-by-device.png" class=""> <img src="/static/images/2022/performance/good-core-web-vitals-by-device.png" alt="The percent of websites having good CWV, segmented by device and year." aria-labelledby="fig-1-caption" aria-describedby="fig-1-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1239858329&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-core-web-vitals-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-1-description" data-show-text="Show description of Figure 12.1" data-hide-text="Hide description of Figure 12.1">Show description of Figure 12.1</button> <div id="fig-1-description" class="hidden">Bar chart showing that in 2020 34% of websites used on desktop had good Core Web Vitals, versus 24% on phone. In 2021 that increased to 41% and 29% respectively, and in 2022 that further increased to 44% of desktop sites and 39% of phone sites.</div> <figcaption id="fig-1-caption"> <a href="#fig-1" class="anchor-link">Figure 12.1.</a> The percent of websites having good CWV, segmented by device and year. </figcaption> </figure> <p>In 2021, 29% of websites were assessed as having good CWV for mobile users. This was a significant step up from 2020, representing a 5 percentage point increase. However, the progress in 2022 was an even bigger leap forward, now with 39% of websites having good CWV on mobile—representing a further 10 point increase!</p> <p>44% of websites have good CWV on desktop. While this is better than mobile, the rate of improvement for desktop experiences is not as rapid as mobile, so the gap is closing.</p> <p>There are a few possible explanations for why mobile experiences tend to be worse than desktop. While the portability of a pocket-sized computer is a great convenience, it may have adverse effects on the user experience. As described in the <a href="./mobile-web#mobile-performance">Mobile Web</a> chapter, the smaller form factor has an impact on the amount of processing power that can be packed in, which is further constrained by the high cost to own more powerful phones. Devices with poorer processing capabilities take longer to perform the computations needed to render a web page. The portability of these devices also means that they can be taken into areas with poor connectivity, which hinders websites’ loading speeds. One final consideration is the way that developers decide how to build websites. Rather than creating a mobile-friendly version of the page, some websites may be serving desktop-sized images or unnecessary amounts of scripting functionality. All of these things put mobile users at a disadvantage compared to desktop users and may help to explain why their CWV performance is lower.</p> <p>Many more websites were assessed as having good CWV in 2022 relative to 2021. But how evenly distributed was that improvement across the web?</p> <figure id="fig-2"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-cwv-performance-by-rank-and-year.png" class=""> <img src="/static/images/2022/performance/good-cwv-performance-by-rank-and-year.png" alt="The percent of websites having good CWV, segmented by rank and year." aria-labelledby="fig-2-caption" aria-describedby="fig-2-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=737356809&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=863235163"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-cwv-performance-by-rank-and-year.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-2-description" data-show-text="Show description of Figure 12.2" data-hide-text="Hide description of Figure 12.2">Show description of Figure 12.2</button> <div id="fig-2-description" class="hidden">Bar chart showing the split of Good Core Web Vitals by rank over 2021 and 2022. For 2021 it was 37% for the top 1,000 websites, 31% for top 10,000, 29% for top 100,000, 30% for top million, and 32% overall. For 2022 it was 53% for the for the top 1,000 websites, 44% for top 10,000, 40% for top 100,000, 40% for top million, and 42% overall.</div> <figcaption id="fig-2-caption"> <a href="#fig-2" class="anchor-link">Figure 12.2.</a> The percent of websites having good CWV, segmented by rank and year. </figcaption> </figure> <p>We segmented sites by their relative popularity (rank) and year, without distinguishing between desktop and mobile. What’s interesting is that it seems websites across the board generally got more performant this year, regardless of their popularity. The top 1,000 most popular websites improved most significantly, a 16 percentage point increase to 53%, with all ranks improving by 10 points or more. The most popular websites also tend to have the best CWV experience, which is not too surprising if we assume that they have bigger engineering teams and budgets.</p> <p>To better understand why mobile experiences have gotten so much better this year, let’s dive deeper into each individual CWV metric.</p> <h2 id="largest-contentful-paint-lcp"><a href="#largest-contentful-paint-lcp" class="anchor-link">Largest Contentful Paint (LCP)</a></h2> <p><a hreflang="en" href="https://web.dev/articles/lcp">Largest Contentful Paint</a> (LCP) is the time from the start of the navigation until the largest block of content is visible in the viewport. This metric represents how quickly users are able to see what is likely the most meaningful content.</p> <p>We say that a website has good LCP if at least 75 percent of all page views are faster than 2,500 ms. Of the three CWV metrics, LCP pass rates are the lowest, often making it the bottleneck to achieving good CWV assessments.</p> <figure id="fig-3"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-lcp-by-device.png" class=""> <img src="/static/images/2022/performance/good-lcp-by-device.png" alt="The percent of websites having good LCP, segmented by device and year." aria-labelledby="fig-3-caption" aria-describedby="fig-3-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1542261080&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-lcp-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-3-description" data-show-text="Show description of Figure 12.3" data-hide-text="Hide description of Figure 12.3">Show description of Figure 12.3</button> <div id="fig-3-description" class="hidden">Bar chart showing the number of websites with good LCP increased from 53% in 2020 to 60% in 2021 to 63% in 2022. For sites visited on phones the increase was from 43% in 2020 to 45% in 2021 and then to 51% in 2022.</div> <figcaption id="fig-3-caption"> <a href="#fig-3" class="anchor-link">Figure 12.3.</a> The percent of websites having good LCP, segmented by device and year. </figcaption> </figure> <p>This year, 51% of websites have good LCP experiences on mobile and 63% on desktop. LCP appears to be one of the major reasons why websites’ mobile experiences have gotten so much better in 2022, having a 6 percentage point improvement this year.</p> <p>Why did LCP improve so much this year? To help answer that, let’s explore a couple of loading performance diagnostic metrics: TTFB and FCP.</p> <h3 id="time-to-first-byte-ttfb"><a href="#time-to-first-byte-ttfb" class="anchor-link">Time to First Byte (TTFB)</a></h3> <p><a hreflang="en" href="https://web.dev/articles/ttfb">Time to First Byte</a> (TTFB) is the time from the start of the navigation to the first byte of data returned to the client. It’s our first step in the web performance checklist, representing the backend component of LCP performance, particularly network connection speeds and server response times.</p> <figure id="fig-4"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-ttfb-by-device.png" class=""> <img src="/static/images/2022/performance/good-ttfb-by-device.png" alt="The percent of websites having good TTFB, segmented by device and year." aria-labelledby="fig-4-caption" aria-describedby="fig-4-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=628253519&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-ttfb-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-4-description" data-show-text="Show description of Figure 12.4" data-hide-text="Hide description of Figure 12.4">Show description of Figure 12.4</button> <div id="fig-4-description" class="hidden">Bar chart showing the number of websites with good TTFB increased from 47% in 2020 to 51% in 2021 to 52% in 2022. For sites visited on phones the it was fairly stable with 41% of sites achieving good TTFB in 2020, 39% in 2021 and 40% in 2022.</div> <figcaption id="fig-4-caption"> <a href="#fig-4" class="anchor-link">Figure 12.4.</a> The percent of websites having good TTFB, segmented by device and year. </figcaption> </figure> <p>As an aside, note that earlier this year Chrome <a hreflang="en" href="https://developer.chrome.com/docs/crux/release-notes#202204">changed</a> the threshold for “good” TTFB from 500 ms to 800 ms. In the chart above, all historical data is using this new threshold for comparison purposes.</p> <p>With that in mind, the percentage of websites having good TTFB has not actually improved very much. In the past year, websites’ desktop and mobile experiences have gotten one percentage point better, which is nice but doesn’t account for the gains observed to LCP. While this doesn’t rule out improvements to the “needs improvement” and “poor” ends of the TTFB distribution, the “good” end is what matters most.</p> <p>Another complication is that TTFB is still considered to be an <a hreflang="en" href="https://developer.chrome.com/docs/crux/methodology#experimental-metrics">experimental</a> metric in CrUX. According to the CrUX documentation, TTFB <em>does not</em> factor in more advanced navigation types like pre-rendered and back/forward navigations. This is somewhat of a blind spot, so if there were improvements in these areas, they wouldn’t necessarily affect the TTFB results.</p> <h3 id="first-contentful-paint-fcp"><a href="#first-contentful-paint-fcp" class="anchor-link">First Contentful Paint (FCP)</a></h3> <p><a hreflang="en" href="https://web.dev/articles/fcp">First Contentful Paint</a> (FCP) is the time from the start of the request to the first meaningful content painted to the screen. In addition to TTFB, this metric can be affected by render-blocking content. The threshold for “good” FCP is 1,800 ms.</p> <figure id="fig-5"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-fcp-by-device.png" class=""> <img src="/static/images/2022/performance/good-fcp-by-device.png" alt="The percent of websites having good FCP, segmented by device and year." aria-labelledby="fig-5-caption" aria-describedby="fig-5-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=831105883&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-fcp-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-5-description" data-show-text="Show description of Figure 12.5" data-hide-text="Hide description of Figure 12.5">Show description of Figure 12.5</button> <div id="fig-5-description" class="hidden">Bar chart showing the number of websites with good FCP increased from 53% in 2020 to 60% in 2021 to 64% in 2022. For sites visited on phones the it was 38% of sites achieving good FCP in 2020, and the same 2021, increasing to 49% in 2022.</div> <figcaption id="fig-5-caption"> <a href="#fig-5" class="anchor-link">Figure 12.5.</a> The percent of websites having good FCP, segmented by device and year. </figcaption> </figure> <p>FCP improved dramatically this year, with 49% of websites having good mobile experiences and 64% for desktop. This represents an 11 and 4 percentage point increase for mobile and desktop, respectively.</p> <p>In the absence of TTFB data to the contrary, this indicates that there were major improvements to frontend optimizations, like eliminating render-blocking resources or better resource prioritization. However, as we’ll see in the following sections, it seems like there may have been something else entirely to thank for the LCP improvements this year.</p> <h3 id="lcp-metadata-and-best-practices"><a href="#lcp-metadata-and-best-practices" class="anchor-link">LCP metadata and best practices</a></h3> <p>These performance improvements may not actually be due to changes to the websites themselves. Changes to network infrastructure, operating systems, or browsers could also impact LCP performance at web-scale like this, so let’s dig into some heuristics.</p> <h4 id="render-blocking-resources"><a href="#render-blocking-resources" class="anchor-link">Render-blocking resources</a></h4> <p>A page is considered to have render-blocking resources if resources hold up the initial paint (or render) of the page. This is particularly likely for critical scripts and styles that are loaded over the network. Lighthouse includes an <a hreflang="en" href="https://web.dev/render-blocking-resources/">audit</a> that checks for these resources, which we’ve run on the home page of each website in CrUX. You can learn more about how we test these pages in our <a href="./methodology">Methodology</a>.</p> <figure id="fig-6"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/pages-passing-render-blocking-resources-audit.png" class=""> <img src="/static/images/2022/performance/pages-passing-render-blocking-resources-audit.png" alt="The percent of pages that pass the render-blocking Lighthouse audit , segmented by device and year." aria-labelledby="fig-6-caption" aria-describedby="fig-6-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1619115021&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1317344415"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/render_blocking_resources.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/pages-passing-render-blocking-resources-audit.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-6-description" data-show-text="Show description of Figure 12.6" data-hide-text="Hide description of Figure 12.6">Show description of Figure 12.6</button> <div id="fig-6-description" class="hidden">Bar chart showing 19% of mobile pages passed the “render-blocking resources” audit in 2021. In 2022 this increased slightly to 20%, and we also added the desktop equivalent which was 14%.</div> <figcaption id="fig-6-caption"> <a href="#fig-6" class="anchor-link">Figure 12.6.</a> The percent of pages that pass the render-blocking Lighthouse audit , segmented by device and year. </figcaption> </figure> <p>Surprisingly, there was no dramatic improvement in the percent of pages that have render-blocking resources. Only 20% of mobile pages pass the audit, which is a mere 1 percentage point increase over last year.</p> <p>2022 is the first year in which we have Lighthouse data for desktop. So while we’re unable to compare it against previous years, it’s still interesting to see that many fewer desktop pages pass the audit relative to mobile, in spite of the trend of desktop pages tending to have better LCP and FCP performance.</p> <h4 id="lcp-content-types"><a href="#lcp-content-types" class="anchor-link">LCP content types</a></h4> <p>The LCP element can be a number of different types of content, like an image, a heading, or a paragraph of text.</p> <figure id="fig-7"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/top-lcp-element-types.png" class=""> <img src="/static/images/2022/performance/top-lcp-element-types.png" alt="The percent of pages that have a given element as its LCP." aria-labelledby="fig-7-caption" aria-describedby="fig-7-description" width="600" height="702" data-width="600" data-height="702" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=932136285&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1174093943"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_element_data.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/top-lcp-element-types.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-7-description" data-show-text="Show description of Figure 12.7" data-hide-text="Hide description of Figure 12.7">Show description of Figure 12.7</button> <div id="fig-7-description" class="hidden">Bar chart showing <code>IMG</code> is the LCP element on 47% of desktop pages and 42% of mobile pages, <code>DIV</code> on 28% and 26% respectively, <code>P</code> on 6% and 9%, <code>H1</code> on 3% and 5%, <code>undetected</code> on 3% and 3%, <code>SECTION</code> on 3% and 3%, <code>H2</code> on 1% and 2%, <code>A</code> on 1% and 2%, <code>SPAN</code> on 1% and 1%, <code>H3</code> on 0% and 1%, <code>HEADER</code> on 1% and 1%, <code>LI</code> on 1% and 1%, <code>RS-SBG</code> on 1% and 1%, <code>TD</code> on 1% and 1%, <code>VIDEO</code> on 0% and 0%, and finally <code>H4</code> is the LCP element type on 0% of both desktop and mobile pages.</div> <figcaption id="fig-7-caption"> <a href="#fig-7" class="anchor-link">Figure 12.7.</a> The percent of pages that have a given element as its LCP. </figcaption> </figure> <p>It’s clear that images are the most common type of LCP content, with the <code>img</code> element representing the LCP on 42% of mobile pages. Mobile pages are slightly more likely to have heading and paragraph elements be the LCP than desktop pages, while desktop pages are more likely to have image elements as the LCP. One possible explanation is the way that mobile layouts—especially in portrait orientation—make images that are <em>not</em> responsive appear smaller, giving way to large blocks of text like headings and paragraphs to become the LCP elements.</p> <p>The second most popular LCP element type is <code>div</code>. This is a generic HTML container that could be used for text or styling background images. To help disambiguate how often these elements contain images or text, we can evaluate the <code>url</code> property of the <a href="https://developer.mozilla.org/docs/Web/API/LargestContentfulPaint">LCP API</a>. According to the <a hreflang="en" href="https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-url">specification</a>, when this property is set, the LCP content must be an image.</p> <figure id="fig-8"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/top-lcp-content-types.png" class=""> <img src="/static/images/2022/performance/top-lcp-content-types.png" alt="The percent of pages that use each type of LCP content." aria-labelledby="fig-8-caption" aria-describedby="fig-8-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=839846485&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=872701281"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_resource_type.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/top-lcp-content-types.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-8-description" data-show-text="Show description of Figure 12.8" data-hide-text="Hide description of Figure 12.8">Show description of Figure 12.8</button> <div id="fig-8-description" class="hidden">Bar chart showing an image is the LCP content type on 82% of desktop pages and 72% of mobile pages, it is text on 17% and 26% respectively, and an inline image on 2% of desktop and 1% of mobile pages.</div> <figcaption id="fig-8-caption"> <a href="#fig-8" class="anchor-link">Figure 12.8.</a> The percent of pages that use each type of LCP content. </figcaption> </figure> <p>We see that 72% of mobile pages and 82% of desktop pages have images as their LCP. For example, these images may be traditional <code>img</code> elements or CSS background images. This suggests that the vast majority of the <code>div</code> elements seen in the previous figure are images as well. 26% of mobile pages and 17% of desktop pages have text-based content as their LCP.</p> <p>1% of pages actually use inline images as their LCP content. This is almost always a bad idea for a number of reasons, mostly around caching and complexity.</p> <h4 id="lcp-prioritization"><a href="#lcp-prioritization" class="anchor-link">LCP prioritization</a></h4> <p>After the HTML document is loaded, there are two major factors that affect how quickly the LCP resource itself can be loaded: discoverability and prioritization. We’ll explore <a href="#lcp-static-discoverability">LCP discoverability</a> later, but first let’s look at how LCP images are prioritized.</p> <p>Images are not loaded at high priority by default, but thanks to the new <a hreflang="en" href="https://web.dev/articles/fetch-priority">Priority Hints</a> API, developers can explicitly set their LCP images to load at high priority to take precedence over non-essential resources.</p> <figure id="fig-9"> <div class="figure-wrapper"> <div class="big-number">0.03%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=600760184"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_element_data_2.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-9-caption"> <a href="#fig-9" class="anchor-link">Figure 12.9.</a> The percent of pages that use <code>fetchpriority=high</code> on their LCP element. </figcaption> </figure> <p>0.03% of pages use <code>fetchpriority=high</code> on their LCP elements. Counterproductively, a handful of pages actually <em>lower</em> the priority over their LCP images: 77 pages on mobile and 104 on desktop.</p> <p><code>fetchpriority</code> is still very new and not supported everywhere, but there’s little to no reason why it shouldn’t be in every developer’s toolbox. <a href="https://x.com/patmeenan">Patrick Meenan</a>, who helped develop the API, <a href="https://x.com/patmeenan/status/1460276602479251457">describes it</a> as a “cheat code” given how easy it is to implement relative to the potential improvements.</p> <h4 id="lcp-static-discoverability"><a href="#lcp-static-discoverability" class="anchor-link">LCP static discoverability</a></h4> <p>Ensuring an LCP image is discovered early is key to the browser loading it as soon as possible. Even the <a href="#lcp-prioritization">prioritization</a> improvements that we discussed above, cannot help if the browser does not know it needs to load the resource until later.</p> <p>An LCP image is considered to be <em>statically discoverable</em> if its source URL can be parsed directly from the markup sent by the server. This definition includes sources defined within <code>picture</code> or <code>img</code> elements as well as sources that are explicitly preloaded.</p> <p>One caveat is that text-based LCP content is always statically discoverable based on this definition. However, text-based content may sometimes depend on client-side rendering or web fonts, so consider these results as lower bounds.</p> <pre><code class="html language-html"><span class="support tag"><span class="support tag"><</span><span class="support tag-name">img</span></span> <span class="support attribute">data-src</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">kitten.jpg</span><span class="string quote">"</span> <span class="support attribute">class</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">lazyload</span><span class="string quote">"</span><span class="support tag close">></span></code></pre> <p>Custom lazy-loading techniques like the example above are one way that images are prevented from being statically discoverable, since they rely on JavaScript to update the <code>src</code> attribute. Client-side rendering may also obscure the LCP content.</p> <figure id="fig-10"> <div class="figure-wrapper"> <div class="big-number">39%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1465687616"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_preload_discoverable.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-10-caption"> <a href="#fig-10" class="anchor-link">Figure 12.10.</a> The percent of mobile pages on which the LCP element was not statically discoverable. </figcaption> </figure> <p>39% of mobile pages have LCP elements that are not statically discoverable. This figure is even worse on desktop at 44% of pages, potentially as a consequence of the previous section’s finding that LCP content is more likely to be an image on desktop pages.</p> <p>This is the first year that we’re looking at this metric, so we don’t have historical data for comparison, but these results hint at a big opportunity to improve the load delay of LCP resources.</p> <h4 id="lcp-preloading"><a href="#lcp-preloading" class="anchor-link">LCP preloading</a></h4> <p>When the LCP image is not statically discoverable, <a hreflang="en" href="https://web.dev/preload-critical-assets/">preloading</a> can be an effective way to minimize the load delay. Of course, it would be better if the resource was statically discoverable to begin with, but addressing that may require a complex rearchitecture of the way the page loads. Preloading is somewhat of a quick fix by comparison, as it can be implemented with a single HTTP header or <code>meta</code> tag.</p> <figure id="fig-11"> <div class="figure-wrapper"> <div class="big-number">0.56%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1465687616"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_preload_discoverable.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-11-caption"> <a href="#fig-11" class="anchor-link">Figure 12.11.</a> The percent of mobile pages that preload their LCP images. </figcaption> </figure> <p>Only about 1 in 200 mobile pages preload their LCP images. This figure falls to about 1 in 400 (0.25%) when we only consider pages whose LCP images are not statically discoverable.</p> <p> Preloading statically discoverable images might be considered overkill, as the browser should already know about the image thanks to its <a hreflang="en" href="https://web.dev/preload-scanner/">preload scanner</a>. However, it can help load critical images earlier above other statically discoverable images that may be earlier in the HTML—for example header images or mega menu images. This is especially true for <a hreflang="en" href="https://caniuse.com/?search=fetchpriority">browsers that do not support <code>fetchpriority</code></a >. </p> <p>These results show that the overwhelming majority of the web could benefit from making their LCP images more discoverable. Loading LCP images sooner, either by making them statically discoverable or preloading them, can go a long way to improving LCP performance. But as with all things related to performance, always experiment to understand what’s best for your specific site.</p> <h4 id="lcp-initiator"><a href="#lcp-initiator" class="anchor-link">LCP initiator</a></h4> <p>When an LCP resource is not statically discoverable, there must be some other, more convoluted process by which it gets discovered.</p> <figure id="fig-12"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/top-lcp-initiators-among-pages-whose-lcp-is-not-statically-discoverable.png" class=""> <img src="/static/images/2022/performance/top-lcp-initiators-among-pages-whose-lcp-is-not-statically-discoverable.png" alt="The percent of pages whose LCP is not statically discoverable and initiated from a given resource." aria-labelledby="fig-12-caption" aria-describedby="fig-12-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1835555974&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1866346503"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_initiator_type_undiscoverable.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/top-lcp-initiators-among-pages-whose-lcp-is-not-statically-discoverable.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-12-description" data-show-text="Show description of Figure 12.12" data-hide-text="Hide description of Figure 12.12">Show description of Figure 12.12</button> <div id="fig-12-description" class="hidden">Bar chart showing that <code>html</code> is the initiator on 29% of desktop and 28% of mobile pages, <code>css</code> on 11% and 9% respectively, <code>unknown</code> on 5% and 4%, and finally <code>other</code> is the initiator on 0% of both desktop and mobile pages.</div> <figcaption id="fig-12-caption"> <a href="#fig-12" class="anchor-link">Figure 12.12.</a> The percent of pages whose LCP is not statically discoverable and initiated from a given resource. </figcaption> </figure> <p>27% of mobile pages have LCP images that are discovered in the HTML <em>after</em> the preload scanner has already run, typically due to script-based lazy-loading or client-side rendering.</p> <p>8% of mobile pages depend on an external stylesheet for their LCP resource, for example using the <code>background-image</code> property. This adds a link in the resource’s critical request chain and may further complicate LCP performance if the stylesheet is loaded cross-origin.</p> <p>4% of mobile pages have an undiscoverable LCP initiator whose type we’re unable to detect. These may be a combination of HTML and CSS initiators.</p> <p>Both script- and style-based discoverability issues are bad for performance, but their effects can be mitigated with preloading.</p> <h4 id="lcp-lazy-loading"><a href="#lcp-lazy-loading" class="anchor-link">LCP lazy-loading</a></h4> <p>Lazy-loading is an effective performance technique to delay when non-critical resources start loading, usually until they’re in or near the viewport. With precious bandwidth and rendering power freed up, the browser can load critical content earlier in the page load. A problem arises when lazy-loading is applied to the LCP image itself, because that prevents the browser from loading it until much later.</p> <figure id="fig-13"> <div class="figure-wrapper"> <div class="big-number">9.8%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=600760184"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_element_data_2.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-13-caption"> <a href="#fig-13" class="anchor-link">Figure 12.13.</a> The percent of mobile pages having image-based LCP that set <code>loading=lazy</code> on it. </figcaption> </figure> <p>Nearly 1 in 10 of pages with <code>img</code>-based LCP are using the native <code>loading=lazy</code> attribute. Technically, these images are statically discoverable, but the browser will need to wait to start loading them until it’s laid out the page to know whether they will be in the viewport. LCP images are always in the viewport, by definition, so in reality none of these images should have been lazy-loaded. For pages whose LCP varies by viewport size or initial scroll position from deep-linked navigations, it’s worth testing whether eagerly loading the LCP candidate results in better overall performance.</p> <p>Note that the percentages in this section are out of only those pages in which the <code>img</code> element is the LCP, not all pages. For reference, recall that this accounts for 42% of pages.</p> <figure id="fig-14"> <div class="figure-wrapper"> <div class="big-number">8.8%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1585533536"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_lazy.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-14-caption"> <a href="#fig-14" class="anchor-link">Figure 12.14.</a> The percent of mobile pages having image-based LCP that use custom lazy-loading on it. </figcaption> </figure> <p>As we showed earlier, one way that sites might polyfill the native lazy-loading behavior is to assign the image source to a <code>data-src</code> attribute and include an identifier like <code>lazyload</code> in the class list. Then, a script will watch the positions of images with this class name relative to the viewport, and swap the <code>data-src</code> value for the native <code>src</code> value to trigger the image to start loading.</p> <p>Nearly as many pages are using this kind of custom lazy-loading behavior as native lazy-loading, at 8.8% of pages with <code>img</code>-based LCP.</p> <p>Beyond the adverse performance effects of lazy-loading LCP images, native image lazy-loaded is <a hreflang="en" href="https://caniuse.com/loading-lazy-attr">supported</a> by all major browsers, so custom solutions may be adding unnecessary overhead. In our opinion, while some custom solutions may provide more granular control over when images load, developers should remove these extraneous polyfills and defer to the user agent’s native lazy-loading heuristics.</p> <p>Another benefit to using native lazy-loading is that browsers like Chrome are <a hreflang="en" href="https://bugs.chromium.org/p/chromium/issues/detail?id=996963">experimenting with using heuristics to ignore the attribute on probable LCP candidates</a>. This is only possible with native lazy-loading, so custom solutions would not benefit from any improvements in this case.</p> <figure id="fig-15"> <div class="figure-wrapper"> <div class="big-number">18%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1585533536"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_lazy.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-15-caption"> <a href="#fig-15" class="anchor-link">Figure 12.15.</a> The percent of mobile pages having image-based LCP that use native or custom lazy-loading on it. </figcaption> </figure> <p>Looking at pages that use either technique, 18% of pages with <code>img</code>-based LCP are unnecessarily delaying the load of their most important images.</p> <p>Lazy-loading is a good thing when used correctly, but these stats strongly suggest that there’s a major opportunity to improve performance by removing this functionality from LCP images in particular.</p> <p>WordPress was one of the pioneers of native lazy-loading adoption, and between versions 5.5 and 5.9, it didn’t actually omit the attribute from LCP candidates. So let’s explore the extent to which WordPress is still contributing to this anti-pattern.</p> <figure id="fig-16"> <div class="figure-wrapper"> <div class="big-number">72%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1585533536"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_lazy_wordpress.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-16-caption"> <a href="#fig-16" class="anchor-link">Figure 12.16.</a> The percent of mobile pages using native lazy-loading on their LCP image that also use WordPress. </figcaption> </figure> <p>According to the <a href="./cms">CMS</a> chapter, <a href="./cms#most-popular-cmss">WordPress is used by 35% of pages</a>. So it’s surprising to see that 72% of pages that use native lazy-loading on their LCP image are using WordPress, given that a fix has been available since January 2022 in version 5.9. One theory that needs more investigation is that plugins may be circumventing the safeguards built into WordPress core by injecting LCP images onto the page with the lazy-loading behavior.</p> <figure id="fig-17"> <div class="figure-wrapper"> <div class="big-number">54%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1585533536"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_lazy_wordpress.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-17-caption"> <a href="#fig-17" class="anchor-link">Figure 12.17.</a> The percent of mobile pages using custom lazy-loading on their LCP image that also use WordPress. </figcaption> </figure> <p>Similarly, a disproportionately high percentage of pages that use custom lazy-loading are built with WordPress at 54%. This hints at a wider issue in the WordPress ecosystem about lazy-loading overuse. Rather than being a fixable bug localized to WordPress core, there may be hundreds or thousands of separate themes and plugins contributing to this anti-pattern.</p> <h4 id="lcp-size"><a href="#lcp-size" class="anchor-link">LCP size</a></h4> <p>A major factor in the time it takes to load the LCP resource is its size over the wire. Larger resources will naturally take longer to load. So for image-based LCP resources, how large are they?</p> <figure id="fig-18"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/lcp-image-size-distribution.png" class=""> <img src="/static/images/2022/performance/lcp-image-size-distribution.png" alt="Distribution of the size of image-based LCP resources." aria-labelledby="fig-18-caption" aria-describedby="fig-18-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1738717687&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=916137359"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_bytes_distribution.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/lcp-image-size-distribution.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-18-description" data-show-text="Show description of Figure 12.18" data-hide-text="Hide description of Figure 12.18">Show description of Figure 12.18</button> <div id="fig-18-description" class="hidden">Bar chart showing that at the 10th percentile the LCP image size is 15 KB on desktop and 12 KB on mobile, at the 25th percentile it’s 46 KB and 34 KB, 50th percentile it’s 124 KB and 95 KB, at the 75th percentile it’s 301 KB and 244 KB, and finally at the 90th percentile it’s 666 KB on desktop and 565 KB on mobile.</div> <figcaption id="fig-18-caption"> <a href="#fig-18" class="anchor-link">Figure 12.18.</a> Distribution of the size of image-based LCP resources. </figcaption> </figure> <p>The median LCP image on mobile is 95 KB. To be honest, we expected much worse!</p> <p>Desktop pages tend to have larger LCP images across the distribution, with a median size of 124 KB.</p> <figure id="fig-19"> <div class="figure-wrapper"> <div class="big-number">114,285 KB</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=916137359"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_bytes_distribution.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-19-caption"> <a href="#fig-19" class="anchor-link">Figure 12.19.</a> The size of the largest LCP image. </figcaption> </figure> <p>We also looked at the largest LCP image sizes and found a 68,607 KB image on desktop and 114,285 KB image on mobile. While it can be fun to look at how obscenely large these outliers are, let’s keep in mind the unfortunate reality that these are active websites visited by real users. Data isn’t always free, and performance problems like these start to become <a href="./accessibility">accessibility</a> problems for users on metered mobile data plans. These are also <a href="./sustainability">sustainability</a> problems considering how much energy is wasted loading blatantly oversized images like these.</p> <figure id="fig-20"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/lcp-image-size-histogram.png" class=""> <img src="/static/images/2022/performance/lcp-image-size-histogram.png" alt="Histogram of image-based LCP sizes." aria-labelledby="fig-20-caption" aria-describedby="fig-20-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=664106183&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=201472151"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_bytes_histogram.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/lcp-image-size-histogram.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-20-description" data-show-text="Show description of Figure 12.20" data-hide-text="Hide description of Figure 12.20">Show description of Figure 12.20</button> <div id="fig-20-description" class="hidden">Bar chart showing the LCP image size is 0 - 100 KB for 1% of desktop and mobile pages, it’s 100 - 200 KB for 43% of desktop and 51% of mobile pages, it’s 200 - 300 KB for 20% and 19% respectively, it’s 300 - 400 KB for 11% and 9%, it’s 400 - 500 KB for 6% and 5%, it’s 500 - 600 KB for 4% and 3%, it’s 600 - 700 KB for 3% and 2%, it’s 700 - 800 KB for 2% and 2%, it’s 800 - 900 KB for 2% and 1%, it’s 900 - 1000 KB for 1% and 1%, and finally it’s over 1000 KB for 7% of desktop and 5% of mobile pages.</div> <figcaption id="fig-20-caption"> <a href="#fig-20" class="anchor-link">Figure 12.20.</a> Histogram of image-based LCP sizes. </figcaption> </figure> <p>Looking at it a different way, the figure above shows the distribution as a histogram in 100 KB increments. This view makes it clearer to see how LCP image sizes fall predominantly in the sub-200 KB range. We also see that 5% of LCP images on mobile are greater than 1,000 KB in size.</p> <p>How large an LCP image should <em>optimally</em> be depends on many factors. But the fact that 1 in 20 websites are serving megabyte-sized images to our <a href="./methodology#webpagetest">360px-wide</a> mobile viewports clearly highlights the need for site owners to embrace <a href="https://developer.mozilla.org/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">responsive images</a>. For more analysis on this topic, refer to the <a href="./media#srcset">Media</a> and <a href="./mobile-web#responsive-images">Mobile Web</a> chapters.</p> <h4 id="lcp-format"><a href="#lcp-format" class="anchor-link">LCP format</a></h4> <p>Choice of LCP image format can have <a href="./media#bits-per-pixel-by-format">significant effects</a> on its byte size and ultimately its loading performance. WebP and AVIF are two relatively newer formats that are found to be more efficient than traditional formats like JPG (or JPEG) and PNG.</p> <figure id="fig-21"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/lcp-image-formats.png" class=""> <img src="/static/images/2022/performance/lcp-image-formats.png" alt="The percent of pages that use a given format for their LCP images." aria-labelledby="fig-21-caption" aria-describedby="fig-21-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=98443529&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1281945683"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_format.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/lcp-image-formats.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-21-description" data-show-text="Show description of Figure 12.21" data-hide-text="Hide description of Figure 12.21">Show description of Figure 12.21</button> <div id="fig-21-description" class="hidden">Bar chart showing <code>jpg</code> is the LCP image format for 67% of desktop and mobile pages using LCP images, <code>png</code> for 26% of both, <code>webp</code> for 4% of both, <code>gif</code> for 2% of both, <code>svg</code> for 1% of both, and <code>avif</code>, <code>ico</code>, <code>heic</code>, and <code>heif</code> all show as 0% for both.</div> <figcaption id="fig-21-caption"> <a href="#fig-21" class="anchor-link">Figure 12.21.</a> The percent of pages that use a given format for their LCP images. </figcaption> </figure> <p>According to the <a href="./media#format-adoption">Media</a> chapter, the JPG format makes up about 40% of all images loaded on mobile pages. However, JPG makes up 67% of all LCP images on mobile, which is 2.5x more common than PNG at 26%. These results may hint at a tendency for pages to use photographic-quality images as their LCP resource rather than digital artwork, as photographs tend to compress better as JPG compared to PNG, but this is just speculation.</p> <p>4% of pages with image-based LCP use WebP. This is good news for image efficiency, however less than 1% are using AVIF. While AVIF may compress even better than WebP, it’s not supported in all modern browsers, which explains its low adoption. On the other hand, WebP <em>is</em> supported in all modern browsers, so its low adoption represents a major opportunity to optimize LCP images and their performance.</p> <h4 id="lcp-image-optimization"><a href="#lcp-image-optimization" class="anchor-link">LCP image optimization</a></h4> <p>The previous section looked at the popularity of various image formats used by LCP resources. Another way that developers can make their LCP resources smaller and load more quickly is to utilize efficient compression settings. The JPG format can be lossily compressed to eke out unnecessary bytes without losing too much image quality. However, some JPG images may not be compressed enough.</p> <p>Lighthouse includes an <a hreflang="en" href="https://web.dev/uses-optimized-images/">audit</a> that will measure the byte savings from setting JPGs to compression level 85. If the image is more than 4 KB smaller as a result, the audit fails and it’s considered an opportunity for optimization.</p> <figure id="fig-22"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/lcp-image-optimization.png" class=""> <img src="/static/images/2022/performance/lcp-image-optimization.png" alt="Histogram of byte savings for JPG-based LCP images." aria-labelledby="fig-22-caption" aria-describedby="fig-22-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=894221089&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=369396330"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_wasted_bytes.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/lcp-image-optimization.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-22-description" data-show-text="Show description of Figure 12.22" data-hide-text="Hide description of Figure 12.22">Show description of Figure 12.22</button> <div id="fig-22-description" class="hidden">Bar chart showing how many bytes can be saved by optimizing JPG images that are the LCP resource. 68% of mobile pages have 0 kilobytes of savings, 20% have up to 100 KB, 5% 200 KB, 2% 300 KB, 1% 400 KB, and 4% 500 KB or more. Desktop pages have a similar distribution.</div> <figcaption id="fig-22-caption"> <a href="#fig-22" class="anchor-link">Figure 12.22.</a> Histogram of byte savings for JPG-based LCP images. </figcaption> </figure> <p>Of the pages whose LCP images are JPG-based and flagged by Lighthouse, 68% of them do not have opportunities to improve the LCP image via lossy compression alone. These results are somewhat surprising and suggest that the majority of “hero” JPG images use appropriate quality settings. That said, 20% of these pages could save as much as 100 KB and 4% can save 500 KB or more. Recall that the majority of LCP images are under 200 KB, so this is some serious savings!</p> <h4 id="lcp-host"><a href="#lcp-host" class="anchor-link">LCP host</a></h4> <p>In addition to the size and efficiency of the LCP image itself, the server from which it loads can also have an impact on its performance. Loading LCP images from the same origin as the HTML document tends to be faster because the open connection can be reused.</p> <p>However, LCP images may be loaded from other origins, like asset domains and image CDNs. When this happens, setting up the additional connection can take valuable time away from the LCP allowance.</p> <figure id="fig-23"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/cross-hosted-lcp-images.png" class=""> <img src="/static/images/2022/performance/cross-hosted-lcp-images.png" alt="Cross-hosted LCP images." aria-labelledby="fig-23-caption" aria-describedby="fig-23-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=65223493&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=139284544"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/lcp_host.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/cross-hosted-lcp-images.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-23-description" data-show-text="Show description of Figure 12.23" data-hide-text="Hide description of Figure 12.23">Show description of Figure 12.23</button> <div id="fig-23-description" class="hidden">Bar chart showing same host is used for the LCP image for 55% of desktop and 48% of mobile pages, cross host for 23% and 21% respectively, and other content is the LCP element for 21% of desktop and 31% of mobile pages.</div> <figcaption id="fig-23-caption"> <a href="#fig-23" class="anchor-link">Figure 12.23.</a> Cross-hosted LCP images. </figcaption> </figure> <p>One in five mobile pages cross-host their LCP images. The time to set up the connection to these third-party hosts could add unnecessary delays to the LCP time. It’s best practice to self-host LCP images on the same origin as the document, whenever possible. <a href="../2021/resource-hints">Resource hints</a> could be used to preconnect to the LCP origin—or better yet, preload the image itself—but these techniques are not very widely adopted.</p> <h3 id="lcp-conclusions"><a href="#lcp-conclusions" class="anchor-link">LCP conclusions</a></h3> <p>LCP performance has improved significantly this year, especially for mobile users. While we don’t have a definitive answer for why that happened, the data presented above does give us a few clues.</p> <p>What we’ve seen so far is that render-blocking resources are still quite prevalent, very few sites are using advanced prioritization techniques, and more than a third of LCP images are not statically discoverable. Without concrete data to suggest that site owners or large publishing platforms are concertedly optimizing these aspects of their LCP performance, other places to look are optimizations at the OS or browser level.</p> <p>According to a <a hreflang="en" href="https://blog.chromium.org/2022/03/a-new-speed-milestone-for-chrome.html#:~:text=Chrome%20continues%20to%20get%20faster%20on%20Android%20as%20well.%20Loading%20a%20page%20now%20takes%2015%25%20less%20time%2C%20thanks%20to%20prioritizing%20critical%20navigation%20moments%20on%20the%20browser%20user%20interface%20thread">Chromium blog post</a> in March 2022, loading performance on Android improved by 15%. The post doesn’t go into too much detail, but it credits the improvement to “<em>prioritizing critical navigation moments on the browser user interface thread</em>.” This may help explain why mobile performance outpaced desktop performance in 2022.</p> <p>The six percentage point improvement to LCP this year can only happen when hundreds of thousands of websites’ performance improves. Putting aside the tantalizing question of how that happened, let’s take a moment to appreciate that user experiences on the web <em>are</em> getting better. It’s hard work, but improvements like these make the ecosystem healthier and are worth celebrating.</p> <h2 id="cumulative-layout-shift-cls"><a href="#cumulative-layout-shift-cls" class="anchor-link">Cumulative Layout Shift (CLS)</a></h2> <p><a hreflang="en" href="https://web.dev/articles/cls">Cumulative Layout Shift</a> (CLS) is a layout stability metric that represents the amount that content unexpectedly moves around on the screen. We say that a website has good CLS if at least 75% of all navigations across the site have a score of 0.1 or less.</p> <figure id="fig-24"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-cls-by-device.png" class=""> <img src="/static/images/2022/performance/good-cls-by-device.png" alt="Good CLS by device." aria-labelledby="fig-24-caption" aria-describedby="fig-24-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=20373607&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-cls-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-24-description" data-show-text="Show description of Figure 12.24" data-hide-text="Hide description of Figure 12.24">Show description of Figure 12.24</button> <div id="fig-24-description" class="hidden">Bar chart showing the number of websites with good CLS increased from 54% in 2020 to 62% in 2021 to 65% in 2022. For sites visited on phones the it was 60% of sites achieving good CLS in 2020, 62% for 2021, increasing to 74% in 2022.</div> <figcaption id="fig-24-caption"> <a href="#fig-24" class="anchor-link">Figure 12.24.</a> Good CLS by device. </figcaption> </figure> <p>This year, the percentage of websites with “good” CLS improved significantly on mobile devices, going from 62% to 74%. CLS on desktop improved by 3 percentage points to 65%.</p> <p>While LCP is the bottleneck for most sites to be assessed as having good CWV overall, there’s no doubt that the major improvements to mobile CLS this year have had a positive effect on the CWV pass rates.</p> <p>What happened to improve mobile CLS by such a significant margin? One likely explanation is Chrome’s new and improved <a hreflang="en" href="https://web.dev/bfcache/">back/forward cache</a> (bfcache), which was released in version 96 in mid-November 2021. This change enabled eligible pages to be pristinely restored from memory during back and forward navigations, rather than having to “start over” by fetching resources from the HTTP cache—or worse, over the network—and reconstructing the page.</p> <figure id="fig-25"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/monthly-cls-lcp.png" class=""> <img src="/static/images/2022/performance/monthly-cls-lcp.png" alt="Monthly timeseries of the percent of websites having good mobile LCP and CLS." aria-labelledby="fig-25-caption" aria-describedby="fig-25-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1531911610&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1879625698"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/monthly_cls_lcp.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/monthly-cls-lcp.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-25-description" data-show-text="Show description of Figure 12.25" data-hide-text="Hide description of Figure 12.25">Show description of Figure 12.25</button> <div id="fig-25-description" class="hidden">Line chart showing the monthly percent of websites that whose mobile LCP and CLS is rated good. More websites have good CLS than LCP. The CLS line trends upwards starting at 62% in June 2021, bumps up to 67% in September 2021, and another bump to 73% starting in January 2022. LCP is also increasing, but the trend starts in November 2021 at 47% and steadily rises to 54% in May 2022.</div> <figcaption id="fig-25-caption"> <a href="#fig-25" class="anchor-link">Figure 12.25.</a> Monthly timeseries of the percent of websites having good mobile LCP and CLS. </figcaption> </figure> <p>This chart shows LCP and CLS performance over time at monthly granularity. Over a two month period starting in January 2022, after Chrome released the bfcache update, the percent of websites having good CLS started to climb much more quickly than before.</p> <p>But how did bfcache improve CLS so much? Due to the way Chrome instantly restores the page from memory, its layout is settled and unaffected by any of the initial instability that typically occurs during loading.</p> <p>One theory why LCP experiences didn’t improve as dramatically is that back/forward navigations were already pretty fast thanks to standard HTTP caching. Remember, the threshold for “good” LCP is 2.5 seconds, which is pretty generous assuming any critical resources would already be in cache, and there are no bonus points for making “good” experiences even faster.</p> <h3 id="cls-metadata-and-best-practices"><a href="#cls-metadata-and-best-practices" class="anchor-link">CLS metadata and best practices</a></h3> <p>Let’s explore how much of the web is adhering to CLS best practices.</p> <h4 id="explicit-dimensions"><a href="#explicit-dimensions" class="anchor-link">Explicit dimensions</a></h4> <p>The most straightforward way to avoid layout shifts is to reserve space for content by setting dimensions, for example using <code>height</code> and <code>width</code> attributes on images.</p> <figure id="fig-26"> <div class="figure-wrapper"> <div class="big-number">72%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1160188541"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_unsized_images.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-26-caption"> <a href="#fig-26" class="anchor-link">Figure 12.26.</a> The percent of mobile pages that fail to set explicit dimensions on at least one image. </figcaption> </figure> <p>72% of mobile pages have unsized images. This stat alone doesn’t give the full picture, because unsized images don’t always result in user-perceived layout shifts, for example if they load outside of the viewport. Still, it’s a sign that site owners may not be closely adhering to CLS best practices.</p> <figure id="fig-27"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/unsized-images.png" class=""> <img src="/static/images/2022/performance/unsized-images.png" alt="Distribution of the number of unsized images per page." aria-labelledby="fig-27-caption" aria-describedby="fig-27-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=449564630&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1160188541"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_unsized_images.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/unsized-images.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-27-description" data-show-text="Show description of Figure 12.27" data-hide-text="Hide description of Figure 12.27">Show description of Figure 12.27</button> <div id="fig-27-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentile number of images per page. The values for mobile are 0, 0, 2, 11, and 26 unsized images per page, respectively. Desktop pages have between 1 and 3 more unsized images per page in the 50 to 90th percentiles.</div> <figcaption id="fig-27-caption"> <a href="#fig-27" class="anchor-link">Figure 12.27.</a> Distribution of the number of unsized images per page. </figcaption> </figure> <p>The median web page has 2 unsized images and 10% of mobile pages have at least 26 unsized images.</p> <p>Having any unsized images on the page can be a liability for CLS, but perhaps a more important factor is the size of the image. Large images contribute to bigger layout shifts, which make CLS worse.</p> <figure id="fig-28"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/unsized-image-height.png" class=""> <img src="/static/images/2022/performance/unsized-image-height.png" alt="Distribution of the heights of unsized images." aria-labelledby="fig-28-caption" aria-describedby="fig-28-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1273679516&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=309190465"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_unsized_image_height.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/unsized-image-height.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-28-description" data-show-text="Show description of Figure 12.28" data-hide-text="Hide description of Figure 12.28">Show description of Figure 12.28</button> <div id="fig-28-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentile height of unsized images. The values for mobile are 16, 40, 99, 184, and 267px tall, respectively. The values for desktop are much larger: 18, 42, 113, 237, and 410px.</div> <figcaption id="fig-28-caption"> <a href="#fig-28" class="anchor-link">Figure 12.28.</a> Distribution of the heights of unsized images. </figcaption> </figure> <p>The median unsized image on mobile has a height of 99px. Given that our <a href="./methodology#webpagetest">test devices</a> have a mobile viewport height of 512px, that’s about 20% of the viewport area that would shift down, assuming full-width content. Depending on where that image is in the viewport when it loads, it could cause a <a hreflang="en" href="https://web.dev/articles/cls#layout-shift-score">layout shift score</a> of at most 0.2, which more than exceeds the 0.1 threshold for “good” CLS.</p> <p>Desktop pages tend to have larger unsized images. The median unsized image on desktop is 113px tall and the 90th percentile has a height of 410px.</p> <figure id="fig-29"> <div class="figure-wrapper"> <div class="really-big-number">4,048,234,137,947,990,000px</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=309190465"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_unsized_image_height.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-29-caption"> <a href="#fig-29" class="anchor-link">Figure 12.29.</a> The height of the largest unsized image. </figcaption> </figure> <p>In what we can only hope is either a measurement error or a seriously mistaken web developer, the largest unsized image that we found is an incredible 4 quintillion pixels tall. That image is so big it could stretch from the Earth to the moon… three million times. Even if that is some kind of one-off mistake, the next biggest unsized image is still 33,554,432 pixels tall. Either way, that’s a big layout shift.</p> <h4 id="animations"><a href="#animations" class="anchor-link">Animations</a></h4> <p>Some <a hreflang="en" href="https://web.dev/non-composited-animations/">non-composited</a> CSS animations can affect the layout of the page and contribute to CLS. The <a hreflang="en" href="https://web.dev/articles/optimize-cls#animations-%F0%9F%8F%83%E2%80%8D%E2%99%80%EF%B8%8F">best practice</a> is to use <code>transform</code> animations instead.</p> <figure id="fig-30"> <div class="figure-wrapper"> <div class="big-number">38%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=309190465"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_unsized_image_height.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-30-caption"> <a href="#fig-30" class="anchor-link">Figure 12.30.</a> The percent of mobile pages that have non-composited animations. </figcaption> </figure> <p>38% of mobile pages use these layout-altering CSS animations and risk making their CLS worse. Similar to the unused images issue, what matters most for CLS is the degree to which the animations affect the layout relative to the viewport.</p> <figure id="fig-31"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/animations.png" class=""> <img src="/static/images/2022/performance/animations.png" alt="Distribution of the number of non-composited animations per page." aria-labelledby="fig-31-caption" aria-describedby="fig-31-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=6443199&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=603122500"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/cls_animations.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/animations.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-31-description" data-show-text="Show description of Figure 12.31" data-hide-text="Hide description of Figure 12.31">Show description of Figure 12.31</button> <div id="fig-31-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentiles of the number of non-composited animations per page. At the 75th percentile, pages have 2 non-composited animations, and at the 90th percentile they have 10 for mobile and 11 for desktop.</div> <figcaption id="fig-31-caption"> <a href="#fig-31" class="anchor-link">Figure 12.31.</a> Distribution of the number of non-composited animations per page. </figcaption> </figure> <p>The distribution above shows that most pages don’t use these types of animations, and the ones that do only use it sparingly. At the 75th percentile, pages use them twice.</p> <h4 id="fonts"><a href="#fonts" class="anchor-link">Fonts</a></h4> <p>In the page load process, it can take some time for the browser to discover, request, download, and apply a web font. While this is all happening, it’s possible that text has already been rendered on a page. If the web font isn’t yet available, the browser can default to rendering text in a system font. Layout shifts happen when the web font becomes available and existing text, rendered in a system font, switches to the web font. The amount of layout shift caused depends on how different the fonts are from each other.</p> <figure id="fig-32"> <div class="figure-wrapper"> <div class="big-number">82%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1A1XwuGa1DkqNLaF-lSXz4ndxO9G6SfACHwUvvywHgbQ/edit#gid=1517999851"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/../fonts/font_usage_over_time.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-32-caption"> <a href="#fig-32" class="anchor-link">Figure 12.32.</a> The percent of mobile pages that use web fonts. </figcaption> </figure> <p>82% of pages use web fonts, so this section is highly relevant to most site owners.</p> <figure id="fig-33"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/font-display-usage.png" class=""> <img src="/static/images/2022/performance/font-display-usage.png" alt="Adoption of font-display values." aria-labelledby="fig-33-caption" aria-describedby="fig-33-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vQF6OH_2-0apcFzjE-iHSQNuZqp9DtM7udIeOzPSOSMM-Pf6KdTnRwAclX9QPZF1vNNgu6acZvqoN5b/pubchart?oid=1648924039&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1A1XwuGa1DkqNLaF-lSXz4ndxO9G6SfACHwUvvywHgbQ/edit#gid=1599822681&amp;range=G11"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/../fonts/font_display_usage.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/font-display-usage.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-33-description" data-show-text="Show description of Figure 12.33" data-hide-text="Hide description of Figure 12.33">Show description of Figure 12.33</button> <div id="fig-33-description" class="hidden">Bar chart showing the percent of pages that use the various <code>font-display</code> values. 29% of mobile pages use swap, 17% block, 8% auto, 2% fallback, and less than 1% use optional. The values for desktop are similar.</div> <figcaption id="fig-33-caption"> <a href="#fig-33" class="anchor-link">Figure 12.33.</a> Adoption of <code>font-display</code> values. </figcaption> </figure> <p> One way to avoid font-induced layout shifts is to use <a href="https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display"><code>font-display: optional</code></a >, which will never swap in a web font after the system text has already been shown. However, as noted by the <a href="./fonts#font-display">Fonts</a> chapter, less than 1% of pages are taking advantage of this directive. </p> <p>Even though <code>optional</code> is good for CLS, there are UX tradeoffs. Site owners might be willing to have some layout instability or a noticeable flash of unstyled text (FOUT) if it means that their preferred font can be displayed to users.</p> <p>Rather than hiding the web fonts, another strategy to mitigate CLS is to load them as quickly as possible. Doing so would, if all goes well, display the web font before the system text is rendered.</p> <figure id="fig-34"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/fonts-resource-hints.png" class=""> <img src="/static/images/2022/performance/fonts-resource-hints.png" alt="Adoption of resource hints for font resources." aria-labelledby="fig-34-caption" aria-describedby="fig-34-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vQF6OH_2-0apcFzjE-iHSQNuZqp9DtM7udIeOzPSOSMM-Pf6KdTnRwAclX9QPZF1vNNgu6acZvqoN5b/pubchart?oid=1831399490&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1A1XwuGa1DkqNLaF-lSXz4ndxO9G6SfACHwUvvywHgbQ/edit#gid=592046045&amp;range=F11"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/../fonts/resource_hints_usage.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/fonts-resource-hints.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-34-description" data-show-text="Show description of Figure 12.34" data-hide-text="Hide description of Figure 12.34">Show description of Figure 12.34</button> <div id="fig-34-description" class="hidden">Bar chart showing the percent of pages that use each type of resource hint on web fonts. 32% of mobile pages use dns-prefetch, 20% preload, 16% preconnect, and 2% preload. The values for desktop are similar.</div> <figcaption id="fig-34-caption"> <a href="#fig-34" class="anchor-link">Figure 12.34.</a> Adoption of resource hints for font resources. </figcaption> </figure> <p>According to the <a href="./fonts#resource-hints">Fonts</a> chapter, 20% of mobile pages are preloading their web fonts. One challenge with preloading the font is that the exact URL may not be known upfront, for example if using a service like Google Fonts. Preconnecting to the font host is the next best option for performance, but only 16% of pages are using that, which is half as many pages that use the less-performant option to prefetch the DNS.</p> <h4 id="bfcache-eligibility"><a href="#bfcache-eligibility" class="anchor-link">bfcache eligibility</a></h4> <p>We’ve shown how impactful bfcache can be for CLS, so it’s worth considering eligibility as a somewhat indirect best practice.</p> <p>The best way to tell if a given page is eligible for bfcache is to <a hreflang="en" href="https://web.dev/bfcache/#test-to-ensure-your-pages-are-cacheable">test it in DevTools</a>. Unfortunately, there are over <a hreflang="en" href="https://docs.google.com/spreadsheets/d/1li0po_ETJAIybpaSX5rW_lUN62upQhY0tH4pR5UPt60/edit?usp=sharing">100 eligibility criteria</a>, many of which are hard or impossible to measure in the lab. So rather than looking at bfcache eligibility as a whole, let’s look at a few criteria that are more easily measurable to get a sense for the lower bound of eligibility.</p> <figure id="fig-35"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/bfcache-unload.png" class=""> <img src="/static/images/2022/performance/bfcache-unload.png" alt="Usage of unload by site rank." aria-labelledby="fig-35-caption" aria-describedby="fig-35-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=63175690&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=996465265"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/bfcache_unload.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/bfcache-unload.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-35-description" data-show-text="Show description of Figure 12.35" data-hide-text="Hide description of Figure 12.35">Show description of Figure 12.35</button> <div id="fig-35-description" class="hidden">Bar chart showing the percent of pages that are ineligible for bfcache due to setting <code>unload</code> handlers, grouped by site popularity rank. 36% of the top 1 thousand mobile pages set this handler, 33% of the top 10 thousand, 27% of the top 100 thousand, 21% of the top million, and 17% of all mobile pages. Desktop pages tend to use the <code>unload</code> handler slightly more often by a couple of percentage points across the ranks.</div> <figcaption id="fig-35-caption"> <a href="#fig-35" class="anchor-link">Figure 12.35.</a> Usage of <code>unload</code> by site rank. </figcaption> </figure> <p> The <a href="https://developer.mozilla.org/docs/Web/API/Window/unload_event"><code>unload</code></a> event is a discouraged way to do work when the page is in the process of going away (unloading). Besides there being <a hreflang="en" href="https://web.dev/bfcache/#never-use-the-unload-event">better ways</a> to do that, it’s also one way to make your page ineligible for bfcache. </p> <p>17% of all mobile pages set this event handler, however the situation worsens the more popular the website is. In the top 1k, 36% of mobile pages are ineligible for bfcache for this reason.</p> <figure id="fig-36"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/bfcache-nostore.png" class=""> <img src="/static/images/2022/performance/bfcache-nostore.png" alt="Usage of Cache-Control: no-store by site rank." aria-labelledby="fig-36-caption" aria-describedby="fig-36-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1655848232&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1063873438"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/bfcache_cachecontrol_nostore.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/bfcache-nostore.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-36-description" data-show-text="Show description of Figure 12.36" data-hide-text="Hide description of Figure 12.36">Show description of Figure 12.36</button> <div id="fig-36-description" class="hidden">Bar chart showing the percent of pages that are ineligible for bfcache due to setting the <code>Cache-Control: no-store</code> header on the main document. 28% of the top 1 thousand mobile pages set this header, 27% of the top 10 thousand, 28% of the top 100 thousand, 27% of the top million, and 22% of all mobile pages. Desktop pages use this header slightly more often by up to 2 percentage points.</div> <figcaption id="fig-36-caption"> <a href="#fig-36" class="anchor-link">Figure 12.36.</a> Usage of <code>Cache-Control: no-store</code> by site rank. </figcaption> </figure> <p> The <a href="https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#no-store"><code>Cache-Control: no-store</code></a> header tells user agents never to cache a given resource. When set on the main HTML document, this makes the entire page ineligible for bfcache. </p> <p>22% of all mobile pages set this header, and 28% of mobile pages in the top 1k. This and the <code>unload</code> criteria are not mutually exclusive, so combined we can only say that at least 22% of mobile pages are ineligible for bfcache.</p> <p>To reiterate, it’s not that these things cause CLS issues. However, fixing them may make pages eligible for bfcache, which we’ve been shown to be an indirect yet powerful tool for improving layout stability.</p> <h3 id="cls-conclusions"><a href="#cls-conclusions" class="anchor-link">CLS conclusions</a></h3> <p>CLS is the CWV metric that improved the most in 2022 and it appears to have had a significant impact on the number of websites that have “good” overall CWV.</p> <p>The cause of this improvement seems to come down to Chrome’s launch of bfcache, which is reflected in the January 2022 CrUX dataset. However, at least a fifth of sites are ineligible for this feature due to aggressive <code>no-store</code> caching policies or discouraged use of the <code>unload</code> event listener. Correcting these anti-patterns is CLS’s “one weird trick” to improve performance.</p> <p>There are other, more direct ways site owners can improve their CLS. Setting <code>height</code> and <code>width</code> attributes on images is the most straightforward one. Optimizing how animations are styled and how fonts load are two other—admittedly more complex—approaches to consider.</p> <h2 id="first-input-delay-fid"><a href="#first-input-delay-fid" class="anchor-link">First Input Delay (FID)</a></h2> <p><a hreflang="en" href="https://web.dev/articles/fid">First Input Delay</a> (FID) measures the time from the first user interaction like a click or tap to the time at which the browser begins processing the corresponding event handlers. A website has “good” FID if at least 75 percent of all navigations across the site are faster than 100 ms.</p> <figure id="fig-37"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/good-fid-by-device.png" class=""> <img src="/static/images/2022/performance/good-fid-by-device.png" alt="Good FID by device." aria-labelledby="fig-37-caption" aria-describedby="fig-37-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1546220733&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/good-fid-by-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-37-description" data-show-text="Show description of Figure 12.37" data-hide-text="Hide description of Figure 12.37">Show description of Figure 12.37</button> <div id="fig-37-description" class="hidden">Bar chart showing 100% of websites had good FID in 2020, 2021, and 2022. For sites visited on phones this increased from 80% in 2020 to 90% in 2021 and then to 92% in 2022.</div> <figcaption id="fig-37-caption"> <a href="#fig-37" class="anchor-link">Figure 12.37.</a> Good FID by device. </figcaption> </figure> <p>Effectively all websites have “good” FID for desktop users, and this trend has held firm over the years. Mobile FID performance is also exceptionally fast, with 92% of websites having “good” FID, a slight improvement over last year.</p> <p>While it’s great that so many websites have good FID experiences, developers need to be careful not to become too complacent. Google has been <a hreflang="en" href="https://web.dev/better-responsiveness-metric/">experimenting with a new responsiveness metric</a> that could end up replacing FID, which is especially important because sites tend to perform much worse on <a href="./#interaction-to-next-paint-inp">this new metric</a> than FID.</p> <h3 id="fid-metadata-and-best-practices"><a href="#fid-metadata-and-best-practices" class="anchor-link">FID metadata and best practices</a></h3> <p>Let’s dig deeper into the ways that responsiveness can be improved across the web.</p> <h4 id="disabling-double-tap-to-zoom"><a href="#disabling-double-tap-to-zoom" class="anchor-link">Disabling double-tap to zoom</a></h4> <p>Some mobile browsers, including Chrome, wait at least 250 ms before handling tap inputs to make sure users aren’t attempting to <a hreflang="en" href="https://developer.chrome.com/blog/300ms-tap-delay-gone-away">double-tap to zoom</a>. Given that the threshold for “good” FID is 100 ms, this behavior makes it impossible to pass the assessment.</p> <pre><code class="html language-html"><span class="support tag"><span class="support tag"><</span><span class="support tag-name">meta</span></span> <span class="support attribute">name</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">viewport</span><span class="string quote">"</span> <span class="support attribute">content</span><span class="support operator">=</span><span class="string quote">"</span><span class="string value">width=device-width, initial-scale=1</span><span class="string quote">"</span><span class="support tag close">></span></code></pre> <p>There’s an easy fix, though. Including a <code>meta</code> viewport tag in the document head like the one above will prompt the browser to render the page as wide at the device width, which makes text content more legible and eliminates the need for double-tap to zoom.</p> <p>This is one of the quickest, easiest, and least intrusive ways to meaningfully improve responsiveness and all mobile pages should be setting it.</p> <figure id="fig-38"> <div class="figure-wrapper"> <div class="big-number">7.3%</div> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1839727600"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/viewport_meta_zoom_disable.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-38-caption"> <a href="#fig-38" class="anchor-link">Figure 12.38.</a> The percent of mobile pages that do not set a viewport <code>meta</code> tag. </figcaption> </figure> <p>7.3% of mobile pages fail to set the <code>meta</code> viewport directive. Recall that about 8% of mobile websites fail to meet the threshold for “good” FID. This is a significant proportion of the web that is needlessly slowing down their sites’ responsiveness. Correcting this may very well mean the difference between failing and passing the FID assessment.</p> <h4 id="total-blocking-time-tbt"><a href="#total-blocking-time-tbt" class="anchor-link">Total Blocking Time (TBT)</a></h4> <p><a hreflang="en" href="https://web.dev/tbt/">Total Blocking Time</a> (TBT) is the time between the <a hreflang="en" href="https://web.dev/articles/fcp">First Contentful Paint</a> (FCP) and <a hreflang="en" href="https://web.dev/tti/">Time to Interactive</a> (TTI), representing the total amount of time that the main thread was blocked and unable to respond to user inputs.</p> <p>TBT is often used as a lab-based proxy for FID, due to the challenges of realistically simulating user interactions in synthetic tests.</p> <figure id="fig-39"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/tbt.png" class=""> <img src="/static/images/2022/performance/tbt.png" alt="Distribution of lab-based TBT per page." aria-labelledby="fig-39-caption" aria-describedby="fig-39-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1459512477&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=528722499"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/fid_tbt.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/tbt.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-39-description" data-show-text="Show description of Figure 12.39" data-hide-text="Hide description of Figure 12.39">Show description of Figure 12.39</button> <div id="fig-39-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentile of lab-based TBT per page. The values for mobile pages are 0.2, 0.6, 1.7, 3.6, and 6.4 seconds, respectively. The values for desktop pages are much faster, with fewer than 100ms in the top 50 percent, about 250ms in the 75th percentile, and 600ms in the 90th percentile.</div> <figcaption id="fig-39-caption"> <a href="#fig-39" class="anchor-link">Figure 12.39.</a> Distribution of lab-based TBT per page. </figcaption> </figure> <p>Note that these results are sourced from the lab-based TBT performance of pages in the HTTP Archive dataset. This is an important distinction because for the most part we’ve been looking at real-user performance data from the CrUX dataset.</p> <p>With that in mind, we see that mobile pages have significantly worse TBT than desktop pages. This isn’t surprising given that our <a href="./methodology#lighthouse">Lighthouse</a> mobile environment is intentionally configured to run with a throttled CPU in a way that emulates a low-end mobile device. Nevertheless, the results show that the median mobile page has a TBT of 1.7 seconds, meaning that if this were a real-user experience, no taps within 1.7 seconds of FCP would be responsive. At the 90th percentile, a user would have to wait 6.3 seconds before the page became responsive.</p> <p>Despite the fact that these results come from synthetic testing, they’re based on the actual JavaScript served by real websites. If a real user on similar hardware tried to access one of these sites, their TBT might not be too different. That said, the key difference between TBT and FID is that the latter relies on the user actually interacting with the page, which they can do at any time before, during, or after the TBT window, all leading to vastly different FID values.</p> <h4 id="long-tasks"><a href="#long-tasks" class="anchor-link">Long tasks</a></h4> <p><a hreflang="en" href="https://web.dev/long-tasks-devtools/">Long tasks</a> are periods of script-induced CPU activity at least 50 ms long that prevent the main thread from responding to input. Any long task is liable to cause responsiveness issues if a user attempts to interact with the page at that time.</p> <p>Note that, like the TBT analysis above, this section draws from lab-based data. As a result, we’re only able to measure long tasks during the page load observation window, which starts when the page is requested and ends after 60 seconds or 3 seconds of network inactivity, whichever comes first. A real user may experience long tasks throughout the entire lifetime of the page.</p> <figure id="fig-40"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/long-tasks.png" class=""> <img src="/static/images/2022/performance/long-tasks.png" alt="Distribution of lab-based long tasks per page." aria-labelledby="fig-40-caption" aria-describedby="fig-40-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1004723255&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1849899474"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/fid_long_tasks.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/long-tasks.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-40-description" data-show-text="Show description of Figure 12.40" data-hide-text="Hide description of Figure 12.40">Show description of Figure 12.40</button> <div id="fig-40-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentiles of the sum of lab-based long tasks per page. The values for mobile are 0.8, 1.7, 3.3, 5.3, and 8.0 seconds of long tasks per page. The values for desktop are much faster at fewer than 100ms in the first 50%, followed by 700ms at the 75th percentile, and 1.4 seconds at the 90th percentile.</div> <figcaption id="fig-40-caption"> <a href="#fig-40" class="anchor-link">Figure 12.40.</a> Distribution of lab-based long tasks per page. </figcaption> </figure> <p>The median mobile web page has 3.3 seconds-worth of long tasks, compared to only 0.4 seconds for desktop pages. Again, this shows the outsized effects of CPU speed on responsiveness heuristics. At the 90th percentile, mobile pages have at least 8.0 seconds of long tasks.</p> <p>It’s also worth noting that these results are significantly higher than the distribution of TBT times. Remember that TBT is bounded by FCP and TTI and FID is dependent on both how busy the CPU is and when the user attempts to interact with the page. These post-TTI long tasks can also create frustrating responsiveness experiences, but unless they occur during the first interaction, they wouldn’t be represented by FID. This is one reason why we need a field metric that more comprehensively represents users’ experiences throughout the entire page lifetime.</p> <h3 id="interaction-to-next-paint-inp"><a href="#interaction-to-next-paint-inp" class="anchor-link">Interaction to Next Paint (INP)</a></h3> <p><a hreflang="en" href="https://web.dev/articles/inp">Interaction to Next Paint</a> (INP) measures the amount of time it takes for the browser to complete the next paint in response to a user interaction. This metric was created after Google <a hreflang="en" href="https://web.dev/responsiveness/">requested feedback</a> on a proposal to improve how we measure responsiveness. Many readers may be hearing about this metric for the first time, so it’s worth going into a bit more detail about how it works.</p> <p>An <em>interaction</em> in this context refers to the user experience of providing an input to a web application and waiting for the next frame of visual feedback to be painted on the screen. The only inputs that are considered for INP are clicks, taps, and key presses. The INP value itself is taken from one of the worst interaction latencies on the page. Refer to the <a hreflang="en" href="https://web.dev/articles/inp#what-is-inp">INP documentation</a> for more info on how it’s calculated.</p> <p>Unlike FID, INP is a measure of all interactions on the page, not just the first one. It also measures the entire time until the next frame is painted, unlike FID which only measures the time until the event handler starts processing. In these ways, INP is a much more representative metric of the holistic user experience on the page.</p> <p>A website has “good” INP if 75% of its INP experiences are faster than 200 ms. A website has “poor” INP if the 75th percentile is greater than or equal to 500 ms. Otherwise, it’s INP is assessed as “needs improvement”.</p> <figure id="fig-41"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/inp-device.png" class=""> <img src="/static/images/2022/performance/inp-device.png" alt="Distribution of INP performance by device." aria-labelledby="fig-41-caption" aria-describedby="fig-41-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=755106375&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=555510064"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/inp-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-41-description" data-show-text="Show description of Figure 12.41" data-hide-text="Hide description of Figure 12.41">Show description of Figure 12.41</button> <div id="fig-41-description" class="hidden">Bar chart showing the percent of websites having good, needs improvement, or poor INP by device. 95% of desktop websites have good INP, 4% need improvement, and 1% are poor. 55% of mobile websites have good INP, 36% need improvement, and 8% are poor.</div> <figcaption id="fig-41-caption"> <a href="#fig-41" class="anchor-link">Figure 12.41.</a> Distribution of INP performance by device. </figcaption> </figure> <p>55% of websites have “good” INP on mobile, 36% are rated “needs improvement”, and 8% have “poor” INP. The desktop story of INP is more similar to FID in that 95% of websites are rated “good”, 4% are rated “needs improvement”, and 1% are “poor”.</p> <p>The enormous disparity between desktop and mobile users’ INP experiences is much wider than with FID. This illustrates the extent to which mobile devices are struggling to keep up with the overwhelming amount of work websites do, and all signs point to the increasing reliance on <a hreflang="en" href="https://httparchive.org/reports/state-of-javascript?start=earliest&end=latest&view=grid#bytesJs">JavaScript</a> as a major factor.</p> <h4 id="inp-by-rank"><a href="#inp-by-rank" class="anchor-link">INP by rank</a></h4> <p>To see how unevenly distributed INP performance is across the web, it’s useful to segment websites by their popularity ranking.</p> <figure id="fig-42"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/inp-mobile-performance-by-rank.png" class=""> <img src="/static/images/2022/performance/inp-mobile-performance-by-rank.png" alt="Mobile INP performance by rank." aria-labelledby="fig-42-caption" aria-describedby="fig-42-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1034889047&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=805166525"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/inp-mobile-performance-by-rank.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-42-description" data-show-text="Show description of Figure 12.42" data-hide-text="Hide description of Figure 12.42">Show description of Figure 12.42</button> <div id="fig-42-description" class="hidden">Stacked bar chart showing INP performance on mobile devices segmented by rank. The top 1,000 sites have 27% of good INP experiences, 52% have needs improvement INP experiences, and 20% have poor INP experiences. For the top 10,000 sites it’s 25%, 50%, and 24% respectively, for the top 100,000 sites it’s 31%, 50%, and 18%, for the top 1,000,000 sites it’s 42%, 46%, and 12%, and finally for all sites it’s 55% of good, 27% of needs improvement, and 5% of poor experiences.</div> <figcaption id="fig-42-caption"> <a href="#fig-42" class="anchor-link">Figure 12.42.</a> Mobile INP performance by rank. </figcaption> </figure> <p>27% of the top 1k most popular websites have good mobile INP. As the site popularity decreases, the percent having good mobile INP does something funny; it worsens at bit at the top 10k rank to 25%, then it improves to 31% at the top 100k, 41% at the top million, and it ultimately lands at 55% for all websites. Except for the top 1k, it seems that INP performance is inversely proportional to site popularity.</p> <figure id="fig-43"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/js-bytes-rank.png" class=""> <img src="/static/images/2022/performance/js-bytes-rank.png" alt="Median amount of JavaScript loaded per page, by rank." aria-labelledby="fig-43-caption" aria-describedby="fig-43-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=1725756250&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1423103831"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/js_bytes_rank.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/js-bytes-rank.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-43-description" data-show-text="Show description of Figure 12.43" data-hide-text="Hide description of Figure 12.43">Show description of Figure 12.43</button> <div id="fig-43-description" class="hidden">Bar chart showing the median kilobytes of JavaScript per page, grouped by device and site rank. The median top 1 thousand mobile page loads 604 KB of JavaScript, 680 in the top 10 thousand, 610 in the top 100 thousand, 583 in the top million, and 462 overall. The values for desktop follow the same trend and are larger by tens of kilobytes.</div> <figcaption id="fig-43-caption"> <a href="#fig-43" class="anchor-link">Figure 12.43.</a> Median amount of JavaScript loaded per page, by rank. </figcaption> </figure> <p>When we look at the amount of JavaScript that the median mobile page loads for each of these ranks, it follows the same funny pattern! The median mobile page in the top 1k loads 604 KB of JavaScript, then it increases to 680 KB for the top 10k before dropping all the way down to 462 KB over all websites. These results don’t prove that loading—and using—more JavaScript necessarily causes poor INP, but it definitely suggests a correlation exists.</p> <h4 id="inp-as-a-hypothetical-cwv-metric"><a href="#inp-as-a-hypothetical-cwv-metric" class="anchor-link">INP as a hypothetical CWV metric</a></h4> <p>INP is not an official CWV metric, but <a href="https://x.com/anniesullie">Annie Sullivan</a>, who is the Tech Lead for the CWV program at Google, has <a href="https://x.com/anniesullie/status/1535208365374185474">commented</a> about its intended future, saying “<em>INP is still experimental! Not a Core Web Vital yet, but we hope it can replace FID.</em>”</p> <p>This raises an interesting question: hypothetically, if INP were to be a CWV metric today, how different would the pass rates be?</p> <figure id="fig-44"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/cwv-fid-inp-device.png" class=""> <img src="/static/images/2022/performance/cwv-fid-inp-device.png" alt="Comparison of the percent of websites having good CWV with FID and INP, by device." aria-labelledby="fig-44-caption" aria-describedby="fig-44-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=56387241&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=805166525"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/cwv-fid-inp-device.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-44-description" data-show-text="Show description of Figure 12.44" data-hide-text="Hide description of Figure 12.44">Show description of Figure 12.44</button> <div id="fig-44-description" class="hidden">Bar chart showing the percent of websites that would be assessed as having good CWV, with either FID or INP as the responsiveness metric. 44% of desktop websites have good CWV with FID, compared to 43% with INP. 40% of mobile websites have good CWV with FID, compared to 31% with INP.</div> <figcaption id="fig-44-caption"> <a href="#fig-44" class="anchor-link">Figure 12.44.</a> Comparison of the percent of websites having good CWV with FID and INP, by device. </figcaption> </figure> <p>For desktop experiences, the situation wouldn’t change much. 43% of websites would have good CWV with INP, compared to 44% with FID.</p> <p>However, the disparity is much more dramatic among websites’ mobile experiences, which would fall to 31% having good CWV with INP, from 40% with FID.</p> <figure id="fig-45"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/cwv-fid-inp-rank.png" class=""> <img src="/static/images/2022/performance/cwv-fid-inp-rank.png" alt="Comparison of the percent of mobile websites having good mobile CWV with FID and INP, by rank." aria-labelledby="fig-45-caption" aria-describedby="fig-45-description" width="600" height="371" data-width="600" data-height="371" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=2082509168&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=805166525"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/cwv-fid-inp-rank.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-45-description" data-show-text="Show description of Figure 12.45" data-hide-text="Hide description of Figure 12.45">Show description of Figure 12.45</button> <div id="fig-45-description" class="hidden">Bar char showing the percent of mobile websites assessed as having good CWV, with either FID or INP as the responsiveness metric. 52% of the 1 thousand most popular mobile websites would have good CWV with FID, compared to 20% with INP. 42% of the top 10 thousand with FID and 18% with INP. 38% of the top 100 thousand with FID and 20% with INP. 38% of the top million with FID and 25% with INP. 40% of all websites with FID and 31% with INP.</div> <figcaption id="fig-45-caption"> <a href="#fig-45" class="anchor-link">Figure 12.45.</a> Comparison of the percent of mobile websites having good mobile CWV with FID and INP, by rank. </figcaption> </figure> <p>The situation gets even starker when we look at mobile experiences by site rank. Rather than 52% of the top 1k websites having good CWV with FID, only 20% of them would have good CWV with INP, a decrease of 32 percentage points. So even though the most popular websites overperform with FID compared to all websites (52% versus 40%), they actually <em>underperform</em> with INP (20% versus 31%).</p> <p>The story is similar for the top 10k websites, which would decrease by 24 percentage points with INP as a CWV. Websites in this rank would have the lowest rate of good CWV with INP. As we saw in the previous section, this is also the rank with the highest usage of JavaScript. The rate of good CWV converges with FID and INP as the ranks become less popular, with the difference falling to 18, 13, and 9 percentage points respectively.</p> <p>These results show that the most popular websites have the most work to do to get their INP into shape.</p> <figure id="fig-46"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/cwv-inp-tech.png" class=""> <img src="/static/images/2022/performance/cwv-inp-tech.png" alt="Percent change of websites having good CWV from FID to INP, by technology." aria-labelledby="fig-46-caption" aria-describedby="fig-46-description" width="600" height="632" data-width="600" data-height="632" data-seamless="" data-frameborder="0" data-scrolling="no" data-iframe="https://docs.google.com/spreadsheets/d/e/2PACX-1vR-dJP3uphZoGE5A_luniNBFm5V2ww6irfOxANg0hrMid7gjgrtchsN_utOIDOvVZUjIwpmUBb27nHF/pubchart?oid=457714899&format=interactive" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/#gid=1104559069"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/web_vitals_by_technology.sql"> View query </a> </li> <li> <a href="/static/images/2022/performance/cwv-inp-tech.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-46-description" data-show-text="Show description of Figure 12.46" data-hide-text="Hide description of Figure 12.46">Show description of Figure 12.46</button> <div id="fig-46-description" class="hidden">Bar chart showing the percent of mobile websites that would start failing the CWV assessment switching from FID to INP, grouped by the CMS or JavaScript framework used. In decreasing order of the most popular technologies, the values are: WordPress 6%, React 11%, WooCommerce 3%, Shopify 6%, Vue.js 8%, RequireJS 10%, Wix 15%, Joomla 6%, Drupal 8%, 1C-Bitrix 39%, Squarespace 1%, AMP 10%, PrestaShop 7%, Emotion 10%, Angular 5%, Magento 6%, TYPO3 CMS 6%, Nuxt.js 9%, Duda 14%, Adobe Experience Manager 9%, Gatsby 14%, GoDaddy Website Builder 10%, and Pixnet 86%.</div> <figcaption id="fig-46-caption"> <a href="#fig-46" class="anchor-link">Figure 12.46.</a> Percent change of websites having good CWV from FID to INP, by technology. </figcaption> </figure> <p>In this chart we’re looking at the percent of a given technology’s websites that would no longer be considered as having “good” CWV should FID be replaced with INP.</p> <p>Two things jump out in this chart: 1C-Bitrix and Pixnet, which are CMSs and would have an enormous proportion of their websites ceasing to pass the CWV assessment with INP. Pixnet stands to lose 86% of its websites, down from 98% to 13%! The passing rate for 1C-Bitrix would fall from 79% to 40%, a difference of 39%.</p> <p>11% of websites using the React framework would no longer pass CWV. Wix, which is now <a href="./cms#most-popular-cmss">the second most popular CMS</a>, uses React. 15% of its websites would not have “good” CWV. Proportionally though, there would still be more Wix websites passing CWV than React websites overall, at 24% and 19% respectively, but INP would narrow that gap.</p> <p>WordPress is the most popular technology in the list and 6% of its 2.3 million websites would no longer have “good” CWV. Its passing rate would fall from 30% to 24%.</p> <p>Squarespace would have the least amount of movement due to this hypothetical change, only losing 1% of its websites’ “good” CWV. This suggests that Squarespace websites not only have a fast first interaction but also consistently fast interactions throughout the page experience. Indeed, the <a hreflang="en" href="https://datastudio.google.com/s/sM9D7EUjxU8">CWV Technology Report</a> shows Squarespace significantly outperforming other CMSs at INP, having over 80% of their websites passing the INP threshold.</p> <h4 id="inp-and-tbt"><a href="#inp-and-tbt" class="anchor-link">INP and TBT</a></h4> <p>What actually makes INP a better responsiveness metric than FID? One way to answer that question is to look at the correlation between field-based INP and FID performance and lab-based TBT performance. TBT is a direct measure of how unresponsive a page <em>can</em> be, but it can never be a CWV itself because it doesn’t actually measure the <a hreflang="en" href="https://web.dev/user-centric-performance-metrics/">user-perceived experience</a>.</p> <p>This section draws from Annie Sullivan’s <a hreflang="en" href="https://colab.sandbox.google.com/drive/12lJmAABgyVjaUbmWvrbzj9BkkTxw6ay2">research</a> using the May 2022 dataset.</p> <figure id="fig-47"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/tbt-fid.png" class=""> <img src="/static/images/2022/performance/tbt-fid.png" class="" alt="Scatterplot visualizing the correlation between FID and TBT. (Source)" aria-labelledby="fig-47-caption" aria-describedby="fig-47-description" width="600" height="371" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="/static/images/2022/performance/tbt-fid.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-47-description" data-show-text="Show description of Figure 12.47" data-hide-text="Hide description of Figure 12.47">Show description of Figure 12.47</button> <div id="fig-47-description" class="hidden">Scatterplot visualization showing the correlation of field-based FID and lab-based TBT per page. Most FID values are in the 0-50ms range with TBT values widely ranging from 0-10 seconds. There’s a small cluster of FID values around 250ms with a TBT of around 0ms.</div> <figcaption id="fig-47-caption"> <a href="#fig-47" class="anchor-link">Figure 12.47.</a> Scatterplot visualizing the correlation between FID and TBT. (<a hreflang="en" href="https://colab.sandbox.google.com/drive/12lJmAABgyVjaUbmWvrbzj9BkkTxw6ay2">Source</a>) </figcaption> </figure> <p>This chart shows the relationship between pages’ FID and TBT responsiveness. The solid horizontal line at 100 ms represents the threshold for “good” FID, and most pages fall comfortably under this threshold.</p> <p>The most notable attribute of this chart is the dense area in the bottom left corner, which appears to be smeared out across the TBT axis. The length of this smear represents pages having high TBT and low FID, which illustrates the low degree of correlation between FID and TBT.</p> <p>There’s also a patch of pages that have low TBT and a FID of about 250 ms. This area represents pages that have <a hreflang="en" href="https://developer.chrome.com/blog/300ms-tap-delay-gone-away">tap delay</a> issues due to missing a <code><meta name=viewport></code> tag. These are outliers that can be safely ignored for this analysis’s purposes.</p> <p>The <a href="https://wikipedia.org/wiki/Kendall_rank_correlation_coefficient">Kendall</a> and <a href="https://wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient">Spearman</a> coefficients of correlation for this distribution are 0.29 and 0.40, respectively.</p> <figure id="fig-48"> <div class="figure-wrapper"> <a href="/static/images/2022/performance/tbt-inp.png" class=""> <img src="/static/images/2022/performance/tbt-inp.png" class="" alt="Scatterplot visualizing the correlation between INP and TBT. (Source)" aria-labelledby="fig-48-caption" aria-describedby="fig-48-description" width="600" height="371" loading="lazy"> </a> <div class="figure-dropdown nav-dropdown"> <button type="button" class="nav-dropdown-btn js-enable hidden" disabled aria-expanded="false" title="Explore the results"> <span class="visually-hidden">Explore the results</span> <svg aria-hidden="true" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" /> </svg> </button> <ul class="figure-dropdown-list nav-dropdown-list floating-card hidden"> <li> <a href="/static/images/2022/performance/tbt-inp.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-48-description" data-show-text="Show description of Figure 12.48" data-hide-text="Hide description of Figure 12.48">Show description of Figure 12.48</button> <div id="fig-48-description" class="hidden">Scatterplot visualization showing the correlation of field-based INP and lab-based TBT per page. Most INP values are in the 0-750ms range with TBT values ranging from 0-5 seconds.</div> <figcaption id="fig-48-caption"> <a href="#fig-48" class="anchor-link">Figure 12.48.</a> Scatterplot visualizing the correlation between INP and TBT. (<a hreflang="en" href="https://colab.sandbox.google.com/drive/12lJmAABgyVjaUbmWvrbzj9BkkTxw6ay2">Source</a>) </figcaption> </figure> <p>This is the same chart, but with INP instead of FID. The solid horizontal line here represents the 200 ms threshold for “good” INP. Compared to FID, there are many more pages above this line and not assessed as “good”.</p> <p>Pages in this chart are more densely packed in the bottom left corner, which signifies the higher degree of correlation between FID and TBT. There’s still a smear, but it’s not as pronounced.</p> <p>The Kendall and Spearman coefficients of correlation for this distribution are 0.34 and 0.45, respectively.</p> <figure> <blockquote> First, is INP correlated with TBT? Is it more correlated with TBT than FID? Yes and yes! <p>But they are both correlated with TBT; is INP catching more problems with main thread blocking JavaScript? We can break down the percent of sites meeting the “good” threshold: yes it is!</p> </blockquote> <figcaption>—Annie Sullivan on <a href="https://x.com/anniesullie/status/1525161893450727425">Twitter</a></figcaption> </figure> <p>As Annie notes, both metrics are correlated with TBT, but she concludes that INP is more strongly correlated, making it a better responsiveness metric.</p> <h3 id="fid-conclusions"><a href="#fid-conclusions" class="anchor-link">FID conclusions</a></h3> <p>These results show that sites absolutely do have responsiveness issues, despite the rosy picture painted by FID. Regardless of whether INP becomes a CWV metric, your users will thank you if you start optimizing it now.</p> <p>Nearly one in ten mobile sites are leaving free performance on the table by failing to disable double-tap to zoom. This is something all sites should be doing; it’s only one line of HTML and it benefits both FID and INP. Run Lighthouse on your page and look for the <a hreflang="en" href="https://web.dev/viewport/">viewport</a> audit to be sure.</p> <p>By taking a hypothetical look at INP as a CWV, we can see just how much work there is to be done just to get back to FID-like levels. The most popular mobile websites would be especially affected by such a change as a consequence of their (over)use of JavaScript. Some CMSs and JavaScript frameworks would be hit harder than others, and it’ll take an ecosystem-wide effort to collectively rein in the amount of client-side work that they do.</p> <h2 id="conclusion"><a href="#conclusion" class="anchor-link">Conclusion</a></h2> <p>As the industry continues to learn more about CWV, we’re seeing steady improvement both in terms of implementation and across all top-level metric values themselves. The most visible performance optimization strides are at the platform level, like Android and bfcache improvements, given that their impact can be felt across many sites at once. But let’s look at the most elusive piece of the performance puzzle: individual site owners.</p> <p>Google’s decision to make CWV part of search ranking catapulted performance to the top of many companies’ roadmaps, especially in the <a href="./seo#core-web-vitals-cwv">SEO</a> industry. Individual site owners are certainly working hard to improve their performance and played a major role in the CWV improvements over the last year, even if those individual efforts are much harder to spot at this scale.</p> <p>That said, there’s still more work to be done. Our research shows opportunities to improve LCP resources’ prioritization and static discoverability. Many sites are still failing to disable double-tap to zoom to avoid artificial interactivity delays. New research into INP has uncovered responsiveness problems that were easy to overlook with FID. Regardless of whether INP becomes a CWV, we should always strive to deliver fast and responsive experiences, and the data shows that we can be doing better.</p> <p>At the end of the day, there will always be more work to do, which is why the most impactful thing we can do is to continue making web performance more approachable. In the years to come, let’s emphasize getting web performance knowledge the “last mile” to site owners.</p> </article> <div class="chapter-links"> <h2 id="explore-results"> <a href="#explore-results" class="anchor-link"> Explore the results </a> </h2> <a class="alt btn" hreflang="en" href="https://docs.google.com/spreadsheets/d/1TPA_4xRTBB2fQZaBPZHVFvD0ikrR-4sNkfJfUEpjibs/"> <svg width="18" height="18" role="img" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bar-chart-logo"></use> </svg> View results </a> <a class="alt btn" hreflang="en" href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2022/performance/"> <svg width="18" height="18" role="img" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sql-logo"></use> </svg> View queries </a> <a class="alt btn" hreflang="en" href="https://github.com/HTTPArchive/almanac.httparchive.org/issues/new?assignees=&labels=bug%2C+writing&title=Issue+with+the+2022+performance+chapter"> <svg width="19" height="18" role="img" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> Suggest edit </a> <a class="alt btn" hreflang="en" href="https://github.com/HTTPArchive/almanac.httparchive.org/issues/923/"> <svg width="18" height="18" role="img" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#globe-logo"></use> </svg> Help translate </a> </div> <section class="webmentions js-enable hidden"> <div id="reactions" class="no-reactions"> <h2> <a href="#reactions" class="anchor-link">Reactions</a> </h2> <div class="reactions" data-source="View source"> <div class="reaction-tabs" role="tablist" aria-label="reactions"> <button id="likes-tab" role="tab" aria-selected="true" aria-controls="likes-panel" tabindex="0" class="no-reactions"> <span id="likes-count">0</span> <span id="likes-label" data-singular="like" data-plural="likes" data-plural-alt="">likes</span> </button> <button id="reposts-tab" role="tab" aria-selected="false" aria-controls="reposts-panel" tabindex="-1" class="no-reactions"> <span id="reposts-count">0</span> <span id="reposts-label" data-singular="repost" data-plural="reposts" data-plural-alt="">reposts</span> </button> <button id="replies-tab" role="tab" aria-selected="false" aria-controls="replies-panel" tabindex="-1" class="no-reactions"> <span id="replies-count">0</span> <span id="replies-label" data-singular="reply" data-plural="replies" data-plural-alt="">replies</span> </button> <button id="mentions-tab" role="tab" aria-selected="false" aria-controls="mentions-panel" tabindex="-1" class="no-reactions"> <span id="mentions-count">0</span> <span id="mentions-label" data-singular="mention" data-plural="mentions" data-plural-alt="">mentions</span> </button> </div> <div id="likes-panel" role="tabpanel" tabindex="0" aria-labelledby="likes-tab"> </div> <div id="reposts-panel" role="tabpanel" tabindex="0" aria-labelledby="reposts-tab" hidden> </div> <div id="replies-panel" role="tabpanel" tabindex="0" aria-labelledby="replies-tab" hidden> </div> <div id="mentions-panel" role="tabpanel" tabindex="0" aria-labelledby="mentions-tab" hidden> </div> </div> </div> </section> <section class="authors"> <h2 id="authors"> <a href="#authors" class="anchor-link"> Authors </a> </h2> <ul> <li> <div aria-hidden="true"> <a href="/en/2022/contributors#mel-ada" tabindex="-1"> <img class="avatar" alt="Melissa Ada avatar" src="https://avatars.githubusercontent.com/u/5370850?v=4&s=200" height="200" width="200" loading="lazy"> </a> </div> <div class="info"> <a href="/en/2022/contributors#mel-ada"><span class="name">Melissa Ada</span></a> <div class="social"> <a class="twitter" href="https://x.com/mel_melificent" aria-labelledby="author-mel-ada-twitter"> <svg width="22" height="22" role="img"> <title id="author-mel-ada-twitter">@mel_melificent on Twitter/X</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> @mel_melificent </a> <a class="github" href="https://github.com/mel-ada" aria-labelledby="author-mel-ada-github"> <svg width="22" height="20"> <title id="author-mel-ada-github">mel-ada on GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> mel-ada </a> <a class="linkedin" href="https://www.linkedin.com/in/mel-ada/" aria-labelledby="author-mel-ada-linkedin"> <svg width="22" height="22"> <title id="author-mel-ada-linkedin">Melissa Ada on LinkedIn</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#linkedin-logo"></use> </svg> mel-ada </a> </div> <div class="bio"> Mel Ada is a software engineer on the Web Performance team at Etsy. Her current involvement in the community includes co-organizing the NY Web Performance Meetup and speaking about recent works. </div> </div> </li> <li> <div aria-hidden="true"> <a href="/en/2022/contributors#rviscomi" tabindex="-1"> <img class="avatar" alt="Rick Viscomi avatar" src="https://avatars.githubusercontent.com/u/1120896?v=4&s=200" height="200" width="200" loading="lazy"> </a> </div> <div class="info"> <a href="/en/2022/contributors#rviscomi"><span class="name">Rick Viscomi</span></a> <div class="social"> <a class="twitter" href="https://x.com/rick_viscomi" aria-labelledby="author-rviscomi-twitter"> <svg width="22" height="22" role="img"> <title id="author-rviscomi-twitter">@rick_viscomi on Twitter/X</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> @rick_viscomi </a> <a class="github" href="https://github.com/rviscomi" aria-labelledby="author-rviscomi-github"> <svg width="22" height="20"> <title id="author-rviscomi-github">rviscomi on GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> rviscomi </a> <a class="website" href="https://rviscomi.dev/" aria-labelledby="author-rviscomi-website"> <svg width="22" height="22"> <title id="author-rviscomi-website">Rick Viscomi website</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#globe-logo"></use> </svg> https://rviscomi.dev/ </a> </div> <div class="bio"> Rick Viscomi is a DevRel engineer at Google, focusing on web performance. He is the co-author of <a hreflang="en" href="https://usingwpt.com/">Using WebPageTest</a>, a book about web performance testing. He also co-maintains HTTP Archive and is the Editor-in-Chief of the Web Almanac. </div> </div> </li> </ul> </section> <section class="citation-box"> <h2 id="cite"> <a href="#cite" class="anchor-link">Citation</a> </h2> <details> <summary>BibTeX</summary> <pre id="bibtex-citation"> @inbook{WebAlmanac.2022.Performance, author = "Ada, Melissa and Viscomi, Rick and Pollard, Barry and Meenan, Patrick and Rasam, Prathamesh and Weyl, Estelle and Obasa, Kanmi and Karamalegos, Sia", title = "Performance", booktitle = "The 2022 Web Almanac", chapter = 12, publisher = "HTTP Archive", year = "2022", language = "English", url = "https://almanac.httparchive.org/en/2022/performance" }</pre> </details> </section> <div id="cta-container" class="invisible"> <a class="alt btn chapter-cta comment-cta webmentions-cta hidden" href="#reactions"> <svg width="22" height="22" role="img" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#comment-logo"></use> </svg> <span class="num-reactions"></span> <span class="reactions-label" data-singular="reaction" data-plural="reactions" data-plural-alt="">Reactions</span> </a> <button class="alt btn chapter-cta share-cta hidden"> <svg width="22" height="22" role="img" aria-hidden="true" class="apple-icon hidden"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#share-apple-logo"></use> </svg> <svg width="22" height="22" role="img" aria-hidden="true" class="android-icon"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#share-android-logo"></use> </svg> Share </button> </div> <nav aria-label="Previous and next chapter navigation" id="chapter-navigation"> <a id="previous-chapter" title="Previous Chapter (press 'p' or ',')" href="/en/2022/accessibility"> <span class="arrow" aria-hidden="true">⌃</span> <span class="chapter-no"> Chapter 11 </span> <span class="chapter-title"> Accessibility </span> </a> <a id="next-chapter" title="Next Chapter (press 'n' or '.')" href="/en/2022/privacy"> <span class="arrow" aria-hidden="true">⌃</span> <span class="chapter-no"> Chapter 13 </span> <span class="chapter-title"> Privacy </span> </a> </nav> </div> </main> </div> <footer id="footer" class="alt-bg"> <div class="container"> <div class="home-logo"> <a class="navigation-logo" href="/en/2022/"> <span class="wa">Web Almanac</span> <span class="line-group"> <span class="pre">By</span> <span class="ha">HTTP Archive</span> </span> </a> </div> <hr> <nav id="footer-nav-items" aria-label="Footer navigation" class="nav-items"> <ul> <li><a href="/en/2022/contributors">Contributors</a></li> <li><a href="/en/2022/methodology">Methodology</a></li> <li> <a class="nav-dropdown-btn js-hide" href="/en/search">Search</a> <div class="nav-dropdown footer search-nav js-enable hidden"> <button type="button" class="nav-dropdown-btn search-button" aria-expanded="false"> Search </button> <ul class="nav-dropdown-list align-right hidden footer-search"> <li class="nav-dropdown-list-part"> <form action="/en/search"> <label for="footer-search-box" class="visually-hidden">Search</label> <input id="footer-search-box" class="search-input" type="search" name="q" placeholder="Search" title="Search" aria-label="Search"> <button class="search-button" type="submit"> <svg width="13" height="13" role="img" aria-labelledby="footer-search-icon"> <title id="footer-search-icon">Search</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#search-logo"></use> </svg> </button> </form> </li> </ul> </div> </li> <li> <a class="nav-dropdown-btn js-hide" href="/en/2022/table-of-contents">Table of Contents</a> <div class="nav-dropdown footer table-of-contents js-enable hidden"> <button type="button" class="nav-dropdown-btn" aria-expanded="false" aria-label="Table of Contents" > Table of Contents </button> <ul class="nav-dropdown-list hidden footer-list"> <li class="nav-dropdown-list-part"> <a href="/en/2022/">Home</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents">Table of Contents</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-1">Part I. Page Content</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/css"> Chapter 1: CSS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/javascript"> Chapter 2: JavaScript </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/markup"> Chapter 3: Markup </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/structured-data"> Chapter 4: Structured Data </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/fonts"> Chapter 5: Fonts </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/media"> Chapter 6: Media </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/webassembly"> Chapter 7: WebAssembly </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/third-parties"> Chapter 8: Third Parties </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/interoperability"> Chapter 9: Interoperability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-2">Part II. User Experience</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/seo"> Chapter 10: SEO </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/accessibility"> Chapter 11: Accessibility </a> </li> <li class="nav-dropdown-list-chapter nav-dropdown-list-current"> <span> Chapter 12: Performance </span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/privacy"> Chapter 13: Privacy </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/security"> Chapter 14: Security </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/mobile-web"> Chapter 15: Mobile Web </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/capabilities"> Chapter 16: Capabilities </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/pwa"> Chapter 17: PWA </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-3">Part III. Content Publishing</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/cms"> Chapter 18: CMS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/jamstack"> Chapter 19: Jamstack </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/sustainability"> Chapter 20: Sustainability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#part-4">Part IV. Content Distribution</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/page-weight"> Chapter 21: Page Weight </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/cdn"> Chapter 22: CDN </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/http"> Chapter 23: HTTP </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#appendices">Appendices</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/methodology">Methodology</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2022/contributors">Contributors</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/search">Search</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2022/table-of-contents#ebook">Ebook</a> </li> <li class="nav-dropdown-list-chapter ebook"> <a href="https://cdn.httparchive.org/almanac/ebooks/web_almanac_2022_en.pdf" data-event="ebook-click" data-label="toc-menu">Ebook PDF (32MB)</a> </li> </ul> </div> </li> <li> <div class="nav-dropdown footer"> <button type="button" class="nav-dropdown-btn js-enable" disabled aria-expanded="false" aria-label="Year Switcher">2022</button> <ul class="nav-dropdown-list hidden footer-list"> <li> <a href="/en/2024/performance">2024</a> </li> <li> <a href="/en/2021/performance">2021</a> </li> <li> <a href="/en/2020/performance">2020</a> </li> <li> <a href="/en/2019/performance">2019</a> </li> </ul> </div> </li> <li> <div class="nav-dropdown footer"> <button type="button" class="nav-dropdown-btn js-enable" disabled aria-expanded="false" aria-label="Language Switcher" >English</button> <ul class="nav-dropdown-list hidden footer-list"> <li> <a lang="ja" href="/ja/2022/performance">日本語</a> </li> <li> <a class="help-translate" href="https://github.com/HTTPArchive/almanac.httparchive.org/wiki/Translators'-Guide"><em>Help translate</em></a> </li> </ul> </div> </li> </ul> </nav> <nav id="mobile-footer-nav-items" aria-label="Footer navigation" class="nav-items"> <ul> <li><a href="/en/2022/contributors">Contributors</a></li> <li><a href="/en/2022/methodology">Methodology</a></li> <li> <form class="search-nav" action="/en/search"> <label for="mobile-footer-search-box" class="visually-hidden">Search</label> <input id="mobile-footer-search-box" class="search-input" type="search" name="q" placeholder="Search" title="Search" aria-label="Search"> <button class="search-button" type="submit"> <svg width="13" height="13" role="img" aria-labelledby="mobile-footer-search-icon"> <title id="mobile-footer-search-icon">Search</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#search-logo"></use> </svg> </button> </form> </li> <li> <a class="js-hide" href="/en/2022/table-of-contents">Table of Contents</a> <div class="table-of-contents-switcher js-enable hidden"> <label for="table-of-contents-switcher-mobile-footer" class="visually-hidden"> Table of Contents Switcher </label> <select id="table-of-contents-switcher-mobile-footer" data-label="toc-menu-mobile"> <option value="/en/2022/">Home</option> <option value="/en/2022/table-of-contents">Table of Contents</option> <option value="/en/2022/css"> Chapter 1: CSS </option> <option value="/en/2022/javascript"> Chapter 2: JavaScript </option> <option value="/en/2022/markup"> Chapter 3: Markup </option> <option value="/en/2022/structured-data"> Chapter 4: Structured Data </option> <option value="/en/2022/fonts"> Chapter 5: Fonts </option> <option value="/en/2022/media"> Chapter 6: Media </option> <option value="/en/2022/webassembly"> Chapter 7: WebAssembly </option> <option value="/en/2022/third-parties"> Chapter 8: Third Parties </option> <option value="/en/2022/interoperability"> Chapter 9: Interoperability </option> <option value="/en/2022/seo"> Chapter 10: SEO </option> <option value="/en/2022/accessibility"> Chapter 11: Accessibility </option> <option disabled selected value="/en/2022/performance"> Chapter 12: Performance </option> <option value="/en/2022/privacy"> Chapter 13: Privacy </option> <option value="/en/2022/security"> Chapter 14: Security </option> <option value="/en/2022/mobile-web"> Chapter 15: Mobile Web </option> <option value="/en/2022/capabilities"> Chapter 16: Capabilities </option> <option value="/en/2022/pwa"> Chapter 17: PWA </option> <option value="/en/2022/cms"> Chapter 18: CMS </option> <option value="/en/2022/jamstack"> Chapter 19: Jamstack </option> <option value="/en/2022/sustainability"> Chapter 20: Sustainability </option> <option value="/en/2022/page-weight"> Chapter 21: Page Weight </option> <option value="/en/2022/cdn"> Chapter 22: CDN </option> <option value="/en/2022/http"> Chapter 23: HTTP </option> <option value="/en/2022/methodology"> Methodology </option> <option value="/en/2022/contributors"> Contributors </option> <option value="/en/search"> Search </option> <option value="https://cdn.httparchive.org/almanac/ebooks/web_almanac_2022_en.pdf" data-event="ebook-click"> Ebook PDF (32MB) </option> </select> </div> </li> <li> <div class="year-switcher js-show"> <label for="year-switcher-mobile-footer" class="visually-hidden">Year Switcher</label> <select id="year-switcher-mobile-footer"> <option value="/en/2024/performance"> 2024 </option> <option selected="selected" value="/en/2022/performance"> 2022 </option> <option value="/en/2021/performance"> 2021 </option> <option value="/en/2020/performance"> 2020 </option> <option value="/en/2019/performance"> 2019 </option> </select> </div> </li> <li> <div class="language-switcher js-show"> <label for="language-switcher-mobile-footer" class="visually-hidden">Language Switcher</label> <select id="language-switcher-mobile-footer"> <option selected="selected" lang="en" value="/en/2022/performance"> English </option> <option lang="ja" value="/ja/2022/performance"> 日本語 </option> <hr> <option value="https://github.com/HTTPArchive/almanac.httparchive.org/wiki/Translators'-Guide"> Help translate </option> </select> </div> </li> </ul> </nav> <div id="footer-mobile-social-media" class="mobile-ha-social-media"> <a class="ha-logo" href="https://httparchive.org/" aria-labelledby="httparchive-logo-footer-mobile"> <svg width="70" height="35" role="img"> <title id="httparchive-logo-footer-mobile">HTTP Archive home</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#ha-logo"></use> </svg> </a> <ul class="social-media"> <li> <a href="https://x.com/HTTPArchive" aria-labelledby="twitter-logo-footer-mobile"> <svg width="20" height="20" role="img"> <title id="twitter-logo-footer-mobile">Twitter</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> </a> </li> <li> <a href="https://bsky.app/profile/httparchive.org" aria-labelledby="bluesky-logo-footer-mobile"> <svg width="20" height="20" role="img"> <title id="bluesky-logo-footer-mobile">Bluesky</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bluesky-logo"></use> </svg> </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org" rel="me" aria-labelledby="github-logo-footer-mobile"> <svg width="22" height="20" role="img"> <title id="github-logo-footer-mobile">GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> </a> </li> </ul> </div> <hr> <p class="copyright"> <span>© Web Almanac. Licensed under <a hreflang="en" href="https://github.com/HTTPArchive/almanac.httparchive.org/blob/main/LICENSE">Apache 2.0</a>.</span> <br> <a class="accessibility-statement" href="/en/accessibility-statement">Accessibility Statement</a> <span class="footer-bullet">•</span> <a class="rss-feed" href="/en/rss.xml">RSS Feed</a> </p> <a class="ha-logo not-mobile" href="https://httparchive.org/" aria-labelledby="ha-logo-footer"> <svg width="70" height="35" role="img"> <title id="ha-logo-footer">HTTP Archive home</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#ha-logo"></use> </svg> </a> <ul class="social-media not-mobile"> <li> <a href="https://x.com/HTTPArchive" aria-labelledby="twitter-logo-footer"> <svg width="20" height="20" role="img"> <title id="twitter-logo-footer">Twitter</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> </a> </li> <li> <a href="https://bsky.app/profile/httparchive.org" aria-labelledby="bluesky-logo-footer"> <svg width="20" height="20" role="img"> <title id="bluesky-logo-footer">Bluesky</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bluesky-logo"></use> </svg> </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org" rel="me" aria-labelledby="github-logo-footer"> <svg width="22" height="20" role="img"> <title id="github-logo-footer">GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> </a> </li> </ul> </div> </footer> <script async src="/static/js/almanac.js?v=1830c897b7a91e8f3ba7a8c08e07540d" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"></script> <script defer src="/static/js/webmentions.js?v=dbb31a967a22e06b6c1bb62d7a9ff9a0" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-PQ5N2MZG5M" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"></script> <link rel="preconnect" href="https://www.google-analytics.com"> <script defer src="/static/js/web-vitals.js?v=f6f30f40e7d014a2d38f1362c5eb6244" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"></script> <script defer src="/static/js/send-web-vitals.js?v=b7224f484fe762e075d4838286ddb066" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"></script> <script type="speculationrules" nonce="txzdaqcqKvPGjYIKCvADlsUZbJAzR0n5"> { "prerender": [ { "source": "document", "where": { "and": [ {"href_matches": "/*"}, {"not": {"href_matches": "/static/*"}} ] }, "eagerness": "moderate" } ] } </script> </body> </html>