CINXE.COM

Performance | 2024 | 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 | 2024 | 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=222e067b0135e75f99da5f73590dcdce"> <link rel="stylesheet" href="/static/css/page.css?v=f237479c0631daba0de02c3f2222a640"> <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="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"> 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 2024 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint metrics and their diagnostics."> <meta property="og:title" content="Performance | 2024 | The Web Almanac by HTTP Archive"> <meta property="og:url" content="https://almanac.httparchive.org/en/2024/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 2024 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint metrics and their diagnostics."> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@HTTPArchive"> <meta name="twitter:title" content="Performance | 2024 | 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 2024 Web Almanac"> <meta name="twitter:description" content="Performance chapter of the 2024 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint 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/2024/performance" }, "headline": "Performance | 2024 | 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/2024/contributors#imeugenia" ,"https://x.com/jevgeniazi" ,"https://github.com/imeugenia" ,"https://www.linkedin.com/in/imeugenia/" ], "name": "Jevgenija Zigisova" },{ "@type": "Person", "sameAs": [ "https://almanac.httparchive.org/en/2024/contributors#ines-akrap" ,"https://x.com/InesAkrap" ,"https://github.com/ines-akrap" ], "name": "Ines Akrap" }] , "description": "Performance chapter of the 2024 Web Almanac covering Core Web Vitals, with deep dives into the Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint metrics and their diagnostics.", "datePublished": "2024-11-11T00:00:00.000Z", "dateModified": "2025-02-04T00: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": "2024", "item": "https://almanac.httparchive.org/en/2024" }] } </script> <meta name="citation_title" content="The 2024 Web Almanac: Performance"> <meta name="citation_author" content="Jevgenija Zigisova"> <meta name="citation_author" content="Ines Akrap"> <meta name="citation_publication_date" content="2024/11/11"> <meta name="citation_journal_title" content="The 2024 Web Almanac"> <meta name="citation_volume" content="6"> <meta name="citation_issue" content="9"> <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/2024/performance"> <link rel="canonical" href="https://almanac.httparchive.org/en/2024/performance"> <link rel="alternate" type="application/rss+xml" title="Web Almanac by HTTP Archive RSS (en)" href="/en/rss.xml"> </head> <body class="year-2024"> <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/2024/"> <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/2024/contributors">Contributors</a></li> <li><a href="/en/2024/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/2024/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/2024/">Home</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents">Table of Contents</a> </li> <li class="nav-dropdown-list-chapter foreword"> <a href="/en/2024/table-of-contents#foreword">Foreword</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-1">Part I. Page Content</a> </li> <li class="nav-dropdown-list-chapter"> <span class="nav-dropdown-list-todo">Chapter 1: JavaScript</span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/markup"> Chapter 2: Markup </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/structured-data"> Chapter 3: Structured Data </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/fonts"> Chapter 4: Fonts </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/media"> Chapter 5: Media </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/third-parties"> Chapter 6: Third Parties </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-2">Part II. User Experience</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/seo"> Chapter 7: SEO </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/accessibility"> Chapter 8: Accessibility </a> </li> <li class="nav-dropdown-list-chapter nav-dropdown-list-current"> <span> Chapter 9: Performance </span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/privacy"> Chapter 10: Privacy </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/security"> Chapter 11: Security </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-3">Part III. Content Publishing</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cms"> Chapter 12: CMS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/ecommerce"> Chapter 13: Ecommerce </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/jamstack"> Chapter 14: Jamstack </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/sustainability"> Chapter 15: Sustainability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-4">Part IV. Content Distribution</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/page-weight"> Chapter 16: Page Weight </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cdn"> Chapter 17: CDN </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/http"> Chapter 18: HTTP </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cookies"> Chapter 19: Cookies </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#appendices">Appendices</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/methodology">Methodology</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/contributors">Contributors</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/search">Search</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">2024</button> <ul class="nav-dropdown-list hidden header-list"> <li> <a href="/en/2022/performance">2022</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 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/2024/contributors">Contributors</a></li> <li><a href="/en/2024/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/2024/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/2024/">Home</option> <option value="/en/2024/table-of-contents">Table of Contents</option> <option value="/en/2024/table-of-contents#foreword">Foreword</option> <option disabled> Chapter 1: JavaScript </option> <option value="/en/2024/markup"> Chapter 2: Markup </option> <option value="/en/2024/structured-data"> Chapter 3: Structured Data </option> <option value="/en/2024/fonts"> Chapter 4: Fonts </option> <option value="/en/2024/media"> Chapter 5: Media </option> <option value="/en/2024/third-parties"> Chapter 6: Third Parties </option> <option value="/en/2024/seo"> Chapter 7: SEO </option> <option value="/en/2024/accessibility"> Chapter 8: Accessibility </option> <option disabled selected value="/en/2024/performance"> Chapter 9: Performance </option> <option value="/en/2024/privacy"> Chapter 10: Privacy </option> <option value="/en/2024/security"> Chapter 11: Security </option> <option value="/en/2024/cms"> Chapter 12: CMS </option> <option value="/en/2024/ecommerce"> Chapter 13: Ecommerce </option> <option value="/en/2024/jamstack"> Chapter 14: Jamstack </option> <option value="/en/2024/sustainability"> Chapter 15: Sustainability </option> <option value="/en/2024/page-weight"> Chapter 16: Page Weight </option> <option value="/en/2024/cdn"> Chapter 17: CDN </option> <option value="/en/2024/http"> Chapter 18: HTTP </option> <option value="/en/2024/cookies"> Chapter 19: Cookies </option> <option value="/en/2024/methodology"> Methodology </option> <option value="/en/2024/contributors"> Contributors </option> <option value="/en/search"> Search </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 selected="selected" value="/en/2024/performance"> 2024 </option> <option 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/2024/performance"> English </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="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"> // 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> <ul> <li> <a href="#notes-on-data-sources">Notes on data sources</a> </li> </ul> </li> <li> <a href="#core-web-vitals">Core Web Vitals</a> </li> <li> <a href="#loading-speed">Loading speed</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="#largest-contentful-paint-lcp">Largest Contentful Paint (LCP)</a> <ul> <li> <a href="#lcp-content-types">LCP content types</a> </li> <li> <a href="#lcp-sub-parts">LCP sub-parts</a> </li> <li> <a href="#lcp-static-discoverability">LCP static discoverability</a> </li> <li> <a href="#lcp-lazy-loading">LCP lazy-loading</a> </li> <li> <a href="#css-background-images">CSS background images</a> </li> <li> <a href="#dynamically-added-images">Dynamically added images</a> </li> <li> <a href="#lcp-prioritization">LCP prioritization</a> </li> <li> <a href="#lcp-size">LCP size</a> </li> </ul> </li> <li> <a href="#loading-speed-conclusions">Loading speed conclusions</a> </li> </ul> </li> <li> <a href="#interactivity">Interactivity</a> <ul> <li> <a href="#interaction-to-next-paint-inp">Interaction to Next Paint (INP)</a> <ul> <li> <a href="#inp-sub-parts">INP sub-parts</a> </li> </ul> </li> <li> <a href="#long-tasks">Long tasks</a> <ul> <li> <a href="#long-animation-frames">Long animation frames</a> </li> </ul> </li> <li> <a href="#total-blocking-time-tbt">Total Blocking Time (TBT)</a> </li> <li> <a href="#interactivity-conclusion">Interactivity conclusion</a> </li> </ul> </li> <li> <a href="#visual-stability">Visual stability</a> <ul> <li> <a href="#cumulative-layout-shift-cls">Cumulative Layout Shift (CLS)</a> </li> <li> <a href="#backforward-cache-bfcache">Back/forward cache (bfcache)</a> </li> <li> <a href="#cls-best-practices">CLS best practices</a> <ul> <li> <a href="#explicit-dimensions">Explicit dimensions</a> </li> <li> <a href="#fonts">Fonts</a> </li> <li> <a href="#animations">Animations</a> </li> </ul> </li> <li> <a href="#visual-stability-conclusion">Visual stability conclusion</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 9 </div> <h1 class="title title-lg"> Performance </h1> <div class="article-dates"> <div class="article-date"> Date published: <time id="published-date" datetime="2024-11-11T00:00:00.000Z">2024/11/11</time> </div> <div class="article-date"> Last updated: <time id="modified-date" datetime="2025-02-04T00:00:00.000Z">2025/02/04</time> </div> <script nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"> // 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 adding 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/2024/contributors#imeugenia">Jevgenija Zigisova</a> and <a class="author" href="/en/2024/contributors#ines-akrap">Ines Akrap</a> </div> <div class="byline reviewers">Reviewed by <a class="reviewer" href="/en/2024/contributors#rviscomi">Rick Viscomi</a> and <a class="reviewer" href="/en/2024/contributors#siakaramalegos">Sia Karamalegos</a> </div> <div class="byline analysts">Analyzed by <a class="analyst" href="/en/2024/contributors#kevinfarrugia">Kevin Farrugia</a> and <a class="analyst" href="/en/2024/contributors#guaca">Estela Franco</a> </div> <div class="byline editors">Edited by <a class="editor" href="/en/2024/contributors#Cherry">James Ross</a> </div> </div> <h2 id="introduction"><a href="#introduction" class="anchor-link">Introduction</a></h2> <p>No one ever complained about a fast website, but a slow-loading and sluggish website quickly frustrates users. Website speed and overall performance directly impact user experience and the success of a website. Moreover, if a website is slow, it becomes less accessible to users, which is against the fundamental goal of the web—to provide universal access to the universe of information.</p> <p>In recent years, <a href="https://web.dev/articles/vitals">Core Web Vitals</a> performance metrics have improved, showing positive trends across many performance metrics. However, some inconsistencies can be observed. For example, the gap between high-end and low-end devices is widening, especially in mobile web performance, as highlighted in Alex Russell&#8217;s research in <a hreflang="en" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">The Performance Inequality Gap</a>. Web performance is tied to what devices and networks people can afford. Fortunately, more developers are aware of these challenges and are actively working to improve performance.</p> <p>In the performance chapter, we focus on Core Web Vitals, as they are key <a href="https://web.dev/articles/user-centric-performance-metrics">user-centric metrics</a> for assessing web performance. However, we also analyze the web performance from a broader perspective: loading, interactivity, and visual stability, adding supportive metrics like First Contentful Paint. This allows us to explore other performance and user experience-related metrics to get a more comprehensive picture of how websites performed in 2024.</p> <p>What&#8217;s new this year?</p> <ul> <li><a href="https://web.dev/blog/inp-cwv-march-12">Interaction to Next Paint (INP) has officially replaced First Input Delay (FID)</a> as part of Core Web Vitals. INP helps to evaluate overall interactivity performance more accurately.</li> <li><a href="https://developer.chrome.com/docs/web-platform/long-animation-frames">Long Animation Frames (LoAF)</a> data is available for the first time, providing new insights into the reasons for poor INP.</li> <li>As of this year, the Performance chapter also includes an analysis of the data for secondary pages in addition to home pages. This allows us to compare the home page with the secondary page performance.</li> </ul> <h3 id="notes-on-data-sources"><a href="#notes-on-data-sources" class="anchor-link">Notes on data sources</a></h3> <p>The HTTP Archive contains only lab performance data. In other words, it is data from a single website load event. This is useful but limited if we want to understand how users experience performance.</p> <p>Thus, in addition to the HTTP Archive data, most of this report is based on real user data from the <a href="https://developer.chrome.com/docs/crux">Chrome User Experience Report (CrUX)</a>. Note that while Chrome is the most widely used browser worldwide, it doesn&#8217;t reflect performance across all browsers and all regions of the world.</p> <p>CrUX is a great source of data, but it doesn&#8217;t contain certain metrics like LCP and INP sub-parts, as well as Long Animation Frames. Luckily, the performance monitoring platform <a hreflang="en" href="https://www.rumvision.com/">RUMvision</a> has provided us with this data for the period from 1st January to 6th October 2024. Compared to The HTTP Archive, RUMvision tests a smaller amount of websites, which is why the results for the same metrics might be slightly different.</p> <h2 id="core-web-vitals"><a href="#core-web-vitals" class="anchor-link">Core Web Vitals</a></h2> <p>Core Web Vitals (CWV) are user-centric metrics designed to measure the different aspects of web performance. These include the <a href="https://web.dev/articles/lcp">Largest Contentful Paint (LCP)</a>, which tracks loading performance, <a href="https://web.dev/articles/inp">Interaction to Next Paint (INP)</a>, which measures interactivity, and <a href="https://web.dev/articles/cls">Cumulative Layout Shift (CLS)</a>, which assesses visual stability.</p> <p>Starting this year, INP has officially replaced <a href="https://web.dev/articles/fid">First Input Delay (FID)</a> and became a part of the CWV. While INP measures the full delay of all interactions experienced by a user, FID only focuses on the input delay of the first interaction. This wider scope makes INP a better reflection of the full user experience.</p> <figure id="fig-1"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-core-web-vitals-fid-devices-years.png" class=""> <img src="/static/images/2024/performance/good-core-web-vitals-fid-devices-years.png" alt="The percent of websites having good CWV using FID and INP, segmented by 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1908072353&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-core-web-vitals-fid-devices-years.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 9.1" data-hide-text="Hide description of Figure 9.1">Show description of Figure 9.1</button> <div id="fig-1-description" class="hidden">Bar chart showing the percentage of websites with good Core Web Vitals (CWV) on mobile, comparing CWV with FID (First Input Delay) and CWV with INP (Interaction to Next Paint) over time. In 2022, 39% of websites had good CWV with FID, while 31% had good CWV with INP. In 2023, the percentage increased to 43% for CWV with FID and 37% for CWV with INP. In 2024, 48% of websites had good CWV with FID, and 43% had good CWV with INP.</div> <figcaption id="fig-1-caption"> <a href="#fig-1" class="anchor-link">Figure 9.1.</a> The percent of websites having good CWV using FID and INP, segmented by year. </figcaption> </figure> <p>The replacement of the FID with the INP metric significantly impacted the percentage of websites with good CWV on mobile. This doesn&#8217;t mean the user experience has worsened, just that is now reflected more accurately due to the metric update. If we still used FID as a measure of interactivity, 48% of the websites would have good CWV on mobile devices. However, with the INP metric, this figure drops to 43%. Interestingly, performance on desktop devices stays the same regardless of which responsiveness metric we use at 54%.</p> <p>In the period from 2020 to 2022, we saw that mobile web performance measured by CWV with FID was improving faster than desktop one, and the gap between them was closing, reaching just 5% in 2022. As CWV with INP chart shows, in 2024, the websites on the desktop performed 11% better than on mobile, so the introduction of the INP shows that the gap is much bigger.</p> <figure id="fig-2"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-core-web-vitals-inp-devices-years.png" class=""> <img src="/static/images/2024/performance/good-core-web-vitals-inp-devices-years.png" alt="The percent of websites having good CWV, segmented by rank and desktop vs mobile." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1814767865&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=355582610"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-core-web-vitals-inp-devices-years.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 9.2" data-hide-text="Hide description of Figure 9.2">Show description of Figure 9.2</button> <div id="fig-2-description" class="hidden">Bar chart showing the percentage of websites with good CWV (Core Web Vitals) performance by rank for desktop and mobile. For the top 1,000 websites, 40% of mobile websites have good CWV, compared to 54% of desktop websites. In the top 10,000, 33% of mobile websites have good CWV, while 46% of desktop websites do. In the top 100,000, 31% of mobile websites and 43% of desktop websites have good CWV. In the top 1,000,000, 36% of mobile websites have good CWV, compared to 48% of desktop websites. For websites ranked 10,000,000 and beyond, 44% of mobile websites and 43% of desktop websites achieve good CWV.</div> <figcaption id="fig-2-caption"> <a href="#fig-2" class="anchor-link">Figure 9.2.</a> The percent of websites having good CWV, segmented by rank and desktop vs mobile. </figcaption> </figure> <p>CWV with INP shows a new tendency when analyzing websites by rank. Previously, the most popular websites <a href="../2022/performance#fig-2">tended to have the best CWV experience</a>, however, this year&#8217;s statistics show the opposite: 40% of 1000 most popular websites on mobile have good CWV which is lower than total website CWV of 43%.</p> <figure id="fig-3"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-core-web-vitals-fid-vs-inp.png" class=""> <img src="/static/images/2024/performance/good-core-web-vitals-fid-vs-inp.png" alt="Percent point change of websites having good CWV from FID to INP, by technology." aria-labelledby="fig-3-caption" aria-describedby="fig-3-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=655066315&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=869409419"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_technology.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-core-web-vitals-fid-vs-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-3-description" data-show-text="Show description of Figure 9.3" data-hide-text="Hide description of Figure 9.3">Show description of Figure 9.3</button> <div id="fig-3-description" class="hidden">Bar chart showing the percentage points of websites with new mobile CWV failures due to INP across various platforms and technologies. 1C-Bitrix has the highest percentage of new failures at 19%, followed by Next.js at 10%, and Emotion at 8%. Other platforms such as WordPress, React, Vue.js, and Drupal show smaller decreases, ranging from 2% to 5%. The chart also displays a range of smaller decreases for various technologies, including Handlebars, Backbone.js, Squarespace, and Angular, all seeing decreases of around 2% to 5%.</div> <figcaption id="fig-3-caption"> <a href="#fig-3" class="anchor-link">Figure 9.3.</a> Percent point change of websites having good CWV from FID to INP, by technology. </figcaption> </figure> <p>As mentioned earlier, the CWV scores have decreased due to the switch of the INP metric. We investigated how different technologies have been affected by this shift. The diagram above illustrates the percent point drop in the percentage of websites with good CWV across various technologies after the INP was introduced.</p> <p>Several technologies were significantly impacted, including a 19% drop for 1C-Bitrix (a popular CMS in Central Asia), a 10% drop for Next.js (a React-based framework), and an 8% drop for Emotion (a CSS-in-JS tool). We can&#8217;t be entirely certain that the decline in CWV scores is solely due to the technology used. Next.js has server-side rendering (SSR) and static site generation (SSG) features, which should theoretically enhance INP, but it has still seen a significant decline. As Next.js is based on React, many websites rely on client-side rendering, which can negatively impact INP. This could serve as a reminder for developers to leverage the SSR and SSG capabilities of the framework they use.</p> <p>As of this year, secondary pages are available to compare with home page data.</p> <figure id="fig-4"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-core-web-vitals-home-secondary-page.png" class=""> <img src="/static/images/2024/performance/good-core-web-vitals-home-secondary-page.png" alt="The percent of websites having good CWV, segmented by page type." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1034225442&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1159394005"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device_secondary_pages.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-core-web-vitals-home-secondary-page.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 9.4" data-hide-text="Hide description of Figure 9.4">Show description of Figure 9.4</button> <div id="fig-4-description" class="hidden">Bar chart showing the percentage of pages with good CWV (Core Web Vitals) for home pages and secondary pages on desktop and mobile. For home pages, 45% of desktop pages have good CWV, while 38% of mobile pages achieve good CWV. For secondary pages, 61% of desktop pages have good CWV, compared to 51% of mobile pages.</div> <figcaption id="fig-4-caption"> <a href="#fig-4" class="anchor-link">Figure 9.4.</a> The percent of websites having good CWV, segmented by page type. </figcaption> </figure> <p>Secondary pages demonstrate significantly better CWV results than home pages. The percentage of the desktop secondary pages with good CWV is by 14 percentage points better than for home pages. For mobile websites, the difference is 13 percentage points. By looking at CWV data only, it is hard to identify what kind of performance experience is better. We will explore these aspects—layout shift, loading, and interactivity—in the corresponding sections.</p> <h2 id="loading-speed"><a href="#loading-speed" class="anchor-link">Loading speed</a></h2> <p>People often refer to website loading speed as a single metric, but in fact, the loading experience is a multi-stage process. No single metric fully captures all aspects of what makes up loading speed. Every stage has an impact on the speed of a website.</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 href="https://web.dev/articles/ttfb">Time to First Byte</a> (TTFB) measures the time from when a user initiates loading a page until the browser receives the first byte of the response. It includes phases like redirect time, DNS lookup, connection and TLS negotiation, and request processing. Reducing latency in connection and server response time can improve TTFB. 800 milliseconds is considered the threshold for good TTFB—with <a href="https://web.dev/articles/ttfb#good-ttfb-score">some caveats!</a></p> <figure id="fig-5"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-time-to-first-byte.png" class=""> <img src="/static/images/2024/performance/good-time-to-first-byte.png" alt="The percent of websites having good TTFB, 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1925312055&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-time-to-first-byte.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 9.5" data-hide-text="Hide description of Figure 9.5">Show description of Figure 9.5</button> <div id="fig-5-description" class="hidden">Stacked bar chart showing TTFB (Time to First Byte) performance for mobile websites from 2020 to 2024, categorized as good, needs improvement, and poor. In 2024, 42% of mobile websites had good TTFB, 40% needed improvement, and 19% were poor. In 2023, 41% were good, 41% needed improvement, and 19% were poor. In 2022, 40% of websites had good TTFB, 41% needed improvement, and 19% were poor. In 2021, 39% were good, 42% needed improvement, and 18% were poor. In 2020, 41% of mobile websites had good TTFB, 41% needed improvement, and 18% were poor.</div> <figcaption id="fig-5-caption"> <a href="#fig-5" class="anchor-link">Figure 9.5.</a> The percent of websites having good TTFB, segmented by device and year. </figcaption> </figure> <p>Over the past five years, the percentage of mobile web pages with good TTFB has remained stable, from 41% in 2021 to 42% in 2024. The percentage of pages that need TTFB improvements has decreased by 1%, and unfortunately, the percentage of pages with poor TTFB remains the same. Since this metric has not changed significantly, we can conclude that there have been no major improvements in connection speed or backend latency.</p> <h3 id="first-contentful-paint-fcp"><a href="#first-contentful-paint-fcp" class="anchor-link">First Contentful Paint (FCP)</a></h3> <p><a href="https://web.dev/articles/fcp">First Contentful Paint (FCP)</a> is a performance metric that helps indicate how quickly users can start seeing content. It measures the time from when a user first requests a page until the first piece of content is rendered on the screen. A good FCP should be under 1.8 seconds.</p> <figure id="fig-6"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-first-contentful-paint-2024.png" class=""> <img src="/static/images/2024/performance/good-first-contentful-paint-2024.png" alt="The percent of websites having good FCP, 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1058680176&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-first-contentful-paint-2024.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 9.6" data-hide-text="Hide description of Figure 9.6">Show description of Figure 9.6</button> <div id="fig-6-description" class="hidden">Bar chart showing the percentage of websites with good FCP (First Contentful Paint) performance by device over time. In July 2021, 60% of desktop websites had good FCP, compared to 38% of mobile websites. By June 2022, 64% of desktop websites and 49% of mobile websites had good FCP. In September 2023, 63% of desktop websites had good FCP, while 47% of mobile websites did. By June 2024, the percentage increased to 68% for desktop websites and 51% for mobile websites.</div> <figcaption id="fig-6-caption"> <a href="#fig-6" class="anchor-link">Figure 9.6.</a> The percent of websites having good FCP, segmented by device and year. </figcaption> </figure> <p>FCP has shown improvements over the past few years. Although there was a slight decline in 2023, the metric recovered in 2024, reaching 68% for desktop and 51% for mobile websites. Overall, this reflects a positive trend in how fast the first content is loaded. Taking into account that the TTFB metric remained mostly unchanged, FCP improvements might be driven by client-side rendering rather than server-side optimizations.</p> <p>Interestingly, website performance is not the only factor that influences FCP. In the research <a hreflang="en" href="https://www.debugbear.com/blog/chrome-extension-performance-2021#impact-on-page-rendering-times">How Do Chrome Extensions Impact Browser Performance?</a> Matt Zeunert found that browser extensions can significantly affect page loading times. Many extensions start running their code as soon as a page starts loading, delaying the first contentful paint. For instance, some extensions can increase FCP from 100 milliseconds to 250 milliseconds.</p> <h3 id="largest-contentful-paint-lcp"><a href="#largest-contentful-paint-lcp" class="anchor-link">Largest Contentful Paint (LCP)</a></h3> <p><a href="https://web.dev/articles/lcp">Largest Contentful Paint (LCP)</a> is an important metric as it indicates how quickly the largest element in the viewport is loaded. A best practice is to ensure the LCP resource starts loading as early as possible. A good LCP should be under 2.5 seconds.</p> <figure id="fig-7"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-scores-2024.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-scores-2024.png" alt="The percent of websites having good, need improvements and poor LCP, segmented by device." aria-labelledby="fig-7-caption" aria-describedby="fig-7-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=2074458485&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-scores-2024.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 9.7" data-hide-text="Hide description of Figure 9.7">Show description of Figure 9.7</button> <div id="fig-7-description" class="hidden">Stacked bar chart showing LCP performance by device, categorized as good (under 2.5 seconds), needs improvement (2.5–4 seconds), and poor (over 4 seconds). For desktop, 72% of websites have good LCP, 20% need improvement, and 8% perform poorly. For phones, 59% of websites have good LCP, 27% need improvement, and 14% perform poorly.</div> <figcaption id="fig-7-caption"> <a href="#fig-7" class="anchor-link">Figure 9.7.</a> The percent of websites having good, need improvements and poor LCP, segmented by device. </figcaption> </figure> <p>LCP has also improved in recent years (from 44% of pages with good LCP in 2022 to 54% in 2024) following the overall positive tendency in CWV. In 2024, 59% of mobile pages achieved a good LCP score. However, there is still a significant gap compared to desktop sites, where 74% have good LCP. This firmly established trend is explained by differences in device processing power and network quality. However, it also highlights that many web pages are still not optimized for mobile use.</p> <figure id="fig-8"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-larges-contentful-paint-primary-secondary-pages.png" class=""> <img src="/static/images/2024/performance/good-larges-contentful-paint-primary-secondary-pages.png" alt="The percent of websites having good LCP, segmented by device and page type." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1404370023&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1159394005"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device_secondary_pages.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-larges-contentful-paint-primary-secondary-pages.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 9.8" data-hide-text="Hide description of Figure 9.8">Show description of Figure 9.8</button> <div id="fig-8-description" class="hidden">Bar chart showing the percentage of pages with good LCP for home pages and secondary pages on desktop and mobile. For home pages, 63% of desktop pages have good LCP, while 53% of mobile pages achieve the same. For secondary pages, 82% of desktop pages have good LCP, compared to 72% of mobile pages.</div> <figcaption id="fig-8-caption"> <a href="#fig-8" class="anchor-link">Figure 9.8.</a> The percent of websites having good LCP, segmented by device and page type. </figcaption> </figure> <p>The comparison between home pages and secondary pages reveals an interesting trend: 72% of all secondary pages have good LCP, which is 20% higher than the result for home pages. This is likely because users typically navigate on the home page first, causing the initial load to happen on the home page. After they navigate to secondary pages, many of the resources are already loaded and cached, speeding up the LCP element to render. Another possible reason is that the home page often contains more media-rich content such as video and images, compared to secondary pages.</p> <h4 id="lcp-content-types"><a href="#lcp-content-types" class="anchor-link">LCP content types</a></h4> <figure id="fig-9"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-top-content-types.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-top-content-types.png" alt="Top three LCP content types segmented by device." aria-labelledby="fig-9-caption" aria-describedby="fig-9-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1134330296&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1760287339"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_resource_type.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-top-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-9-description" data-show-text="Show description of Figure 9.9" data-hide-text="Hide description of Figure 9.9">Show description of Figure 9.9</button> <div id="fig-9-description" class="hidden">Bar chart showing the top LCP content types for desktop and mobile in 2024. For desktop, 83.3% of pages have images as the LCP content type, while 73.3% of mobile pages have images as their LCP content. Text accounts for 16.3% of LCP content on desktop and 26.3% on mobile. Inline images are rare, making up 0.3% of LCP content on desktop and 0.4% on mobile.</div> <figcaption id="fig-9-caption"> <a href="#fig-9" class="anchor-link">Figure 9.9.</a> Top three LCP content types segmented by device. </figcaption> </figure> <p>Most LCP elements, or 73% of mobile pages, are images. Interestingly, this percentage is 10% higher on desktop pages. The situation is reversed for text content. Compared to desktop, 10% more mobile webpages use text as their LCP element. This difference is likely because desktop websites can accommodate more visual content due to larger viewport sizes and generally higher performance.</p> <h4 id="lcp-sub-parts"><a href="#lcp-sub-parts" class="anchor-link">LCP sub-parts</a></h4> <p>Several stages of processing must occur before the LCP element can be fully rendered:</p> <ul> <li><strong>Time to First Byte</strong> (TTFB), which is the time it takes the server to begin responding to the initial request.</li> <li><strong>Resource Load Delay</strong>, which is how long after TTFB the browser begins loading the LCP resource. The LCP elements that originate as inline resources, such as text-based elements or inline images (data URIs), will have a 0 millisecond load delay. Those that require another asset to be downloaded, like an external image, might experience a load delay.</li> <li><strong>Resource Load Duration</strong> which measures how long it takes to load the LCP resource; this stage is also 0 millisecond if no resource is needed.</li> <li><strong>Element Render Delay</strong> which is the time between when the resource finished loading and the LCP element finished rendering.</li> </ul> <p>In the article <a href="https://web.dev/blog/common-misconceptions-lcp#lcp_sub-part_breakdown">Common Misconceptions About How to Optimize LCP</a>, Brendan Kenny analyzed a breakdown of LCP sub-parts using recent CrUX data.</p> <figure id="fig-10"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/median-subpart-p75s.png" class=""> <img src="/static/images/2024/performance/median-subpart-p75s.png" class="" alt="Time spent in each LCP subpart, grouped into LCP buckets of good, needs improvement, and poor." aria-labelledby="fig-10-caption" aria-describedby="fig-10-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/2024/performance/median-subpart-p75s.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-10-description" data-show-text="Show description of Figure 9.10" data-hide-text="Hide description of Figure 9.10">Show description of Figure 9.10</button> <div id="fig-10-description" class="hidden">Bar chart showing the medians of origin p75 LCP sub-parts for good, needs improvement, and poor p75 LCP in July 2024, across mobile and desktop. For good p75 LCP, TTFB is 600 milliseconds, image load delay is 350 milliseconds, image load duration is 160 milliseconds, and render delay is 230 milliseconds. For needs improvement p75 LCP, TTFB is 1360 milliseconds, image load delay is 720 milliseconds, image load duration is 270 milliseconds, and render delay is 310 milliseconds. For poor p75 LCP, TTFB is 2270 milliseconds, image load delay is 1290 milliseconds, image load duration is 350 milliseconds, and render delay is 360 milliseconds.</div> <figcaption id="fig-10-caption"> <a href="#fig-10" class="anchor-link">Figure 9.10.</a> Time spent in each LCP subpart, grouped into LCP buckets of good, needs improvement, and poor. </figcaption> </figure> <p>The study showed that image load duration has the least impact on LCP time, taking only 350 milliseconds at the 75th percentile for websites with poor LCP. Although resource load duration optimization techniques like image size reduction are often recommended, they don&#8217;t offer as much time savings as other LCP sub-parts, even for sites with poor LCP.</p> <p>TTFB is the largest part among all LCP sub-parts due to the network requests for external resources. Websites with poor LCP spend 2.27 seconds on TTFB alone, which is almost as long as the threshold for a good LCP (2.5 seconds). As we saw in the TTFB section, there hasn&#8217;t been much improvement in the percentage of websites with good TTFB, indicating that this metric offers significant opportunities for LCP optimization.</p> <p>Surprisingly, websites spend more time on resource load delay than on load duration, regardless of their LCP status. This makes load delay a good candidate for optimization efforts. One way to improve load delay is by ensuring that the LCP element starts loading as early as possible, which will be explored in detail in the section on LCP static discoverability.</p> <p>This year, we analyzed LCP sub-part data from another real user monitoring source: RUMvision. Although RUMvision has a different population of websites, it&#8217;s interesting to compare it with the larger CrUX website population. We assume that websites using performance monitoring tools like RUMvision should have more insights into performance optimization opportunities than the average website represented in CrUX. Naturally, the LCP sub-part results from two different datasets show some differences.</p> <figure id="fig-11"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-subparts.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-subparts.png" alt="Time spent in each LCP subpart by percentile." aria-labelledby="fig-11-caption" aria-describedby="fig-11-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=249678580&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1987931132"> View data </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-subparts.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-11-description" data-show-text="Show description of Figure 9.11" data-hide-text="Hide description of Figure 9.11">Show description of Figure 9.11</button> <div id="fig-11-description" class="hidden">Bar chart showing the distribution of LCP subparts in milliseconds (ms) across different percentiles. At the 10th percentile, all subparts have minimal values. At the 25th percentile, resource TTFB and load delay remain under 100 milliseconds. At the 50th percentile, resource TTFB increases to around 200 milliseconds, with small increases in load delay, load duration, and render delay. At the 75th percentile, resource TTFB exceeds 500 milliseconds, and render delay also shows an increase. At the 90th percentile, resource TTFB is over 1500 milliseconds, and render delay rises to over 600 milliseconds, with load delay and load duration also increasing.</div> <figcaption id="fig-11-caption"> <a href="#fig-11" class="anchor-link">Figure 9.11.</a> Time spent in each LCP subpart by percentile. </figcaption> </figure> <p>According to RUMvision data, TTFB is also the largest contributor to the LCP time in comparison to the other LCP sub-parts. However, the results of other sub-parts vary. Render delay is the second largest contributor to LCP, taking 184 milliseconds. At the 75th percentile, render delay grows to 443 milliseconds. This reflects a tendency that is different from the CrUX dataset, where LCP load delay is the second largest sub-part.</p> <p>Typically, LCP element rendering takes a long time if the LCP element hasn&#8217;t been added to the DOM yet—a common issue with client-side generated content that we explore in the next section. Also, the main thread blocked by long tasks can contribute to the delay. In addition, render-blocking resources like stylesheets or synchronous scripts in the <code>&lt;head&gt;</code> can delay rendering.</p> <p>It&#8217;s interesting to observe the different LCP challenges that websites across various datasets face. While an average website from the CrUX dataset struggles with image load delay, websites from the RUMvision dataset often face rendering delay issues. Nevertheless, all websites can benefit from using performance monitoring tools with Real User Monitoring (RUM), as these tools provide deeper insights into the performance issues experienced by real users.</p> <h4 id="lcp-static-discoverability"><a href="#lcp-static-discoverability" class="anchor-link">LCP static discoverability</a></h4> <p>One of the most effective ways to optimize the LCP resource load delay is to ensure the resource can be discovered as early as possible. If you make the resource discoverable in the initial HTML document, it enables the LCP resource to begin downloading sooner.</p> <figure id="fig-12"> <div class="figure-wrapper"> <div class="big-number">35%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=200850285"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_preload_discoverable.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-12-caption"> <a href="#fig-12" class="anchor-link">Figure 9.12.</a> The percent of mobile pages on which the LCP element was not statically discoverable. </figcaption> </figure> <p>Unfortunately, 35% of mobile websites do not have an LCP element that is statically discoverable in the document. While this is a slight improvement over the 39% we saw in 2022, it&#8217;s still a significant blocker of LCP performance.</p> <p>As we&#8217;ll explore in the following sections, there are three primary ways that websites prevent their LCP resources from being statically discoverable: lazy loading, CSS background images, and client-side rendering.</p> <h4 id="lcp-lazy-loading"><a href="#lcp-lazy-loading" class="anchor-link">LCP lazy-loading</a></h4> <p>A major obstacle to LCP resource discoverability is lazy-loading of the LCP resource. Overall, lazy-loading images is a helpful performance technique that should be used to postpone loading of non-critical resources until they are near the viewport. However, using lazy-loading on the LCP image will delay the browser from loading it quickly. That is why lazy-loading should not be used on LCP elements.</p> <figure id="fig-13"> <div class="figure-wrapper"> <div class="big-number">16%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1048885241"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_lazy.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-13-caption"> <a href="#fig-13" class="anchor-link">Figure 9.13.</a> The percent of mobile pages having image-based LCP that use native or custom lazy-loading on it. </figcaption> </figure> <p>The good news is that in 2024, fewer websites are using this performance anti-pattern. In 2022, 18% of mobile websites were lazy-loading their LCP images. By 2024, this decreased to 16%.</p> <p>In terms of the specific lazy-loading technique used, 9.5% of mobile websites natively lazy-load their LCP images with the <code>loading=lazy</code> attribute. This is very similar to the 9.8% of sites we saw in 2022. However, the biggest improvement came from custom approaches. This year we see 6.7% of mobile websites using a custom approach, for example hiding the LCP image source behind the <code>data-src</code> attribute, which is down from 8.8% in 2022.</p> <p>Note that the <code>src</code> attribute of an LCP image wth <code>loading=lazy</code> is technically set and therefore discoverable in the static HTML, so we don&#8217;t count it towards the static discoverability figure in the previous section. However, natively lazy-loaded images absolutely do contribute to resource load delays, albeit in a slightly different way than an image whose source is set by CSS or JavaScript, as we&#8217;ll explore next.</p> <h4 id="css-background-images"><a href="#css-background-images" class="anchor-link">CSS background images</a></h4> <figure id="fig-14"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-non-discoverable.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-non-discoverable.png" alt="The percent of pages whose LCP is not statically discoverable and initiated from a given resource." aria-labelledby="fig-14-caption" aria-describedby="fig-14-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=427707611&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1131647963"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_initiator_type.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-non-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-14-description" data-show-text="Show description of Figure 9.14" data-hide-text="Hide description of Figure 9.14">Show description of Figure 9.14</button> <div id="fig-14-description" class="hidden">Bar chart showing the initiators of undiscoverable LCP (Largest Contentful Paint) for desktop and mobile, categorized by resource type. For desktop, 38% of pages have HTML as the initiator of undiscoverable LCP, while for mobile, this figure is 33%. CSS is responsible for 11% of undiscoverable LCP on desktop pages and 9% on mobile. An unknown resource type accounts for 5% of undiscoverable LCP on desktop and 4% on mobile.</div> <figcaption id="fig-14-caption"> <a href="#fig-14" class="anchor-link">Figure 9.14.</a> The percent of pages whose LCP is not statically discoverable and initiated from a given resource. </figcaption> </figure> <p>Also, websites that initiate LCP elements as CSS background images delay LCP static discovery until the CSS file is processed. The data shows that 9% of mobile pages initialize the LCP resource from CSS. Compared to 2022, this metric has remained unchanged.</p> <h4 id="dynamically-added-images"><a href="#dynamically-added-images" class="anchor-link">Dynamically added images</a></h4> <p>One more common reason for non-discoverable LCP elements is dynamically added images. These images are added to the page through JavaScript after the initial HTML is loaded, making them undiscoverable during the HTML document scan.</p> <p>The chart below illustrates the distribution of client-side generated content. It compares the initial HTML with the final HTML (after JavaScript runs) and measures the difference. It displays how the percentage of websites with good LCP changes as the percentage of client-side generated content increases.</p> <figure id="fig-15"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-largest-contentful-paint-client-side-generated-content.png" class=""> <img src="/static/images/2024/performance/good-largest-contentful-paint-client-side-generated-content.png" alt="The percent of websites with good LCP vs percentage of client-side generated content on a page." aria-labelledby="fig-15-caption" aria-describedby="fig-15-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=750231640&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=829333856"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/inp_long_tasks.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-largest-contentful-paint-client-side-generated-content.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-15-description" data-show-text="Show description of Figure 9.15" data-hide-text="Hide description of Figure 9.15">Show description of Figure 9.15</button> <div id="fig-15-description" class="hidden">Line chart showing the percentage of origins with good LCP compared to the percentage of client-side generated HTML for both desktop and mobile. For desktop, the percentage of origins with good LCP starts around 75% for pages with 0-10% client-side generated HTML and remains relatively stable, peaking slightly around 40-50% client-side HTML usage, before gradually declining to about 65% at the 90-100% range. For mobile, the percentage of good LCP starts lower, around 60% for the 0-10% range, and follows a similar trend, peaking slightly in the 30-40% range before declining more sharply to about 45% at the 90-100% client-side HTML usage.</div> <figcaption id="fig-15-caption"> <a href="#fig-15" class="anchor-link">Figure 9.15.</a> The percent of websites with good LCP vs percentage of client-side generated content on a page. </figcaption> </figure> <p>The percentage of pages with good LCP stays at approximately 60% for mobile devices until the amount of client-side generated content reaches 70%. After this threshold, the percentage of websites with good LCP starts to drop at a faster rate until ending at 40%. This suggests that a combination of server- and client-side generated content doesn&#8217;t significantly impact how fast the LCP element gets rendered. However, fully rendering a website on the client side has a significantly negative impact on LCP.</p> <h4 id="lcp-prioritization"><a href="#lcp-prioritization" class="anchor-link">LCP prioritization</a></h4> <p>Another one of the most effective ways to optimize the loading delay of LCP images is to declaratively prioritize them, using the <code>fetchpriority=high</code> attribute. Even if the LCP resource is statically discoverable by the browser&#8217;s preload scanner, it might still not start loading immediately if there are other higher priority resources in line. Images are typically not considered high priority resources, so by providing this hint to the browser, it can adjust the LCP resource&#8217;s priority accordingly, loading it sooner and reducing its load delay phase.</p> <figure id="fig-16"> <div class="figure-wrapper"> <div class="big-number">15%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=731441901"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_async_fetchpriority.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-16-caption"> <a href="#fig-16" class="anchor-link">Figure 9.16.</a> The percent of mobile pages that use <code>fetchpriority=high</code> on their LCP image. </figcaption> </figure> <p>Adoption of LCP image prioritization skyrocketed to 15% of mobile websites in 2024, up from just 0.03% in 2022! This massive leap is thanks in large part to WordPress implementing <a hreflang="en" href="https://make.wordpress.org/core/2023/07/13/image-performance-enhancements-in-wordpress-6-3/">core support</a> for <code>fetchpriority</code> in 2023.</p> <p>As amazing as it is to see such rapid growth, there is still significant room for more sites to take advantage of this impactful one-line optimization.</p> <h4 id="lcp-size"><a href="#lcp-size" class="anchor-link">LCP size</a></h4> <p>The CrUX and RUMvision data on <a href="#lcp-sub-parts">LCP sub-parts</a> showed that resource load duration is rarely the main bottleneck for a slow LCP. However, it is still valuable to analyze the key optimization factors, such as the size and format of the LCP resource.</p> <figure id="fig-17"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-image-sizes.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-image-sizes.png" alt="Distribution of LCP image sizes, segmented by device type." aria-labelledby="fig-17-caption" aria-describedby="fig-17-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=164375992&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1329122831"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_bytes_histogram.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-image-sizes.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-17-description" data-show-text="Show description of Figure 9.17" data-hide-text="Hide description of Figure 9.17">Show description of Figure 9.17</button> <div id="fig-17-description" class="hidden">Histogram showing the distribution of LCP image sizes for desktop and mobile pages, measured in kilobytes (KB). For mobile, 48% of pages have LCP image sizes between 100 and 200 KB, while 18% of desktop pages fall into this range. For desktop, 30% of pages have LCP images between 0 and 100 KB, compared to 1% for mobile. In the 200 to 300 KB range, 9% of desktop pages and 5% of mobile pages have LCP images. The percentages gradually decrease as image size increases, with only a small portion of pages having LCP images larger than 700 KB. At the highest range, 8% of both desktop and mobile pages have LCP images over 1000 KB.</div> <figcaption id="fig-17-caption"> <a href="#fig-17" class="anchor-link">Figure 9.17.</a> Distribution of LCP image sizes, segmented by device type. </figcaption> </figure> <p>In 2024, 48% of mobile websites used an LCP image that was 100KB or less. Though, for 8% of the mobile pages the LCP element size is more than 1000KB.</p> <p>This aligns with the <a hreflang="en" href="https://github.com/GoogleChrome/lighthouse/blob/main/core/audits/byte-efficiency/uses-optimized-images.js">Lighthouse audit on unoptimized images</a>, which also reports the amount of wasted kilobytes that could be saved by image optimization.</p> <figure id="fig-18"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-images-wasted-kb.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-images-wasted-kb.png" alt="Distribution of wasted kilobytes on LCP image." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=321466279&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1984265626"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_wasted_bytes.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-images-wasted-kb.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 9.18" data-hide-text="Hide description of Figure 9.18">Show description of Figure 9.18</button> <div id="fig-18-description" class="hidden">Bar chart showing the distribution of wasted kilobytes on LCP images for desktop and mobile across percentiles. At the 10th, 25th, and 50th percentiles, both desktop and mobile pages have 0 wasted kilobytes. At the 75th percentile, desktop pages waste 20 kilobytes, while mobile pages waste 10 kilobytes. At the 90th percentile, desktop pages waste 190 kilobytes, and mobile pages waste 128 kilobytes.</div> <figcaption id="fig-18-caption"> <a href="#fig-18" class="anchor-link">Figure 9.18.</a> Distribution of wasted kilobytes on LCP image. </figcaption> </figure> <p>The audit results indicate that the median website wastes 0 KB on LCP images, i.e. serves optimized images. This leads to the conclusion that many sites are optimizing their LCP resources effectively, although some still need to improve.</p> <p>You can reduce image sizes through resizing dimensions and increasing compression. Another way to reduce image sizes is by using new image formats like WebP and AVIF, which have better compression algorithms.</p> <figure id="fig-19"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/largest-contentful-paint-image-file-format.png" class=""> <img src="/static/images/2024/performance/largest-contentful-paint-image-file-format.png" alt="The percent of pages that use a given image file format for their LCP images." aria-labelledby="fig-19-caption" aria-describedby="fig-19-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=2086275423&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=240287365"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/lcp_format.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/largest-contentful-paint-image-file-format.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-19-description" data-show-text="Show description of Figure 9.19" data-hide-text="Hide description of Figure 9.19">Show description of Figure 9.19</button> <div id="fig-19-description" class="hidden">Bar chart showing the distribution of LCP (Largest Contentful Paint) image formats for desktop and mobile. JPG is the most common format, used by 61% of desktop pages and a similar percentage of mobile pages. PNG is the second most common format, used by 26% of pages. WebP follows with 7%, while other formats such as MP4, SVG, GIF, and AVIF are used by less than 2% of pages. ICO, HEIC, and HEIF formats are barely used, with their percentages rounding to 0% for both desktop and mobile.</div> <figcaption id="fig-19-caption"> <a href="#fig-19" class="anchor-link">Figure 9.19.</a> The percent of pages that use a given image file format for their LCP images. </figcaption> </figure> <p>JPG and PNG still have the highest proportion of adoption at 87% combined, however WebP and AVIF formats are both increasing in adoption. In comparison to 2022, WebP image format usage increased from <a href="../2022/performance#lcp-format">4%</a> to 7%. Also, AVIF usage increased slightly from 0.1% to 0.3%. According to <a hreflang="en" href="https://webstatus.dev/?q=avif">Baseline</a>, AVIF format is newly available across major browsers, so we expect to see higher adoption in the future.</p> <h3 id="loading-speed-conclusions"><a href="#loading-speed-conclusions" class="anchor-link">Loading speed conclusions</a></h3> <ul> <li>The percentage of websites with good FCP and LCP has improved, though TTFB showed no significant change.</li> <li>One cause for slow LCP is lazy-loading the LCP element. Usage of this antipattern has decreased, but 15% of websites still fail this test and could benefit from removing lazy-loading for their LCP elements.</li> <li>The adoption of modern image formats like AVIF and WebP is growing for LCP elements.</li> </ul> <h2 id="interactivity"><a href="#interactivity" class="anchor-link">Interactivity</a></h2> <p>Interactivity on a website refers to the degree to which users can engage with and respond to content, features, or elements on the page. Measuring interactivity involves assessing the performance for a range of user interactions, such as clicks, taps, and scrolls, as well as more complex actions like form submissions, video plays, or drag-and-drop functions.</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 href="https://web.dev/articles/inp">Interaction to Next Paint (INP)</a> is calculated by observing all the interactions made with a page during the session and reporting the worse latency (for most sites). An interaction&#8217;s latency consists of the single longest duration of a group of event handlers that drive the interaction, from the time the user begins the interaction to the moment the browser is next able to paint a frame.</p> <p>For an origin to receive a &#8220;good&#8221; INP score, at least 75% of all sessions need an INP score of 200 milliseconds or less. The INP score is the slowest or near-slowest interaction time for all interactions on the page. See <a href="https://web.dev/articles/inp#good-score">Details on how INP is calculated</a> for more information.</p> <figure id="fig-20"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/interaction-to-next-paint-2024.png" class=""> <img src="/static/images/2024/performance/interaction-to-next-paint-2024.png" alt="Distribution of INP performance by device." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=667078190&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/interaction-to-next-paint-2024.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 9.20" data-hide-text="Hide description of Figure 9.20">Show description of Figure 9.20</button> <div id="fig-20-description" class="hidden">Stacked bar chart showing INP performance by device, with desktop and phone categorized into good (under 200 milliseconds), needs improvement (200–500 milliseconds), and poor (over 500 milliseconds). For desktop, 97% of websites have good INP, 2% need improvement, and less than 1% perform poorly. For phones, 74% of websites have good INP, 24% need improvement, and 2% perform poorly.</div> <figcaption id="fig-20-caption"> <a href="#fig-20" class="anchor-link">Figure 9.20.</a> Distribution of INP performance by device. </figcaption> </figure> <p>In 2024, 74% of mobile and 97% of desktop websites had good INP. Interestingly, the gap between mobile and desktop is huge, i.e. more than 20%.</p> <p>The primary reason for weaker performance on mobile is its lower processing power and frequently poor network connections. Alex Russell&#8217;s article &#8220;<a hreflang="en" href="https://infrequently.org/2022/12/performance-baseline-2023/">The Performance Inequality Gap</a>&#8221; (2023) raises the issue of the growing performance inequality gap caused by the affordance of high-end vs low-end devices. As the prices of high-end devices rise, fewer users can afford them, widening the inequality gap.</p> <figure id="fig-21"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-interaction-to-next-paint.png" class=""> <img src="/static/images/2024/performance/good-interaction-to-next-paint.png" alt="Good INP score by device." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=416359271&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-interaction-to-next-paint.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 9.21" data-hide-text="Hide description of Figure 9.21">Show description of Figure 9.21</button> <div id="fig-21-description" class="hidden">Bar chart showing the percentage of websites with good INP performance by device (desktop and mobile) across three years. In 2022, 95% of desktop websites had good INP, while 55% of mobile websites achieved good INP. In 2023, the percentage of websites with good INP improved to 97% for desktop and 64% for mobile. By 2024, 97% of desktop websites maintained good INP performance, while mobile improved further to 74%.</div> <figcaption id="fig-21-caption"> <a href="#fig-21" class="anchor-link">Figure 9.21.</a> Good INP score by device. </figcaption> </figure> <p>Although the INP metric displays worse results than the FID, there has been a positive tendency over the past three years. The percentage of mobile pages having good INP increased from 55% in 2022 to 74% in 2024. This is a significant increase, and even though we can&#8217;t be exactly sure what to attribute it to, we can think of a few potential drivers for this change.</p> <p>The first one could be awareness. With the introduction of the INP and the announcement that it will replace FID, many teams realized the impact that could have on their overall CWV score and search ranking. That could have encouraged them to actively work towards fixing parts of the sites that contributed to low INP scores. The second driver could be just a regular advancement in technology. With the above-displayed INP data coming from real users, we can also assume that users&#8217; devices and network connections could have slightly improved over the years, providing them with better site interactivity. The third (and perhaps biggest?) driver is improvements to browsers themselves (and in particular to Chrome, given that powers out insights). The Chrome team have made <a hreflang="en" href="https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/inp.md">a number of improvements that impact INP</a> over the last two years.</p> <p>Mobile INP metric by rank reveals an interesting trend. In <a href="../2022/performance#inp-by-rank">the 2022 chapter</a>, we assumed that the more popular a website is, the more performance optimizations it would have, leading to better performance. However, when it comes to INP, the opposite seems to be true.</p> <figure id="fig-22"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/interaction-to-next-paint-score-mobile-2024.png" class=""> <img src="/static/images/2024/performance/interaction-to-next-paint-score-mobile-2024.png" alt="INP performance on mobile devices segmented by rank." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=296559964&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=355582610"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_rank_and_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/interaction-to-next-paint-score-mobile-2024.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 9.22" data-hide-text="Hide description of Figure 9.22">Show description of Figure 9.22</button> <div id="fig-22-description" class="hidden">Stacked bar chart showing mobile INP performance by website rank, categorized into good (under 200 milliseconds), needs improvement (200–500 milliseconds), and poor (over 500 milliseconds).For the top 1,000 websites, 53% have good INP, 41% need improvement, and 6% perform poorly. For the top 10,000 websites, 49% are in the good range, 44% need improvement, and 7% are poor. In the top 100,000, 51% are good, 43% need improvement, and 6% are poor. For the top 1,000,000 websites, 61% have good INP, 35% need improvement, and 4% are poor. As the rank increases to the top 10,000,000 websites, 73% are good, 24% need improvement, and 3% are poor. Finally, for the top 100,000,000 websites, 74% have good INP, 24% need improvement, and 2% are poor.</div> <figcaption id="fig-22-caption"> <a href="#fig-22" class="anchor-link">Figure 9.22.</a> INP performance on mobile devices segmented by rank. </figcaption> </figure> <p>Fewer websites in the top 1,000 rank have good INP compared to the results for all websites. For example, 53% of the top 1,000 websites have a good INP score, while a much bigger percentage of all websites, i.e. 74%, meet this threshold.</p> <p>This could be because the most visited websites often have more user interactions and complex functionality. Logically, the INP for an interactive e-commerce site would differ from a simple, static blog.</p> <figure id="fig-23"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-interaction-to-next-paint-home-secondary-page.png" class=""> <img src="/static/images/2024/performance/good-interaction-to-next-paint-home-secondary-page.png" alt="Good INP performance on Home and Secondary page by device." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1483510539&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1159394005"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device_secondary_pages.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-interaction-to-next-paint-home-secondary-page.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 9.23" data-hide-text="Hide description of Figure 9.23">Show description of Figure 9.23</button> <div id="fig-23-description" class="hidden">Bar chart showing the percentage of pages with good INP for home pages and secondary pages, separated by desktop and mobile performance. For home pages, 96% of desktop pages have a good INP, while 73% of mobile pages achieve a good INP. For secondary pages, 96% of desktop pages also have a good INP, with 72% of mobile pages reaching this performance level.</div> <figcaption id="fig-23-caption"> <a href="#fig-23" class="anchor-link">Figure 9.23.</a> Good INP performance on Home and Secondary page by device. </figcaption> </figure> <p>Unlike other performance metrics like FCP and LCP, the percentage of secondary pages with good INP does not differ from the home page results. This is likely because INP isn&#8217;t as impacted by caching as loading speed is.</p> <h4 id="inp-sub-parts"><a href="#inp-sub-parts" class="anchor-link">INP sub-parts</a></h4> <p>Interaction to Next Paint metric can be broken down into three key sub-parts:</p> <ul> <li><strong>Input Delay</strong>: the time spent to finish processing the tasks that were already in the queue at the moment of the interaction</li> <li><strong>Processing Time</strong>: the time spent processing the event handlers attached to the element which the user interacted with</li> <li><strong>Presentation Delay</strong>: the time spent figuring out the new layout, if changed, and painting the new pixels on the screen</li> </ul> <p>To optimize your website&#8217;s interactivity, it&#8217;s important to identify the duration of every sub-part.</p> <figure id="fig-24"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/interaction-to-next-paint-subparts-rum-vision.png" class=""> <img src="/static/images/2024/performance/interaction-to-next-paint-subparts-rum-vision.png" alt="INP sub-parts by percentile." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=226800794&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=731456372"> View data </a> </li> <li> <a href="/static/images/2024/performance/interaction-to-next-paint-subparts-rum-vision.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 9.24" data-hide-text="Hide description of Figure 9.24">Show description of Figure 9.24</button> <div id="fig-24-description" class="hidden">Bar chart showing the distribution of INP sub-parts in milliseconds (ms) by percentile. At the 10th percentile, all sub-parts (input delay, processing time, and presentation delay) are minimal. At the 25th percentile, the values slightly increase but remain below 10 milliseconds. At the 50th percentile, input delay and processing time stay modest, while presentation delay reaches around 20 milliseconds. At the 75th percentile, input delay increases to around 50 milliseconds, with processing time and presentation delay also rising. At the 90th percentile, input delay reaches around 150 milliseconds, and both processing time and presentation delay exceed 100 milliseconds.</div> <figcaption id="fig-24-caption"> <a href="#fig-24" class="anchor-link">Figure 9.24.</a> INP sub-parts by percentile. </figcaption> </figure> <p>The INP sub-part duration distribution data from RUMvision shows that presentation delay (36 milliseconds) contributes the most to the median INP. As percentiles increase, input delay and processing time become longer. At the 75th percentile, input delay reaches 37 milliseconds and processing delay 56 milliseconds. By the 90th percentile, input delay jumps to 155 milliseconds, which makes it the biggest contributor to poor INP. One way to optimize input delay is by avoiding long tasks, which we explore in the Long Tasks section.</p> <h3 id="long-tasks"><a href="#long-tasks" class="anchor-link">Long tasks</a></h3> <p>One of the sub-parts of INP is input delay, which can be longer than it should be due to various factors, including long tasks. <a href="https://web.dev/articles/optimize-long-tasks#what-is-task">A task</a> is a discrete unit of work that the browser executes, and JavaScript is often the largest source of tasks. When a task exceeds 50 milliseconds, it is considered a long task. These long tasks can cause delays in responding to user interactions, directly affecting interactivity performance.</p> <p>Due to the lack of same-source data for long tasks and INP, we decided not to correlate them. We will, however, explore the average Long Task duration using data from RUMvision.</p> <figure id="fig-25"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/long-task-duration.png" class=""> <img src="/static/images/2024/performance/long-task-duration.png" alt="Task duration, segmented by device." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=688921860&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1272522211"> View data </a> </li> <li> <a href="/static/images/2024/performance/long-task-duration.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 9.25" data-hide-text="Hide description of Figure 9.25">Show description of Figure 9.25</button> <div id="fig-25-description" class="hidden">Bar chart showing the distribution of task duration in milliseconds (ms) by percentile and device type. At the 25th percentile, the task duration is 61 milliseconds for desktop and 71 for mobile. At the 50th percentile, it increases to 90 milliseconds for desktop and 108 milliseconds for mobile. At the 75th percentile, task duration is 161 milliseconds for desktop and 187 milliseconds for mobile; at the 90th percentile, it reaches 331 milliseconds for desktop and 377 for mobile. This distribution shows that task durations grow significantly as we move from the 25th to the 90th percentile.</div> <figcaption id="fig-25-caption"> <a href="#fig-25" class="anchor-link">Figure 9.25.</a> Task duration, segmented by device. </figcaption> </figure> <p>The task duration distribution shows a median task duration of 90 milliseconds for desktop and 108 milliseconds for mobile, which is twice more than the best practice recommendation of under 50 milliseconds. Less than 25% of websites have an optimal task duration below 50 milliseconds. We can also see that in every percentile, task duration on mobile sites is longer than on desktop sites, with the gap increasing as the percentile increases. On the 90th percentile, there is a 46 millisecond difference between the average task duration between device types. This correlates well with INP scores that show better results on desktop compared to mobile.</p> <p>Task duration data was retrieved using the <a hreflang="en" href="https://www.w3.org/TR/longtasks-1/">Long Tasks API</a>, which provides some useful data about performance issues, but it has limitations when it comes to accurately measuring sluggishness. It only identifies when a long task occurs and how long it lasts. It might overlook essential tasks such as rendering. Due to these limitations, we will explore the Long Animation Frames API in the next section, which offers more detailed insights.</p> <h4 id="long-animation-frames"><a href="#long-animation-frames" class="anchor-link">Long animation frames</a></h4> <p><a href="https://developer.chrome.com/docs/web-platform/long-animation-frames">Long Animation Frames (LoAF)</a> are a performance timeline entry for identifying sluggishness and poor INP by tracking when work and rendering block the main thread. LoAF tracks animation frames instead of individual tasks like the Long Tasks API. A long animation frame is when a rendering update is delayed beyond 50 milliseconds (the same as the threshold for the Long Tasks API). It helps to find scripts that cause INP performance bottlenecks. This data allows us to analyze INP performance based on the categories of scripts responsible for LoAF.</p> <figure id="fig-26"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/interaction-to-next-paint-script-categories-desktop-rum-vision.png" class=""> <img src="/static/images/2024/performance/interaction-to-next-paint-script-categories-desktop-rum-vision.png" alt="Distribution of INP performance segmented by script categories on desktop." aria-labelledby="fig-26-caption" aria-describedby="fig-26-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1975914925&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=947269170"> View data </a> </li> <li> <a href="/static/images/2024/performance/interaction-to-next-paint-script-categories-desktop-rum-vision.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-26-description" data-show-text="Show description of Figure 9.26" data-hide-text="Hide description of Figure 9.26">Show description of Figure 9.26</button> <div id="fig-26-description" class="hidden">Stacked bar chart showing the distribution of INP across LOAF script categories for desktop, measured in milliseconds (ms). User Review, SMS &amp; Email, and Analytics scripts perform best, with most of their INP in the good range. Tag Manager and Consent Provider scripts have more mid-range INP, with some falling into the poor category. Advertising, Others, and User Behaviour scripts perform worse, with the majority of INP falling into the poor range.</div> <figcaption id="fig-26-caption"> <a href="#fig-26" class="anchor-link">Figure 9.26.</a> Distribution of INP performance segmented by script categories on desktop. </figcaption> </figure> <figure id="fig-27"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/interaction-to-next-paint-script-categories-mobile-rum-vision.png" class=""> <img src="/static/images/2024/performance/interaction-to-next-paint-script-categories-mobile-rum-vision.png" alt="Distribution of INP performance segmented by script categories on mobile." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1978447282&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=947269170"> View data </a> </li> <li> <a href="/static/images/2024/performance/interaction-to-next-paint-script-categories-mobile-rum-vision.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 9.27" data-hide-text="Hide description of Figure 9.27">Show description of Figure 9.27</button> <div id="fig-27-description" class="hidden">Stacked bar chart showing the distribution of INP across LOAF script categories for mobile, measured in milliseconds (ms). For Social scripts, most are in the good range, with few in the poor range. Video and Tag Manager scripts also have a majority in the good range but with a larger portion in the mid-range. Site Search and Advertising scripts have a more even distribution, with a significant part in the mid-range and some in the poor range. Developer Utilities, Others, and User Behaviour scripts perform worse, with most falling in the poor range.</div> <figcaption id="fig-27-caption"> <a href="#fig-27" class="anchor-link">Figure 9.27.</a> Distribution of INP performance segmented by script categories on mobile. </figcaption> </figure> <p>The top two categories contributing the most to slow INP scores on mobile and desktop devices are User Behavior scripts (37% of mobile and 60% of desktop pages with good INP) and CDN/Hosting (50% of mobile and 65% of desktop pages with good INP).</p> <p>User Behavior scripts include scripts from hosts like <code>script.hotjar.com</code>, <code>smartlook.com</code>, <code>newrelic.com</code>, etc. While these tools provide valuable insights about users, our data shows that they can significantly degrade user experience by slowing down website interactions.</p> <p>CDN and Hosting script category examples come from domains like <code>cdn.jsdelivr.net</code>, <code>ajax.cloudflare.com</code>, <code>cdnjs.cloudflare.com</code>, <code>cdn.shopify.com</code>, <code>sdk.awswaf.com</code>, <code>cloudfront.net</code>, <code>s3.amazonaws.com</code> and others. Having CDNs among the categories with the poorest INP results seems controversial because CDNs are usually recommended as a performance optimization technique that reduces server load and delivers content faster to users. However, the CDNs included in this category usually deliver first- or third-party JavaScript resources, which contribute to LoAF and negatively impact interactivity.</p> <p>On mobile devices, Consent Providers seem to have a significant impact on INP, resulting in only 53% of mobile pages having good INP when using one. This category consists of providers like <code>consentframework.com</code>, <code>cookiepro.com</code>, <code>cookiebot.com</code>, <code>privacy-mgmt.com</code>, <code>usercentrics.eu</code>, and many others. On desktop devices, Consent Provider scripts show much better results, i.e. 76% of pages with good INP. This difference is likely due to the more powerful processors on desktop devices.</p> <p>It is worth noting that the monitoring category, which also includes performance monitoring tools, has one of the least impacts on poor INP results. This is a good argument in favor of using web performance monitoring tools, as they help with valuable web performance insights without significantly affecting interactivity performance.</p> <h3 id="total-blocking-time-tbt"><a href="#total-blocking-time-tbt" class="anchor-link">Total Blocking Time (TBT)</a></h3> <p><a href="https://web.dev/articles/tbt">Total Blocking Time (TBT)</a> measures the total amount of time after First Contentful Paint (FCP) where the main thread was blocked for long enough to prevent input responsiveness.</p> <p>TBT is a lab metric and is often used as a proxy for field-based responsiveness metrics, such as INP, which can only be collected using real user monitoring, such as CrUX and RUMvision. <a hreflang="en" href="https://colab.research.google.com/drive/12lJmAABgyVjaUbmWvrbzj9BkkTxw6ay2">Lab-based TBT and field-based INP</a> are correlated, meaning TBT results generally reflect INP trends. A TBT below 200 milliseconds is considered good, but most mobile websites exceed this target significantly.</p> <figure id="fig-28"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/total-blocking-time-2024.png" class=""> <img src="/static/images/2024/performance/total-blocking-time-2024.png" alt="TBT per page by percentile." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1525715716&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=89045350"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/inp_tbt.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/total-blocking-time-2024.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 9.28" data-hide-text="Hide description of Figure 9.28">Show description of Figure 9.28</button> <div id="fig-28-description" class="hidden">Bar chart showing the distribution of Total Blocking Time (TBT) per page in milliseconds (ms) by percentile. At the 10th percentile, both desktop and mobile TBT are near 0 milliseconds. At the 25th percentile, desktop TBT is 84 milliseconds, while mobile is 417 milliseconds. At the 50th percentile, desktop has 67 milliseconds of TBT, and mobile rises significantly to 1,209 milliseconds. At the 75th percentile, desktop reaches 282 milliseconds, with mobile at 2,990 milliseconds. Finally, at the 90th percentile, desktop TBT is 718 milliseconds, and mobile climbs to 5,955 milliseconds</div> <figcaption id="fig-28-caption"> <a href="#fig-28" class="anchor-link">Figure 9.28.</a> TBT per page by percentile. </figcaption> </figure> <p>The median TBT on mobile is 1,209 milliseconds, which is 6 times higher than the best practice. In contrast, desktop websites show much better performance, with a median TBT of just 67 milliseconds. It is important to emphasize that the lab results use an emulated low-power device and a slow network, which may not reflect the real user data, as actual device and network conditions can vary. However, even with that in mind, these results still show that in the 90th percentile, user on mobile device will need to wait almost 6 seconds before the site becomes interactive.</p> <p>With TBT being caused by long tasks it is not surprising to notice the same trend per percentiles as well as similar trend in gap between mobile and desktop in the two metrics results. It is also important to note that high TBT can be contributing to the input delay part of the INP, negatively impacting the overall INP score.</p> <h3 id="interactivity-conclusion"><a href="#interactivity-conclusion" class="anchor-link">Interactivity conclusion</a></h3> <p>The main takeaways of the interactivity results are:</p> <ul> <li>Despite the improvement in INP each year, a significant gap between desktop (97% good INP) and mobile (74% good INP) performance still exists.</li> <li>The top visited websites show poorer INP results compared to less popular ones.</li> <li>INP can be divided into three sub-parts: Input Delay, Processing Time, and Presentation Delay. Presentation Delay has the biggest share of the median INP in RUMvisions&#8217;s data.</li> <li>Scripts from user behavior tracking, consent provider, and CDN categories are the main contributors to poor INP scores.</li> </ul> <h2 id="visual-stability"><a href="#visual-stability" class="anchor-link">Visual stability</a></h2> <p>Visual stability on a website refers to the consistency and predictability of visual elements as the page loads and users interact with it. A visually stable website ensures that content does not unexpectedly shift, move, or change layout, which can disrupt the user experience. These shifts often happen due to assets without specified dimensions (images and videos), third-party ads, heavy fonts, etc. The primary metric for measuring visual stability is <a href="https://web.dev/articles/cls">Cumulative Layout Shift (CLS)</a>.</p> <h3 id="cumulative-layout-shift-cls"><a href="#cumulative-layout-shift-cls" class="anchor-link">Cumulative Layout Shift (CLS)</a></h3> <p>CLS measures the biggest burst of layout shift scores for any unexpected layout shifts that happen while a page is open. Layout shifts occur when a visible element changes its position from one place to another.</p> <p>A CLS score of 0.1 or less is considered good, meaning the page offers a visually stable experience, while scores between 0.1 and 0.25 indicate the need for improvement, and scores above 0.25 are considered poor, indicating that users may experience disruptive, unexpected layout shifts.</p> <figure id="fig-29"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-cls-by-device-2024.png" class=""> <img src="/static/images/2024/performance/good-cls-by-device-2024.png" alt="CLS performance by device for 2024." aria-labelledby="fig-29-caption" aria-describedby="fig-29-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1271338928&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/good-cls-by-device-2024.png"> View image </a> </li> </ul> </div> </div> <button type="button" class="fig-description-button novisibility-until-js" aria-expanded="false" aria-controls="fig-29-description" data-show-text="Show description of Figure 9.29" data-hide-text="Hide description of Figure 9.29">Show description of Figure 9.29</button> <div id="fig-29-description" class="hidden">Stacked bar chart showing CLS performance for 2024 by device. For desktop sites, 72% of sites had good CLS score, 18% need improvement, and 11% are considered poor. For mobile sites, 79% of sites have a good score, 12% need improvement, and 9% have a poor score.</div> <figcaption id="fig-29-caption"> <a href="#fig-29" class="anchor-link">Figure 9.29.</a> CLS performance by device for 2024. </figcaption> </figure> <p>In 2024, 72% of websites achieved good CLS scores, while 11% had poor ones. We can also see that websites on mobile devices provide a better user experience when it comes to site stability than desktop sites.</p> <figure id="fig-30"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/good-cls-by-device.png" class=""> <img src="/static/images/2024/performance/good-cls-by-device.png" alt="The percent of websites having good CLS, segmented by device and year." aria-labelledby="fig-30-caption" aria-describedby="fig-30-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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1974391374&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1535582002"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/web_vitals_by_device.sql"> View query </a> </li> <li> <a href="/static/images/2024/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-30-description" data-show-text="Show description of Figure 9.30" data-hide-text="Hide description of Figure 9.30">Show description of Figure 9.30</button> <div id="fig-30-description" class="hidden">Bar chart showing the number of websites with good CLS segmented by device and years. The percentage of mobile sites having good CLS was 60% for year 2020., 62% for 2021, 74% for 2022, 76% for 2023, and 79% for 2024. For desktop sites, 54% had good CLS in 2020, 62% in 2021, 65% in 2022, 68% in 2023, and 72% in 2024.</div> <figcaption id="fig-30-caption"> <a href="#fig-30" class="anchor-link">Figure 9.30.</a> The percent of websites having good CLS, segmented by device and year. </figcaption> </figure> <p>Looking at the metrics over time, we can see a nice upward trend. There is an increase from 60% of websites with good visual stability in 2020 to almost 80% in 2024. A visible jump in mobile data is already addressed in detail and attributed to the introduction of bfcache in <a href="../2022/performance#cumulative-layout-shift-cls">the 2022 chapter</a>. There is still a visible difference from 2022, so we will look in detail at some of the aspects that possibly contributed to it.</p> <h3 id="backforward-cache-bfcache"><a href="#backforward-cache-bfcache" class="anchor-link">Back/forward cache (bfcache)</a></h3> <p><a href="https://web.dev/articles/bfcache">The back/forward cache (bfcache)</a> is a browser optimization feature that improves the speed and efficiency of navigating between web pages by caching a fully interactive snapshot of a page in memory when a user navigates away from it. However, not all sites are eligible for bfcache. With an <a hreflang="en" href="https://html.spec.whatwg.org/multipage/nav-history-apis.html#nrr-details-reason">extensive eligibility criteria</a>, the easiest way to check if the site is eligible is to <a href="https://developer.chrome.com/docs/devtools/application/back-forward-cache">test it in Chrome DevTools</a>.</p> <p>Let&#8217;s look deeper by checking a few eligibility criteria that are quite a common cause and easily measurable using lab data.</p> <p>One of the &#8220;usual suspects&#8221; is the <code>unload</code> event that is triggered when a user navigates away from a page. Due to how bfcache preserves a page&#8217;s state, <code>unload</code> event makes the page ineligible for bfcache. Important to note here is that this feature is specific for browsers on desktops. Mobile browsers ignore the <code>unload</code> event when deciding bfcache eligibility, since it is already unreliable on those devices given how background pages are discarded more often there. This behavior could explain CLS improvement over the years and the gap between mobile and desktop numbers:</p> <figure id="fig-31"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/unload-usage.png" class=""> <img src="/static/images/2024/performance/unload-usage.png" alt="Usage of unload by site rank." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1163433950&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1706831462"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/bfcache_unload.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/unload-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-31-description" data-show-text="Show description of Figure 9.31" data-hide-text="Hide description of Figure 9.31">Show description of Figure 9.31</button> <div id="fig-31-description" class="hidden">Bar chart showing the percentage of pages ineligible for bfcache (back-forward cache) due to unload handlers, by rank, for desktop and mobile devices. For the top 1,000 websites, 35% of desktop pages are ineligible. For the top 10,000, 34% of desktop are ineligible. In the top 100,000, 29% of desktop are ineligible. At the 1,000,000 rank, 21% of desktop pages are ineligible. At the 10,000,000 rank, 17% of desktop are ineligible, while for all ranks, 16% of desktop pages are ineligible.</div> <figcaption id="fig-31-caption"> <a href="#fig-31" class="anchor-link">Figure 9.31.</a> Usage of unload by site rank. </figcaption> </figure> <p>From the above chart showing <code>unload</code> events from pages, we can see a few interesting things. Overall event usage is quite low, 15-16%. However, it increases drastically for the top 1.000 sites, to 35% on desktop and 27% on mobile, indicating that more popular sites probably use quite some more third-party services that often use this specific event. The gap between mobile and desktop is significant as, while mobile sites using <code>unload</code> events are still eligible for the bfcache, they are still unreliable.</p> <p>It is expected to see this decrease in the use of unload events with major browsers like Google Chrome and Firefox moving towards its deprecation since around 2020 and encouraging the use of alternative events like <code>pagehide</code> and <code>visibilitychange</code>. These events are more reliable, do not block the browser&#8217;s navigation, and are compatible with bfcache, allowing pages to be preserved in memory and restored instantly when users navigate back or forward.</p> <p>Another common reason for websites to fall in the bfcache ineligibility category is the use of the <code>cache-control: no-store</code> directive. This cache control header instructs the browser (and any intermediate caches) not to store a copy of the resource, ensuring that the content is fetched from the server on every request.</p> <figure id="fig-32"> <div class="figure-wrapper"> <div class="big-number">21%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=389603749"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/cls_animations.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-32-caption"> <a href="#fig-32" class="anchor-link">Figure 9.32.</a> Percentage of sites using <code>Cache-Control: no-store</code>. </figcaption> </figure> <p>21% of sites are using <code>Cache-Control: no-store</code>. That is a slight decrease from the 2022 report when this measure was about 22%.</p> <p>When bfcache was first introduced, it brought noticeable improvements to Core Web Vitals. Based on that, Chrome is <a href="https://developer.chrome.com/docs/web-platform/bfcache-ccns">gradually bringing bfcache to more sites</a> that were previously ineligible due to the use of the <code>Cache-Control: no-store</code> header. This change aims to further improve site performance.</p> <p>Unload event, as well as <code>Cache-Control: no-store</code>, do not directly affect the page&#8217;s visual stability. As already mentioned, the concept of bfcache load as a side-effect has this positive impact by eliminating some potential issues affecting metrics directly, such as unsized images or dynamic content. To continue exploring the visual stability aspect of the web, let&#8217;s check some of the practices that directly impact the CLS.</p> <h3 id="cls-best-practices"><a href="#cls-best-practices" class="anchor-link">CLS best practices</a></h3> <p>The following best practices allow you to reduce, or even completely avoid CLS.</p> <h4 id="explicit-dimensions"><a href="#explicit-dimensions" class="anchor-link">Explicit dimensions</a></h4> <p>One of the most common reasons for unexpected layout shifts is not preserving space for assets or incoming dynamic content. For example, adding <code>width</code> and <code>height</code> attributes on images is one of the easiest ways to preserve space and avoid shifts.</p> <figure id="fig-33"> <div class="figure-wrapper"> <div class="big-number">66%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1674162543"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/cls_unsized_images.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-33-caption"> <a href="#fig-33" class="anchor-link">Figure 9.33.</a> The percent of mobile pages that fail to set explicit dimensions on at least one image. </figcaption> </figure> <p>66% of mobile pages have at least one unsized image, which is an improvement from 72% in 2022.</p> <figure id="fig-34"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/unsized-images-amount.png" class=""> <img src="/static/images/2024/performance/unsized-images-amount.png" alt="The number of unsized images per page." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=603112996&amp;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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=1674162543"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/cls_unsized_images.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/unsized-images-amount.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 9.34" data-hide-text="Hide description of Figure 9.34">Show description of Figure 9.34</button> <div id="fig-34-description" class="hidden">Bar chart showing the number of unsized images per page by percentile for desktop and mobile devices. At the 10th and 25th percentiles, both desktop and mobile pages have 0 unsized images. At the 50th percentile, both desktop and mobile pages have 2 unsized images. At the 75th percentile, desktop pages have 10 unsized images, while mobile pages have 9. At the 90th percentile, desktop pages have 26 unsized images, and mobile pages have 23.</div> <figcaption id="fig-34-caption"> <a href="#fig-34" class="anchor-link">Figure 9.34.</a> The number of unsized images per page. </figcaption> </figure> <p>The median number of unsized images per web page is two. When we shift to the 90th percentile, that number jumps to 26 for desktop sites and 23 for mobile. Having unsized images on the page can be a risk for layout shift; however, an important aspect to look at is if images are affecting the viewport and if yes, how much.</p> <figure id="fig-35"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/unsized-images-height.png" class=""> <img src="/static/images/2024/performance/unsized-images-height.png" alt="Distribution of the heights of unsized images." 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-1vRiPhLGlGUxomTx_5nC9ahQDRxZBmJXMT3Q0Z2z4Y2pPVqC9kzjsUjRk4hz-JZzaPBjVxyaf7Gtqh93/pubchart?oid=1462566122&amp;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://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/cls_unsized_image_height.sql"> View query </a> </li> <li> <a href="/static/images/2024/performance/unsized-images-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-35-description" data-show-text="Show description of Figure 9.35" data-hide-text="Hide description of Figure 9.35">Show description of Figure 9.35</button> <div id="fig-35-description" class="hidden">Bar chart showing the 10, 25, 50, 75, and 90th percentile height of unsized images. The values for mobile are 16, 38, 100, 200, and 297px tall, respectively. The values for the desktop are larger: 16, 40, 110, 241, and 403.</div> <figcaption id="fig-35-caption"> <a href="#fig-35" class="anchor-link">Figure 9.35.</a> Distribution of the heights of unsized images. </figcaption> </figure> <p>The median mobile site has unsized images of about 100 pixels in height. Our test devices have a mobile viewport height of 512 pixels, representing almost 20% of the screen width. This can potentially be shifted down when an unsized (full-width) image loads, which is not an insignificant shift.</p> <p>As expected, image heights on desktop pages are larger, with the size on the median being 110px and on the 90th percentile 403 pixels.</p> <h4 id="fonts"><a href="#fonts" class="anchor-link">Fonts</a></h4> <p>Fonts can directly impact CLS. When web fonts are loaded asynchronously, a delay occurs between the initial rendering of the page and the time when the custom fonts are applied. During this delay, browsers often display text using a fallback font, which can have different dimensions (width, height, letter spacing) compared to the web font. When the web font finally loads, the text may shift to accommodate the new dimensions, causing a visible layout shift and contributing to a higher CLS score.</p> <figure id="fig-36"> <div class="figure-wrapper"> <div class="big-number">85%</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=344191137"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/font_usage_mobile.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-36-caption"> <a href="#fig-36" class="anchor-link">Figure 9.36.</a> The percent of mobile pages that use web fonts. </figcaption> </figure> <p> Using system fonts is one way to fix this issue. However, with 85% of mobile pages using web fonts it is not very likely that they will stop being used any time soon. A way to control the visual stability of a site that uses web fonts is to use the <code>font-display</code> property in CSS to control how fonts are loaded and displayed. <a href="https://web.dev/articles/font-best-practices#choose_an_appropriate_font-display_strategy">Different <code>font-display</code> strategies can be used</a> depending on the team&#8217;s decision about the tradeoff between performance and aesthetics. </p> <figure id="fig-37"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/font-display-usage.png" class=""> <img src="/static/images/2024/performance/font-display-usage.png" alt="Usage of font-display." 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/u/1/d/e/2PACX-1vTHmcrit1gMzxfZNeFp9LrA4NQSMEh140fapD4CFQ89knpy6LvEKz7VafGaFGlxCAxTdpLZXaVaq8Pg/pubchart?oid=1458420916&amp;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/1EkdvJ8e0B9Rr42evC2Ds5Ekwq6gF9oLBW0BA5cmSUT4/edit?gid=455989674#gid=455989674"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/../fonts/performance/styles_font_display.sql"> View query </a> </li> <li> <a href="/static/images/2024/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-37-description" data-show-text="Show description of Figure 9.37" data-hide-text="Hide description of Figure 9.37">Show description of Figure 9.37</button> <div id="fig-37-description" class="hidden">Bar chart showing the percent of pages that use the various font-display values. 45% of mobile pages use swap, 23% block, 9% auto, 3% fallback, and 1% use optional. The values for desktop are similar.</div> <figcaption id="fig-37-caption"> <a href="#fig-37" class="anchor-link">Figure 9.37.</a> Usage of font-display. </figcaption> </figure> <p>From the data displayed above, we can see that around 44% of both mobile and desktop sites use <code>font-display:swap</code> while 23% of sites use <code>font-display:block</code>. 9% of sites set the <code>font-display</code> property to <code>auto</code> and 3% use the <code>fallback</code> property. Only around 1% of sites use the <code>optional</code> strategy.</p> <p>Compared to the 2022 data, there is a visible increase in the use of all <code>font-display</code> strategies, the biggest one being on <code>swap</code>, whose usage on both mobile and desktop pages jumped from around 30% in 2022 to over 44%.</p> <p>Since most <code>font-display</code> strategies can contribute to CLS, we need to look at other strategies for minimizing potential issues. One of those is using resource hints to ensure third-party fonts are discovered and loaded as soon as possible.</p> <figure id="fig-38"> <div class="figure-wrapper"> <a href="/static/images/2024/performance/fonts-resource-hints.png" class=""> <img src="/static/images/2024/performance/fonts-resource-hints.png" alt="Adoption of resource hints for font resources." aria-labelledby="fig-38-caption" aria-describedby="fig-38-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/u/1/d/e/2PACX-1vTHmcrit1gMzxfZNeFp9LrA4NQSMEh140fapD4CFQ89knpy6LvEKz7VafGaFGlxCAxTdpLZXaVaq8Pg/pubchart?oid=769711215&amp;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/1EkdvJ8e0B9Rr42evC2Ds5Ekwq6gF9oLBW0BA5cmSUT4/edit?gid=405563602#gid=405563602"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/../fonts/performance/pages_link_relationship.sql"> View query </a> </li> <li> <a href="/static/images/2024/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-38-description" data-show-text="Show description of Figure 9.38" data-hide-text="Hide description of Figure 9.38">Show description of Figure 9.38</button> <div id="fig-38-description" class="hidden">Bar chart showing the percent of pages that use each type of resource hint on web fonts. 18% of mobile pages use preconnect, 16% dns-prefetch, 11% preload, and less than 1% prefetch. The values for desktop are almost the same.</div> <figcaption id="fig-38-caption"> <a href="#fig-38" class="anchor-link">Figure 9.38.</a> Adoption of resource hints for font resources. </figcaption> </figure> <p>Around 11% of all tested mobile and desktop pages are preloading their web fonts, indicating to the browser that they should download these files, hopefully early enough to avoid shifts due to late font arrival. Note that using preload incorrectly can harm performance instead of helping it. To avoid this, we need to make sure that the preloaded font will be used and that we don&#8217;t preload too many assets. Preloading too many assets can end up delaying other, more important resources.</p> <p>18% of sites are using <code>preconnect</code> to establish an early connection to a third-party origin. Like with <code>preload</code> it is important to use this resource hint carefully and not to overdo it.</p> <h4 id="animations"><a href="#animations" class="anchor-link">Animations</a></h4> <p>Another cause of unexpected shifts can be <a href="https://developer.chrome.com/docs/lighthouse/performance/non-composited-animations">non-composited</a> CSS animations. These animations involve changes to properties that impact the layout or appearance of multiple elements, which forces the browser to go through more performance-intensive steps like recalculating styles, reflowing the document, and repainting pixels on the screen. The best practice is to use CSS properties such as <code>transform</code> and <code>opacity</code> instead.</p> <figure id="fig-39"> <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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/#gid=293393420"> View data </a> </li> <li> <a href="https://github.com/HTTPArchive/almanac.httparchive.org/tree/main/sql/2024/performance/cls_animations.sql"> View query </a> </li> </ul> </div> </div> <figcaption id="fig-39-caption"> <a href="#fig-39" class="anchor-link">Figure 9.39.</a> The percent of mobile pages that have non-composited animations. </figcaption> </figure> <p>39% of mobile pages and 42% of desktop pages still use non-composited animations, which is a very slight increase from 38% for mobile and 41% for desktop in the analysis from 2022.</p> <h3 id="visual-stability-conclusion"><a href="#visual-stability-conclusion" class="anchor-link">Visual stability conclusion</a></h3> <p>Visual stability of the site can have a big influence on the user experience of the page. Having text shifting around while reading or a button we were just about to click disappear from the viewport can lead to user frustration. The good news is that Cumulative Layout Shift (CLS) continued to improve in 2024. That indicates that more and more website owners are adopting good practices such as sizing images and preserving space for dynamic content, as well as optimizing for bfcache eligibility to benefit from this browser feature.</p> <h2 id="conclusion"><a href="#conclusion" class="anchor-link">Conclusion</a></h2> <p>Web performance continued to improve in 2024, with positive trends across many key metrics. We now have a more comprehensive metric to assess website interactivity—INP—which hopefully should lead to even greater performance optimizations.</p> <p>However, challenges remain. For example, there is still a significant gap in INP performance between desktop and mobile. Presentation Delay is the main contributor to poor INP, mostly caused by third-party scripts for behavior tracking, consent providers, and CDNs.</p> <p>Visual stability continues to improve by the adoption of best practices like proper image sizing and preserving space for dynamic content. Additionally, with recent changes in Chrome&#8217;s bfcache eligibility, more sites will benefit from faster back and forward navigation.</p> <p>Overall, web performance is on a promising track, making loading times faster, interactivity smoother, and visual stability more reliable. However, the difference between mobile and desktop experiences remains large. In future Web Almanac reports, we hope to see this gap decreasing, making the web experience consistent across all devices.</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/15038wEIoqY53Y_kR8U6QWM-PBO31ZySQGi147ABTNBc/"> <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/2024/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+2024+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/2024/contributors#imeugenia" tabindex="-1"> <img class="avatar" alt="Jevgenija Zigisova avatar" src="https://avatars.githubusercontent.com/u/17236402?v=4&s=200" height="200" width="200" loading="lazy"> </a> </div> <div class="info"> <a href="/en/2024/contributors#imeugenia"><span class="name">Jevgenija Zigisova</span></a> <div class="social"> <a class="twitter" href="https://x.com/jevgeniazi" aria-labelledby="author-imeugenia-twitter"> <svg width="22" height="22" role="img"> <title id="author-imeugenia-twitter">@jevgeniazi on Twitter/X</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> @jevgeniazi </a> <a class="github" href="https://github.com/imeugenia" aria-labelledby="author-imeugenia-github"> <svg width="22" height="20"> <title id="author-imeugenia-github">imeugenia on GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> imeugenia </a> <a class="linkedin" href="https://www.linkedin.com/in/imeugenia/" aria-labelledby="author-imeugenia-linkedin"> <svg width="22" height="22"> <title id="author-imeugenia-linkedin">Jevgenija Zigisova on LinkedIn</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#linkedin-logo"></use> </svg> imeugenia </a> </div> <div class="bio"> Jevgenija is a frontend engineer and tech event organizer who is passionate about web performance and developer experience. She works at <a hreflang="en" href="https://www.limehome.com/en/">Limehome</a>—a digital first hotel brand. She ran a Google Developer Group in Latvia and Berlin for several years. </div> </div> </li> <li> <div aria-hidden="true"> <a href="/en/2024/contributors#ines-akrap" tabindex="-1"> <img class="avatar" alt="Ines Akrap avatar" src="https://avatars.githubusercontent.com/u/5904064?v=4&s=200" height="200" width="200" loading="lazy"> </a> </div> <div class="info"> <a href="/en/2024/contributors#ines-akrap"><span class="name">Ines Akrap</span></a> <div class="social"> <a class="twitter" href="https://x.com/InesAkrap" aria-labelledby="author-ines-akrap-twitter"> <svg width="22" height="22" role="img"> <title id="author-ines-akrap-twitter">@InesAkrap on Twitter/X</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#twitter-logo"></use> </svg> @InesAkrap </a> <a class="github" href="https://github.com/ines-akrap" aria-labelledby="author-ines-akrap-github"> <svg width="22" height="20"> <title id="author-ines-akrap-github">ines-akrap on GitHub</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#github-logo"></use> </svg> ines-akrap </a> <a class="website" href="https://inesakrap.com/" aria-labelledby="author-ines-akrap-website"> <svg width="22" height="22"> <title id="author-ines-akrap-website">Ines Akrap website</title> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#globe-logo"></use> </svg> https://inesakrap.com/ </a> </div> <div class="bio"> Ines Akrap is a Frontend Software Engineer passionate about optimizing websites to be fast, sustainable, and provide the best user experience for every user. She works in Storyblok as a Solutions Engineer. She enjoys sharing her knowledge through talks, podcasts, workshops, and courses. </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.2024.Performance, author = "Zigisova, Jevgenija and Akrap, Ines and Viscomi, Rick and Karamalegos, Sia and Farrugia, Kevin and Franco, Estela and Ross, James", title = "Performance", booktitle = "The 2024 Web Almanac", chapter = 9, publisher = "HTTP Archive", year = "2024", language = "English", doi = "10.5281/zenodo.14065738", url = "https://almanac.httparchive.org/en/2024/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/2024/accessibility"> <span class="arrow" aria-hidden="true">&#8963;</span> <span class="chapter-no"> Chapter 8 </span> <span class="chapter-title"> Accessibility </span> </a> <a id="next-chapter" title="Next Chapter (press 'n' or '.')" href="/en/2024/privacy"> <span class="arrow" aria-hidden="true">&#8963;</span> <span class="chapter-no"> Chapter 10 </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/2024/"> <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/2024/contributors">Contributors</a></li> <li><a href="/en/2024/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/2024/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/2024/">Home</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents">Table of Contents</a> </li> <li class="nav-dropdown-list-chapter foreword"> <a href="/en/2024/table-of-contents#foreword">Foreword</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-1">Part I. Page Content</a> </li> <li class="nav-dropdown-list-chapter"> <span class="nav-dropdown-list-todo">Chapter 1: JavaScript</span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/markup"> Chapter 2: Markup </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/structured-data"> Chapter 3: Structured Data </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/fonts"> Chapter 4: Fonts </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/media"> Chapter 5: Media </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/third-parties"> Chapter 6: Third Parties </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-2">Part II. User Experience</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/seo"> Chapter 7: SEO </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/accessibility"> Chapter 8: Accessibility </a> </li> <li class="nav-dropdown-list-chapter nav-dropdown-list-current"> <span> Chapter 9: Performance </span> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/privacy"> Chapter 10: Privacy </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/security"> Chapter 11: Security </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-3">Part III. Content Publishing</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cms"> Chapter 12: CMS </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/ecommerce"> Chapter 13: Ecommerce </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/jamstack"> Chapter 14: Jamstack </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/sustainability"> Chapter 15: Sustainability </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#part-4">Part IV. Content Distribution</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/page-weight"> Chapter 16: Page Weight </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cdn"> Chapter 17: CDN </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/http"> Chapter 18: HTTP </a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/cookies"> Chapter 19: Cookies </a> </li> <li class="nav-dropdown-list-part"> <a href="/en/2024/table-of-contents#appendices">Appendices</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/methodology">Methodology</a> </li> <li class="nav-dropdown-list-chapter"> <a href="/en/2024/contributors">Contributors</a> </li> <li class="nav-dropdown-list-part"> <a href="/en/search">Search</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">2024</button> <ul class="nav-dropdown-list hidden footer-list"> <li> <a href="/en/2022/performance">2022</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 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/2024/contributors">Contributors</a></li> <li><a href="/en/2024/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/2024/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/2024/">Home</option> <option value="/en/2024/table-of-contents">Table of Contents</option> <option value="/en/2024/table-of-contents#foreword">Foreword</option> <option disabled> Chapter 1: JavaScript </option> <option value="/en/2024/markup"> Chapter 2: Markup </option> <option value="/en/2024/structured-data"> Chapter 3: Structured Data </option> <option value="/en/2024/fonts"> Chapter 4: Fonts </option> <option value="/en/2024/media"> Chapter 5: Media </option> <option value="/en/2024/third-parties"> Chapter 6: Third Parties </option> <option value="/en/2024/seo"> Chapter 7: SEO </option> <option value="/en/2024/accessibility"> Chapter 8: Accessibility </option> <option disabled selected value="/en/2024/performance"> Chapter 9: Performance </option> <option value="/en/2024/privacy"> Chapter 10: Privacy </option> <option value="/en/2024/security"> Chapter 11: Security </option> <option value="/en/2024/cms"> Chapter 12: CMS </option> <option value="/en/2024/ecommerce"> Chapter 13: Ecommerce </option> <option value="/en/2024/jamstack"> Chapter 14: Jamstack </option> <option value="/en/2024/sustainability"> Chapter 15: Sustainability </option> <option value="/en/2024/page-weight"> Chapter 16: Page Weight </option> <option value="/en/2024/cdn"> Chapter 17: CDN </option> <option value="/en/2024/http"> Chapter 18: HTTP </option> <option value="/en/2024/cookies"> Chapter 19: Cookies </option> <option value="/en/2024/methodology"> Methodology </option> <option value="/en/2024/contributors"> Contributors </option> <option value="/en/search"> Search </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 selected="selected" value="/en/2024/performance"> 2024 </option> <option 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/2024/performance"> English </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">&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="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"></script> <script defer src="/static/js/webmentions.js?v=dbb31a967a22e06b6c1bb62d7a9ff9a0" nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-PQ5N2MZG5M" nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"></script> <link rel="preconnect" href="https://www.google-analytics.com"> <script defer src="/static/js/web-vitals.js?v=f6f30f40e7d014a2d38f1362c5eb6244" nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"></script> <script defer src="/static/js/send-web-vitals.js?v=b7224f484fe762e075d4838286ddb066" nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"></script> <script type="speculationrules" nonce="_Od8DipeD1astGnXtkZgb0F4cK_pibP6"> { "prerender": [ { "source": "document", "where": { "and": [ {"href_matches": "/*"}, {"not": {"href_matches": "/static/*"}} ] }, "eagerness": "moderate" } ] } </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10