CINXE.COM

Optimize Cumulative Layout Shift  |  Articles  |  web.dev

<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="157101835696-ooapojlodmuabs2do2vuhhnf90bccmoi.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="web.dev"> <meta property="og:type" content="website"><meta name="theme-color" content="#3740ff"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/web/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/css/app.css"> <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/css/dark-theme.css" disabled> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/favicon.png"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/touchicon-180.png"><link rel="canonical" href="https://web.dev/articles/optimize-cls"><link rel="search" type="application/opensearchdescription+xml" title="web.dev" href="https://web.dev/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://web.dev/articles/optimize-cls" /><link rel="alternate" hreflang="x-default" href="https://web.dev/articles/optimize-cls" /><link rel="alternate" hreflang="ar" href="https://web.dev/articles/optimize-cls?hl=ar" /><link rel="alternate" hreflang="bn" href="https://web.dev/articles/optimize-cls?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://web.dev/articles/optimize-cls?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://web.dev/articles/optimize-cls?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://web.dev/articles/optimize-cls?hl=fa" /><link rel="alternate" hreflang="fr" href="https://web.dev/articles/optimize-cls?hl=fr" /><link rel="alternate" hreflang="de" href="https://web.dev/articles/optimize-cls?hl=de" /><link rel="alternate" hreflang="he" href="https://web.dev/articles/optimize-cls?hl=he" /><link rel="alternate" hreflang="hi" href="https://web.dev/articles/optimize-cls?hl=hi" /><link rel="alternate" hreflang="id" href="https://web.dev/articles/optimize-cls?hl=id" /><link rel="alternate" hreflang="it" href="https://web.dev/articles/optimize-cls?hl=it" /><link rel="alternate" hreflang="ja" href="https://web.dev/articles/optimize-cls?hl=ja" /><link rel="alternate" hreflang="ko" href="https://web.dev/articles/optimize-cls?hl=ko" /><link rel="alternate" hreflang="pl" href="https://web.dev/articles/optimize-cls?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://web.dev/articles/optimize-cls?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://web.dev/articles/optimize-cls?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://web.dev/articles/optimize-cls?hl=es-419" /><link rel="alternate" hreflang="th" href="https://web.dev/articles/optimize-cls?hl=th" /><link rel="alternate" hreflang="tr" href="https://web.dev/articles/optimize-cls?hl=tr" /><link rel="alternate" hreflang="vi" href="https://web.dev/articles/optimize-cls?hl=vi" /><link rel="alternate" hreflang="en-cn" href="https://web.developers.google.cn/articles/optimize-cls" /><link rel="alternate" hreflang="x-default" href="https://web.developers.google.cn/articles/optimize-cls" /><link rel="alternate" hreflang="ar-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=ar" /><link rel="alternate" hreflang="bn-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=bn" /><link rel="alternate" hreflang="zh-Hans-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=zh-tw" /><link rel="alternate" hreflang="fa-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=fa" /><link rel="alternate" hreflang="fr-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=fr" /><link rel="alternate" hreflang="de-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=de" /><link rel="alternate" hreflang="he-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=he" /><link rel="alternate" hreflang="hi-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=hi" /><link rel="alternate" hreflang="id-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=id" /><link rel="alternate" hreflang="it-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=it" /><link rel="alternate" hreflang="ja-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=ja" /><link rel="alternate" hreflang="ko-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=ko" /><link rel="alternate" hreflang="pl-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=pl" /><link rel="alternate" hreflang="pt-BR-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=pt-br" /><link rel="alternate" hreflang="ru-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=ru" /><link rel="alternate" hreflang="es-419-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=es-419" /><link rel="alternate" hreflang="th-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=th" /><link rel="alternate" hreflang="tr-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=tr" /><link rel="alternate" hreflang="vi-cn" href="https://web.developers.google.cn/articles/optimize-cls?hl=vi" /><title>Optimize Cumulative Layout Shift &nbsp;|&nbsp; Articles &nbsp;|&nbsp; web.dev</title> <meta property="og:title" content="Optimize Cumulative Layout Shift &nbsp;|&nbsp; Articles &nbsp;|&nbsp; web.dev"><meta name="description" content="Cumulative Layout Shift (CLS) is a metric that quantifies how often users experience sudden shifts in page content. In this guide, we&amp;#39;ll cover optimizing common causes of CLS such as images and iframes without dimensions or dynamic content."> <meta property="og:description" content="Cumulative Layout Shift (CLS) is a metric that quantifies how often users experience sudden shifts in page content. In this guide, we&amp;#39;ll cover optimizing common causes of CLS such as images and iframes without dimensions or dynamic content."><meta property="og:url" content="https://web.dev/articles/optimize-cls"><meta property="og:image" content="https://web.dev/static/articles/optimize-cls/image/thumbnail.v2.png"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="675"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "dateModified": "2023-05-04", "headline": "Optimize Cumulative Layout Shift" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Articles", "item": "https://web.dev/articles" },{ "@type": "ListItem", "position": 2, "name": "Optimize Cumulative Layout Shift", "item": "https://web.dev/articles/optimize-cls" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="web-theme" type="article" appearance layout="docs" display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="webDev" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="web.dev"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg" class="devsite-site-logo" alt="web.dev"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab > <a href="https://web.dev/about" track-metadata-eventdetail="https://web.dev/about" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - about" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: About" track-name="about" > About </a> </tab> <tab > <a href="https://web.dev/html" track-metadata-eventdetail="https://web.dev/html" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - html" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: HTML" track-name="html" > HTML </a> </tab> <tab > <a href="https://web.dev/css" track-metadata-eventdetail="https://web.dev/css" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - css" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: CSS" track-name="css" > CSS </a> </tab> <tab > <a href="https://web.dev/javascript" track-metadata-eventdetail="https://web.dev/javascript" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - javascript" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: JavaScript" track-name="javascript" > JavaScript </a> </tab> <tab > <a href="https://web.dev/blog" track-metadata-eventdetail="https://web.dev/blog" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - blog" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" > Blog </a> </tab> <tab > <a href="https://web.dev/learn" track-metadata-eventdetail="https://web.dev/learn" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - learn" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" > Learn </a> </tab> <tab class="devsite-active"> <a href="https://web.dev/explore" track-metadata-eventdetail="https://web.dev/explore" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - explore" track-metadata-module="primary nav" aria-label="Explore, selected" data-category="Site-Wide Custom Events" data-label="Tab: Explore" track-name="explore" > Explore </a> </tab> <tab > <a href="https://web.dev/patterns" track-metadata-eventdetail="https://web.dev/patterns" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - patterns" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Patterns" track-name="patterns" > Patterns </a> </tab> <tab > <a href="https://web.dev/case-studies" track-metadata-eventdetail="https://web.dev/case-studies" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - case studies" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Case studies" track-name="case studies" > Case studies </a> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="Articles" tenant-name="web.dev" > <form class="devsite-search-form" action="https://web.dev/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-appearance-selector></devsite-appearance-selector> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <devsite-user enable-profiles id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://web.dev/explore" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Collections </a> </li> </ul> </div> </div> <div class="devsite-doc-set-nav-row"> <devsite-tabs class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://web.dev/explore/learn-core-web-vitals" track-metadata-eventdetail="https://web.dev/explore/learn-core-web-vitals" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - core web vitals" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Core Web Vitals" track-name="core web vitals" > Core Web Vitals </a> </tab> <tab > <a href="https://web.dev/explore/metrics" track-metadata-eventdetail="https://web.dev/explore/metrics" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - metrics" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Metrics" track-name="metrics" > Metrics </a> </tab> <tab class="devsite-active"> <a href="https://web.dev/explore/fast" track-metadata-eventdetail="https://web.dev/explore/fast" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - fast load times" track-metadata-module="primary nav" aria-label="Fast load times, selected" data-category="Site-Wide Custom Events" data-label="Tab: Fast load times" track-name="fast load times" > Fast load times </a> </tab> <tab > <a href="https://web.dev/explore/ai" track-metadata-eventdetail="https://web.dev/explore/ai" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - ai" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: AI" track-name="ai" > AI </a> </tab> <tab > <a href="https://web.dev/explore/how-to-optimize-inp" track-metadata-eventdetail="https://web.dev/explore/how-to-optimize-inp" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - optimize interaction to next paint (inp)" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Optimize Interaction to Next Paint (INP)" track-name="optimize interaction to next paint (inp)" > Optimize Interaction to Next Paint (INP) </a> </tab> <tab > <a href="https://web.dev/explore/progressive-web-apps" track-metadata-eventdetail="https://web.dev/explore/progressive-web-apps" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - progressive web apps" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Progressive Web Apps" track-name="progressive web apps" > Progressive Web Apps </a> </tab> <tab > <a href="https://web.dev/accessibility" track-metadata-eventdetail="https://web.dev/accessibility" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - accessible to all" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Accessible to all" track-name="accessible to all" > Accessible to all </a> </tab> <tab > <a href="https://web.dev/explore/reliable" track-metadata-eventdetail="https://web.dev/explore/reliable" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - network reliability" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Network reliability" track-name="network reliability" > Network reliability </a> </tab> <tab > <a href="https://web.dev/explore/secure" track-metadata-eventdetail="https://web.dev/explore/secure" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - safe and secure" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Safe and secure" track-name="safe and secure" > Safe and secure </a> </tab> <tab > <a href="https://web.dev/explore/discoverable" track-metadata-eventdetail="https://web.dev/explore/discoverable" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - easily discoverable" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Easily discoverable" track-name="easily discoverable" > Easily discoverable </a> </tab> <tab > <a href="https://web.dev/explore/payments" track-metadata-eventdetail="https://web.dev/explore/payments" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - web payments" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Web Payments" track-name="web payments" > Web Payments </a> </tab> <tab > <a href="https://web.dev/explore/media" track-metadata-eventdetail="https://web.dev/explore/media" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - media" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Media" track-name="media" > Media </a> </tab> <tab > <a href="https://web.dev/explore/devices" track-metadata-eventdetail="https://web.dev/explore/devices" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - devices" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Devices" track-name="devices" > Devices </a> </tab> <tab > <a href="https://web.dev/explore/animations" track-metadata-eventdetail="https://web.dev/explore/animations" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - animations" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Animations" track-name="animations" > Animations </a> </tab> <tab > <a href="https://web.dev/explore/identity" track-metadata-eventdetail="https://web.dev/explore/identity" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - identity" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Identity" track-name="identity" > Identity </a> </tab> <tab > <a href="https://web.dev/explore/webassembly" track-metadata-eventdetail="https://web.dev/explore/webassembly" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - webassembly" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: WebAssembly" track-name="webassembly" > WebAssembly </a> </tab> <tab > <a href="https://web.dev/explore/test-automation" track-metadata-eventdetail="https://web.dev/explore/test-automation" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - test automation" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Test automation" track-name="test automation" > Test automation </a> </tab> <tab > <a href="https://web.dev/explore/react" track-metadata-eventdetail="https://web.dev/explore/react" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - react" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: React" track-name="react" > React </a> </tab> <tab > <a href="https://web.dev/explore/angular" track-metadata-eventdetail="https://web.dev/explore/angular" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - angular" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Angular" track-name="angular" > Angular </a> </tab> <tab > <a href="https://web.dev/explore/mini-apps" track-metadata-eventdetail="https://web.dev/explore/mini-apps" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - mini apps" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Mini apps" track-name="mini apps" > Mini apps </a> </tab> </nav> </devsite-tabs> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" hidden> <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="webDev" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup-dark-theme.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="web.dev"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg" class="devsite-site-logo" alt="web.dev"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: About" track-name="about" data-category="Site-Wide Custom Events" data-label="Responsive Tab: About" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > About </span> </a> </li> <li class="devsite-nav-item"> <a href="/html" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: HTML" track-name="html" data-category="Site-Wide Custom Events" data-label="Responsive Tab: HTML" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > HTML </span> </a> </li> <li class="devsite-nav-item"> <a href="/css" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: CSS" track-name="css" data-category="Site-Wide Custom Events" data-label="Responsive Tab: CSS" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > CSS </span> </a> </li> <li class="devsite-nav-item"> <a href="/javascript" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: JavaScript" track-name="javascript" data-category="Site-Wide Custom Events" data-label="Responsive Tab: JavaScript" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > JavaScript </span> </a> </li> <li class="devsite-nav-item"> <a href="/blog" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Blog" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Blog </span> </a> </li> <li class="devsite-nav-item"> <a href="/learn" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Explore" track-name="explore" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Explore" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Explore </span> </a> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/explore/learn-core-web-vitals" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Core Web Vitals" track-name="core web vitals" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Core Web Vitals" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Core Web Vitals </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/metrics" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Metrics" track-name="metrics" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Metrics" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Metrics </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/fast" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Fast load times" track-name="fast load times" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Fast load times" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip menu="_book"> Fast load times </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="_book"> </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/ai" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: AI" track-name="ai" data-category="Site-Wide Custom Events" data-label="Responsive Tab: AI" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > AI </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/how-to-optimize-inp" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Optimize Interaction to Next Paint (INP)" track-name="optimize interaction to next paint (inp)" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Optimize Interaction to Next Paint (INP)" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Optimize Interaction to Next Paint (INP) </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/progressive-web-apps" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Progressive Web Apps" track-name="progressive web apps" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Progressive Web Apps" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Progressive Web Apps </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/accessibility" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Accessible to all" track-name="accessible to all" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Accessible to all" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Accessible to all </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/reliable" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Network reliability" track-name="network reliability" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Network reliability" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Network reliability </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/secure" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Safe and secure" track-name="safe and secure" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Safe and secure" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Safe and secure </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/discoverable" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Easily discoverable" track-name="easily discoverable" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Easily discoverable" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Easily discoverable </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/payments" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Web Payments" track-name="web payments" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Web Payments" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Web Payments </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/media" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Media" track-name="media" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Media" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Media </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/devices" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Devices" track-name="devices" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Devices" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Devices </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/animations" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Animations" track-name="animations" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Animations" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Animations </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/identity" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Identity" track-name="identity" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Identity" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Identity </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/webassembly" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: WebAssembly" track-name="webassembly" data-category="Site-Wide Custom Events" data-label="Responsive Tab: WebAssembly" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > WebAssembly </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/test-automation" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Test automation" track-name="test automation" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Test automation" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Test automation </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/react" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: React" track-name="react" data-category="Site-Wide Custom Events" data-label="Responsive Tab: React" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > React </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/angular" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Angular" track-name="angular" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Angular" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Angular </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/explore/mini-apps" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Mini apps" track-name="mini apps" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Mini apps" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Mini apps </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/patterns" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Patterns" track-name="patterns" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Patterns" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Patterns </span> </a> </li> <li class="devsite-nav-item"> <a href="/case-studies" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Case studies" track-name="case studies" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Case studies" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Case studies </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Introduction</span> </div></li> <li class="devsite-nav-item"><a href="/articles/why-speed-matters" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/why-speed-matters" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/why-speed-matters" ><span class="devsite-nav-text" tooltip>Why does speed matter?</span></a></li> <li class="devsite-nav-item"><a href="/articles/what-is-speed" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/what-is-speed" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/what-is-speed" ><span class="devsite-nav-text" tooltip>What is speed?</span></a></li> <li class="devsite-nav-item"><a href="/articles/how-to-measure-speed" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/how-to-measure-speed" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/how-to-measure-speed" ><span class="devsite-nav-text" tooltip>How to measure speed?</span></a></li> <li class="devsite-nav-item"><a href="/articles/how-to-stay-fast" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/how-to-stay-fast" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/how-to-stay-fast" ><span class="devsite-nav-text" tooltip>How to stay fast?</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Core Web Vitals</span> </div></li> <li class="devsite-nav-item"><a href="/articles/vitals" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/vitals" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/vitals" ><span class="devsite-nav-text" tooltip>Web Vitals</span></a></li> <li class="devsite-nav-item"><a href="/articles/user-centric-performance-metrics" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/user-centric-performance-metrics" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/user-centric-performance-metrics" ><span class="devsite-nav-text" tooltip>User-centric performance metrics</span></a></li> <li class="devsite-nav-item"><a href="/articles/defining-core-web-vitals-thresholds" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/defining-core-web-vitals-thresholds" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/defining-core-web-vitals-thresholds" ><span class="devsite-nav-text" tooltip>Defining the Core Web Vitals metrics thresholds</span></a></li> <li class="devsite-nav-item"><a href="/articles/lcp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/lcp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/lcp" ><span class="devsite-nav-text" tooltip>Largest Contentful Paint (LCP)</span></a></li> <li class="devsite-nav-item"><a href="/articles/cls" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/cls" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/cls" ><span class="devsite-nav-text" tooltip>Cumulative Layout Shift (CLS)</span></a></li> <li class="devsite-nav-item"><a href="/articles/inp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/inp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/inp" ><span class="devsite-nav-text" tooltip>Interaction to Next Paint (INP)</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-lcp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-lcp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-lcp" ><span class="devsite-nav-text" tooltip>Optimize Largest Contentful Paint</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-cls" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-cls" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-cls" ><span class="devsite-nav-text" tooltip>Optimize Cumulative Layout Shift</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-inp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-inp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-inp" ><span class="devsite-nav-text" tooltip>Optimize Interaction to Next Paint</span></a></li> <li class="devsite-nav-item"><a href="/articles/top-cwv" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/top-cwv" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/top-cwv" ><span class="devsite-nav-text" tooltip>The most effective ways to improve Core Web Vitals</span></a></li> <li class="devsite-nav-item"><a href="/articles/vitals-tools" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/vitals-tools" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/vitals-tools" ><span class="devsite-nav-text" tooltip>Core Web Vitals workflows with Google tools</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-cwv-business" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-cwv-business" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-cwv-business" ><span class="devsite-nav-text" tooltip>Optimizing Core Web Vitals for business decision makers</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Measure performance in the field</span> </div></li> <li class="devsite-nav-item"><a href="/articles/chrome-ux-report" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/chrome-ux-report" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/chrome-ux-report" ><span class="devsite-nav-text" tooltip>Using the Chrome UX Report to look at performance in the field</span></a></li> <li class="devsite-nav-item"><a href="/articles/lab-and-field-data-differences" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/lab-and-field-data-differences" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/lab-and-field-data-differences" ><span class="devsite-nav-text" tooltip>Why lab and field data can be different (and what to do about it)</span></a></li> <li class="devsite-nav-item"><a href="/articles/crux-and-rum-differences" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/crux-and-rum-differences" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/crux-and-rum-differences" ><span class="devsite-nav-text" tooltip>Why is CrUX data different from my RUM data?</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize your resource delivery</span> </div></li> <li class="devsite-nav-item"><a href="/articles/optimize-ttfb" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-ttfb" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-ttfb" ><span class="devsite-nav-text" tooltip>Optimize Time to First Byte</span></a></li> <li class="devsite-nav-item"><a href="/articles/content-delivery-networks" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/content-delivery-networks" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/content-delivery-networks" ><span class="devsite-nav-text" tooltip>Content delivery networks (CDNs)</span></a></li> <li class="devsite-nav-item"><a href="/articles/prioritize-resources" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/prioritize-resources" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/prioritize-resources" ><span class="devsite-nav-text" tooltip>Prioritize resources</span></a></li> <li class="devsite-nav-item"><a href="/articles/preload-critical-assets" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/preload-critical-assets" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/preload-critical-assets" ><span class="devsite-nav-text" tooltip>Preload critical assets to improve loading speed</span></a></li> <li class="devsite-nav-item"><a href="/articles/preconnect-and-dns-prefetch" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/preconnect-and-dns-prefetch" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/preconnect-and-dns-prefetch" ><span class="devsite-nav-text" tooltip>Establish network connections early to improve perceived page speed</span></a></li> <li class="devsite-nav-item"><a href="/articles/link-prefetch" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/link-prefetch" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/link-prefetch" ><span class="devsite-nav-text" tooltip>Prefetch resources to speed up future navigations</span></a></li> <li class="devsite-nav-item"><a href="/articles/fast-playback-with-preload" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/fast-playback-with-preload" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/fast-playback-with-preload" ><span class="devsite-nav-text" tooltip>Fast playback with audio and video preload</span></a></li> <li class="devsite-nav-item"><a href="/articles/adaptive-serving-based-on-network-quality" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/adaptive-serving-based-on-network-quality" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/adaptive-serving-based-on-network-quality" ><span class="devsite-nav-text" tooltip>Adaptive serving based on network quality</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize your images</span> </div></li> <li class="devsite-nav-item"><a href="/articles/choose-the-right-image-format" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/choose-the-right-image-format" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/choose-the-right-image-format" ><span class="devsite-nav-text" tooltip>Choose the right image format</span></a></li> <li class="devsite-nav-item"><a href="/articles/compress-images" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/compress-images" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/compress-images" ><span class="devsite-nav-text" tooltip>Choose the correct level of compression</span></a></li> <li class="devsite-nav-item"><a href="/articles/use-imagemin-to-compress-images" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/use-imagemin-to-compress-images" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/use-imagemin-to-compress-images" ><span class="devsite-nav-text" tooltip>Use Imagemin to compress images</span></a></li> <li class="devsite-nav-item"><a href="/articles/replace-gifs-with-videos" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/replace-gifs-with-videos" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/replace-gifs-with-videos" ><span class="devsite-nav-text" tooltip>Replace animated GIFs with video for faster page loads</span></a></li> <li class="devsite-nav-item"><a href="/articles/serve-responsive-images" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/serve-responsive-images" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/serve-responsive-images" ><span class="devsite-nav-text" tooltip>Serve responsive images</span></a></li> <li class="devsite-nav-item"><a href="/articles/serve-images-with-correct-dimensions" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/serve-images-with-correct-dimensions" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/serve-images-with-correct-dimensions" ><span class="devsite-nav-text" tooltip>Serve images with correct dimensions</span></a></li> <li class="devsite-nav-item"><a href="/articles/serve-images-webp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/serve-images-webp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/serve-images-webp" ><span class="devsite-nav-text" tooltip>Use WebP images</span></a></li> <li class="devsite-nav-item"><a href="/articles/image-cdns" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/image-cdns" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/image-cdns" ><span class="devsite-nav-text" tooltip>Use image CDNs to optimize images</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Lazy-load images and video</span> </div></li> <li class="devsite-nav-item"><a href="/articles/browser-level-image-lazy-loading" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/browser-level-image-lazy-loading" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/browser-level-image-lazy-loading" ><span class="devsite-nav-text" tooltip>Browser-level image lazy loading for the web</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize web fonts</span> </div></li> <li class="devsite-nav-item"><a href="/articles/font-best-practices" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/font-best-practices" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/font-best-practices" ><span class="devsite-nav-text" tooltip>Best practices for fonts</span></a></li> <li class="devsite-nav-item"><a href="/articles/avoid-invisible-text" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/avoid-invisible-text" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/avoid-invisible-text" ><span class="devsite-nav-text" tooltip>Avoid invisible text during font loading</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-webfont-loading" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-webfont-loading" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-webfont-loading" ><span class="devsite-nav-text" tooltip>Optimize web font loading and rendering</span></a></li> <li class="devsite-nav-item"><a href="/articles/reduce-webfont-size" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/reduce-webfont-size" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/reduce-webfont-size" ><span class="devsite-nav-text" tooltip>Reduce web font size</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize your CSS</span> </div></li> <li class="devsite-nav-item"><a href="/articles/defer-non-critical-css" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/defer-non-critical-css" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/defer-non-critical-css" ><span class="devsite-nav-text" tooltip>Defer non-critical CSS</span></a></li> <li class="devsite-nav-item"><a href="/articles/minify-css" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/minify-css" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/minify-css" ><span class="devsite-nav-text" tooltip>Minify CSS</span></a></li> <li class="devsite-nav-item"><a href="/articles/extract-critical-css" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/extract-critical-css" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/extract-critical-css" ><span class="devsite-nav-text" tooltip>Extract critical CSS</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-css-background-images-with-media-queries" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-css-background-images-with-media-queries" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-css-background-images-with-media-queries" ><span class="devsite-nav-text" tooltip>Optimize CSS background images with media queries</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize your third-party resources</span> </div></li> <li class="devsite-nav-item"><a href="/articles/third-party-javascript" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/third-party-javascript" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/third-party-javascript" ><span class="devsite-nav-text" tooltip>Third-party JavaScript performance</span></a></li> <li class="devsite-nav-item"><a href="/articles/identify-slow-third-party-javascript" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/identify-slow-third-party-javascript" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/identify-slow-third-party-javascript" ><span class="devsite-nav-text" tooltip>Identify slow third-party JavaScript</span></a></li> <li class="devsite-nav-item"><a href="/articles/efficiently-load-third-party-javascript" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/efficiently-load-third-party-javascript" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/efficiently-load-third-party-javascript" ><span class="devsite-nav-text" tooltip>Efficiently load third-party JavaScript</span></a></li> <li class="devsite-nav-item"><a href="/articles/tag-best-practices" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/tag-best-practices" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/tag-best-practices" ><span class="devsite-nav-text" tooltip>Best practices for tags and tag managers</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Optimize your JavaScript</span> </div></li> <li class="devsite-nav-item"><a href="/articles/optimize-long-tasks" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-long-tasks" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-long-tasks" ><span class="devsite-nav-text" tooltip>Optimize long tasks</span></a></li> <li class="devsite-nav-item"><a href="/articles/optimize-inp" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/optimize-inp" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/optimize-inp" ><span class="devsite-nav-text" tooltip>Optimize Interaction to Next Paint</span></a></li> <li class="devsite-nav-item"><a href="/articles/apply-instant-loading-with-prpl" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/apply-instant-loading-with-prpl" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/apply-instant-loading-with-prpl" ><span class="devsite-nav-text" tooltip>Apply instant loading with the PRPL pattern</span></a></li> <li class="devsite-nav-item"><a href="/articles/reduce-javascript-payloads-with-code-splitting" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/reduce-javascript-payloads-with-code-splitting" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/reduce-javascript-payloads-with-code-splitting" ><span class="devsite-nav-text" tooltip>Reduce JavaScript payloads with code splitting</span></a></li> <li class="devsite-nav-item"><a href="/articles/remove-unused-code" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/remove-unused-code" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/remove-unused-code" ><span class="devsite-nav-text" tooltip>Remove unused code</span></a></li> <li class="devsite-nav-item"><a href="/articles/reduce-network-payloads-using-text-compression" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/reduce-network-payloads-using-text-compression" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/reduce-network-payloads-using-text-compression" ><span class="devsite-nav-text" tooltip>Minify and compress network payloads</span></a></li> <li class="devsite-nav-item"><a href="/articles/serve-modern-code-to-modern-browsers" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/serve-modern-code-to-modern-browsers" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/serve-modern-code-to-modern-browsers" ><span class="devsite-nav-text" tooltip>Serve modern code to modern browsers for faster page loads</span></a></li> <li class="devsite-nav-item"><a href="/articles/publish-modern-javascript" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/publish-modern-javascript" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/publish-modern-javascript" ><span class="devsite-nav-text" tooltip>Publish, ship, and install modern JavaScript for faster applications</span></a></li> <li class="devsite-nav-item"><a href="/articles/commonjs-larger-bundles" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/commonjs-larger-bundles" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/commonjs-larger-bundles" ><span class="devsite-nav-text" tooltip>How CommonJS is making your bundles larger</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Build a performance culture</span> </div></li> <li class="devsite-nav-item"><a href="/articles/value-of-speed" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/value-of-speed" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/value-of-speed" ><span class="devsite-nav-text" tooltip>The value of speed</span></a></li> <li class="devsite-nav-item"><a href="/articles/how-can-performance-improve-conversion" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/how-can-performance-improve-conversion" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/how-can-performance-improve-conversion" ><span class="devsite-nav-text" tooltip>How can performance improve conversion?</span></a></li> <li class="devsite-nav-item"><a href="/articles/what-should-you-measure-to-improve-performance" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/what-should-you-measure-to-improve-performance" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/what-should-you-measure-to-improve-performance" ><span class="devsite-nav-text" tooltip>What should you measure to improve performance?</span></a></li> <li class="devsite-nav-item"><a href="/articles/fixing-website-speed-cross-functionally" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/fixing-website-speed-cross-functionally" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/fixing-website-speed-cross-functionally" ><span class="devsite-nav-text" tooltip>Fixing website speed cross-functionally</span></a></li> <li class="devsite-nav-item"><a href="/articles/site-speed-and-business-metrics" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/site-speed-and-business-metrics" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/site-speed-and-business-metrics" ><span class="devsite-nav-text" tooltip>Relating site speed and business metrics</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Set performance budgets</span> </div></li> <li class="devsite-nav-item"><a href="/articles/performance-budgets-101" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/performance-budgets-101" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/performance-budgets-101" ><span class="devsite-nav-text" tooltip>Performance budgets 101</span></a></li> <li class="devsite-nav-item"><a href="/articles/your-first-performance-budget" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/your-first-performance-budget" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/your-first-performance-budget" ><span class="devsite-nav-text" tooltip>Your first performance budget</span></a></li> <li class="devsite-nav-item"><a href="/articles/incorporate-performance-budgets-into-your-build-tools" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/incorporate-performance-budgets-into-your-build-tools" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/incorporate-performance-budgets-into-your-build-tools" ><span class="devsite-nav-text" tooltip>Incorporate performance budgets into your build process</span></a></li> <li class="devsite-nav-item"><a href="/articles/use-lighthouse-for-performance-budgets" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/use-lighthouse-for-performance-budgets" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/use-lighthouse-for-performance-budgets" ><span class="devsite-nav-text" tooltip>Use Lighthouse for performance budgets</span></a></li> <li class="devsite-nav-item"><a href="/articles/using-bundlesize-with-travis-ci" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/using-bundlesize-with-travis-ci" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/using-bundlesize-with-travis-ci" ><span class="devsite-nav-text" tooltip>Using bundlesize with Travis CI</span></a></li> <li class="devsite-nav-item"><a href="/articles/using-lighthouse-bot-to-set-a-performance-budget" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/using-lighthouse-bot-to-set-a-performance-budget" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/using-lighthouse-bot-to-set-a-performance-budget" ><span class="devsite-nav-text" tooltip>Using Lighthouse Bot to set a performance budget</span></a></li> <li class="devsite-nav-item"><a href="/articles/lighthouse-ci" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /articles/lighthouse-ci" track-type="bookNav" track-name="click" track-metadata-eventdetail="/articles/lighthouse-ci" ><span class="devsite-nav-text" tooltip>Performance monitoring with Lighthouse CI</span></a></li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" has-book-nav has-sidebar > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars ></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://web.dev/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Home </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/articles" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Articles" > Articles </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/explore" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="" > Explore </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://web.dev/explore/fast" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="4" track-type="globalNav" track-name="breadcrumb" track-metadata-position="4" track-metadata-eventdetail="" > Fast load times </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <h1 class="devsite-page-title" tabindex="-1"> Optimize Cumulative Layout Shift </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <p>Learn how to avoid sudden layout shifts to improve user-experience</p> <p> <div class="wd-authors" translate="no"> <div class="wd-author"> <img class="devsite-landing-row-item-icon" alt="Addy Osmani" src="https://web.dev/images/authors/addyosmani.jpg" decoding="async" height="64" loading="lazy" width="64"> <div> <span> Addy Osmani </span> <div class="wd-author__links"> <a href="https://twitter.com/addyosmani" aria-label="Addy Osmani on X" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 300 271"> <title>X</title> <path fill="currentColor" 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"></path> </svg></a> <a href="https://github.com/addyosmani" aria-label="Addy Osmani on GitHub" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 32.6 31.8"> <title>GitHub</title> <path d="M16.3 0C7.3 0 0 7.3 0 16.3c0 7.2 4.7 13.3 11.1 15.5.8.1 1.1-.4 1.1-.8v-2.8c-4.5 1-5.5-2.2-5.5-2.2-.7-1.9-1.8-2.4-1.8-2.4-1.5-1 .1-1 .1-1 1.6.1 2.5 1.7 2.5 1.7 1.5 2.5 3.8 1.8 4.7 1.4.1-1.1.6-1.8 1-2.2-3.6-.4-7.4-1.8-7.4-8.1 0-1.8.6-3.2 1.7-4.4-.1-.3-.7-2 .2-4.2 0 0 1.4-.4 4.5 1.7 1.3-.4 2.7-.5 4.1-.5 1.4 0 2.8.2 4.1.5 3.1-2.1 4.5-1.7 4.5-1.7.9 2.2.3 3.9.2 4.3 1 1.1 1.7 2.6 1.7 4.4 0 6.3-3.8 7.6-7.4 8 .6.5 1.1 1.5 1.1 3V31c0 .4.3.9 1.1.8 6.5-2.2 11.1-8.3 11.1-15.5C32.6 7.3 25.3 0 16.3 0z" fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" /> </svg></a> </div> </div> </div> <div class="wd-author"> <img class="devsite-landing-row-item-icon" alt="Barry Pollard" src="https://web.dev/images/authors/tunetheweb.jpg" decoding="async" height="64" loading="lazy" width="64"> <div> <span> Barry Pollard </span> <div class="wd-author__links"> <a href="https://twitter.com/tunetheweb" aria-label="Barry Pollard on X" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 300 271"> <title>X</title> <path fill="currentColor" 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"></path> </svg></a> <a href="https://github.com/tunetheweb" aria-label="Barry Pollard on GitHub" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 32.6 31.8"> <title>GitHub</title> <path d="M16.3 0C7.3 0 0 7.3 0 16.3c0 7.2 4.7 13.3 11.1 15.5.8.1 1.1-.4 1.1-.8v-2.8c-4.5 1-5.5-2.2-5.5-2.2-.7-1.9-1.8-2.4-1.8-2.4-1.5-1 .1-1 .1-1 1.6.1 2.5 1.7 2.5 1.7 1.5 2.5 3.8 1.8 4.7 1.4.1-1.1.6-1.8 1-2.2-3.6-.4-7.4-1.8-7.4-8.1 0-1.8.6-3.2 1.7-4.4-.1-.3-.7-2 .2-4.2 0 0 1.4-.4 4.5 1.7 1.3-.4 2.7-.5 4.1-.5 1.4 0 2.8.2 4.1.5 3.1-2.1 4.5-1.7 4.5-1.7.9 2.2.3 3.9.2 4.3 1 1.1 1.7 2.6 1.7 4.4 0 6.3-3.8 7.6-7.4 8 .6.5 1.1 1.5 1.1 3V31c0 .4.3.9 1.1.8 6.5-2.2 11.1-8.3 11.1-15.5C32.6 7.3 25.3 0 16.3 0z" fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" /> </svg></a> <a href="https://webperf.social/@tunetheweb" aria-label="Barry Pollard on Mastodon" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 16 16"> <title>Mastodon</title> <path fill="currentColor" d="M 15.659 9.592 C 15.424 10.72 13.553 11.956 11.404 12.195 C 10.283 12.32 9.18 12.434 8.003 12.384 C 6.079 12.302 4.56 11.956 4.56 11.956 C 4.56 12.13 4.572 12.297 4.595 12.452 C 4.845 14.224 6.478 14.33 8.025 14.379 C 9.586 14.429 10.976 14.02 10.976 14.02 L 11.04 15.337 C 11.04 15.337 9.948 15.884 8.003 15.984 C 6.93 16.039 5.598 15.959 4.047 15.576 C 0.683 14.746 0.104 11.4 0.015 8.006 C -0.012 6.998 0.005 6.048 0.005 5.253 C 0.005 1.782 2.443 0.765 2.443 0.765 C 3.672 0.238 5.782 0.017 7.975 0 L 8.029 0 C 10.221 0.017 12.332 0.238 13.561 0.765 C 13.561 0.765 15.999 1.782 15.999 5.253 C 15.999 5.253 16.03 7.814 15.659 9.592 Z M 13.124 5.522 L 13.124 9.725 L 11.339 9.725 L 11.339 5.646 C 11.339 4.786 10.951 4.35 10.175 4.35 C 9.317 4.35 8.887 4.867 8.887 5.891 L 8.887 8.124 L 7.113 8.124 L 7.113 5.891 C 7.113 4.867 6.683 4.35 5.825 4.35 C 5.049 4.35 4.661 4.786 4.661 5.646 L 4.661 9.725 L 2.876 9.725 L 2.876 5.522 C 2.876 4.663 3.111 3.981 3.582 3.476 C 4.067 2.971 4.703 2.712 5.493 2.712 C 6.406 2.712 7.098 3.039 7.555 3.695 L 8 4.39 L 8.445 3.695 C 8.902 3.039 9.594 2.712 10.507 2.712 C 11.297 2.712 11.933 2.971 12.418 3.476 C 12.889 3.981 13.124 4.663 13.124 5.522 Z" style="stroke:none;stroke-miterlimit:10;fill-rule:evenodd;"></path> </svg></a> <a href="https://www.tunetheweb.com" aria-label="Barry Pollard's homepage" rel="me"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 30 30"> <title>Homepage</title> <circle cx="14.5" cy="14.5" r="13.5" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> <ellipse cx="14.5" cy="14.5" rx="6.1" ry="13.5" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> <path d="M1.6 9.6h25.8M1.6 19.4h25.8" stroke-width="2" stroke-miterlimit="10" fill="none" stroke="currentColor" /> </svg></a> </div> </div> </div> </div></p> <p><a href="/articles/cls">Cumulative Layout Shift (CLS)</a> is one of the three <a href="/articles/vitals#core_web_vitals">Core Web Vitals</a> metrics. It measures the instability of content by combining how much visible content has shifted in the viewport with the distance the affected elements moved.</p> <p>Layout shifts can be distracting to users. Imagine you&#39;ve started reading an article when all of a sudden elements shift around the page, throwing you off and requiring you to find your place again. This is very common on the web, including when reading the news, or trying to click those &#39;Search&#39; or &#39;Add to Cart&#39; buttons. Such experiences are visually jarring and frustrating. They&#39;re often caused when visible elements are forced to move because another element was suddenly added to the page or resized.</p> <p>To provide a good user experience, <strong>sites should strive to have a CLS of 0.1 or less for at least 75% of page visits.</strong></p> <figure> <picture> <source srcset="https://web.dev/static/articles/optimize-cls/image/good-cls-values.svg" media="(min-width: 640px)" width="800" height="200"> <img src="/static/articles/optimize-cls/image/good-cls-values-are-under-1ce942cb59c08.svg" alt="Good CLS values are under 0.1, poor values are greater than 0.25 and anything in between needs improvement" width="640" height="480"> </picture> <figcaption class="wd-caption"> Good CLS values are 0.1 or less. Poor values are greater than 0.25. </figcaption> </figure> <p>Unlike the other Core Web Vitals, which are time-based values measured in seconds or milliseconds, the CLS score is a unitless value based on a calculation of how much content is shifting and by how far.</p> <p>In this guide, we&#39;ll cover optimizing common causes of layout shifts.</p> <p>The most common causes of a poor CLS are:</p> <ul> <li>Images without dimensions.</li> <li>Ads, embeds, and iframes without dimensions.</li> <li>Dynamically injected content such as ads, embeds, and iframes without dimensions.</li> <li>Web fonts.</li> </ul> <aside class="note"> <p> <b>Note:</b> For a visual overview of some of the content presented in this guide, see the Optimize for Core Web Vitals video from Google I/O 2020: </p> <devsite-video video-id="AQqFZ5t8uNc"></devsite-video> </aside> <h2 id="causes" data-text="Understand the causes of layout shifts" tabindex="-1">Understand the causes of layout shifts</h2> <p>Before you start looking at solutions to common CLS issues, it&#39;s important to understand your CLS score and where the shifts are coming from.</p> <h3 id="lab-field" data-text="CLS in lab tools versus field" tabindex="-1">CLS in lab tools versus field</h3> <p>It is common to hear developers think the CLS measured by the <a href="https://developer.chrome.com/docs/crux">Chrome UX Report (CrUX)</a> is incorrect as it does not match the CLS they measure using Chrome DevTools or other lab tools. Web performance lab tools like Lighthouse may not show the full CLS of a page as they typically do a simple load of the page to measure some web performance metrics and provide some guidance (though <a href="/articles/lighthouse-user-flows">Lighthouse user flows</a> do allow you measure beyond the default page load audit).</p> <p>CrUX is the official dataset of the Web Vitals program, and for that, CLS is measured throughout the full life of the page and not just during the initial page load that lab tools typically measure.</p> <p>Layout shifts are very common during page load, as all the necessary resources are fetched to initially render the page, but layout shifts can also happen after the initial load. Many post-load shifts may occur <a href="/articles/cls#user-initiated_layout_shifts">as the result of a user interaction</a> and therefore will be excluded from the CLS score as they are <em>expected</em> shifts—as long as they occur within 500 milliseconds of that interaction.</p> <p>However, other post-load shifts that are unexpected by the user may be included where there was no qualifying interaction—for example, if you scroll further along the page and lazy-loaded content is loaded and that causes shifts. Other common causes of post-load CLS are on interactions of transitions, for example on Single Page Apps, which take longer than the 500 millisecond grace period.</p> <p><a href="https://pagespeed.web.dev/">PageSpeed Insights</a> shows both the user-perceived CLS from a URL in its &quot;Discover what your real users are experiencing&quot; section, and the lab-based load CLS in its &quot;Diagnose performance issues&quot; section. Differences between these values are likely the result of post-load CLS.</p> <figure> <img src="/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402.png" alt="Screenshot of PageSpeed Insights showing URL-level data highlighting the real user CLS which is considerably larger than the Lighthouse CLS" width="800" height="450" srcset="https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_36.png 36w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_48.png 48w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_72.png 72w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_96.png 96w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_480.png 480w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_720.png 720w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_856.png 856w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_960.png 960w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_1440.png 1440w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_1920.png 1920w,https://web.dev/static/articles/optimize-cls/image/screenshot-pagespeed-ins-1b9715cccc402_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> In this example, CrUX measures a much larger CLS than Lighthouse. </figcaption> </figure> <aside class="note"> <b>Note:</b> PageSpeed Insights will show URL-level data where it exists, and attempt to fall back to origin-level data where this does not exist. Always check what data is showing to ensure you don't waste time trying to track down a CLS issue that actually exists on other pages on your origin! In the earlier example, you can see this is URL-level data as shown in the top right of the image. </aside> <h3 id="identifying-load-cls-issues" data-text="Identify load CLS issues" tabindex="-1">Identify load CLS issues</h3> <p>When the CrUX and Lighthouse CLS scores of PageSpeed Insights are broadly aligned, this usually indicates there is a load CLS issue that was detected by Lighthouse. In this case Lighthouse will help with two audits to provide more information on images causing CLS due to missing width and height, and also list all the elements that shifted for the page load along with their CLS contribution. You can see these audits by filtering on the CLS audits:</p> <figure> <img src="/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b.png" alt="Lighthouse Screenshot showing the CLS audits providing more information to help you identify and address CLS issues" width="800" height="544" srcset="https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_36.png 36w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_48.png 48w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_72.png 72w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_96.png 96w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_480.png 480w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_720.png 720w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_856.png 856w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_960.png 960w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_1440.png 1440w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_1920.png 1920w,https://web.dev/static/articles/optimize-cls/image/lighthouse-screenshot-sho-1c6eeefdc4b1b_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> Lighthouse's detailed CLS diagnostics. </figcaption> </figure> <aside class="note"> <b>Note:</b> Lighthouse will identify the elements that were shifted, but often these are the ones <em>impacted</em> rather than the elements <em>causing</em> the CLS. For example, if a new element is inserted into the DOM, the elements that are beneath it will show in this audit, but the root cause is the addition of the new element above. However, the shifted element should be sufficient to help you identify and resolve the root cause. </aside> <p>The <a href="https://developer.chrome.com/docs/devtools/evaluate-performance">Performance panel</a> in DevTools also highlights layout shifts in the <strong>Experience</strong> section. The <strong>Summary</strong> view for a <code translate="no" dir="ltr">Layout Shift</code> record includes the cumulative layout shift score as well as a rectangle overlay showing the affected regions. This is particularly helpful to get more detail on load CLS issues since this is easily replicated with a reload performance profile.</p> <figure> <img src="/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25.jpg" alt="Layout Shift records being displayed in the Chrome DevTools performance panel when expanding the Experience section" width="800" height="438" srcset="https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_36.jpg 36w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_48.jpg 48w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_72.jpg 72w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_96.jpg 96w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_480.jpg 480w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_720.jpg 720w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_856.jpg 856w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_960.jpg 960w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_1440.jpg 1440w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_1920.jpg 1920w,https://web.dev/static/articles/optimize-cls/image/layout-shift-records-bein-90d4c6c924a25_2880.jpg 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> After recording a new trace in the Performance panel, the <b>Experience</b> section of the results is populated with a red-tinted bar displaying a <code translate="no" dir="ltr">Layout Shift</code> record. Clicking the record lets you drill down into impacted elements by showing details such as the "moved from" and "moved to" entries in this image. </figcaption> </figure> <h3 id="identifying-post-load-cls-issues" data-text="Identify post-load CLS issues" tabindex="-1">Identify post-load CLS issues</h3> <p>Disagreement between the CrUX and Lighthouse CLS scores often indicates post-load CLS. These shifts can be tricky to track down without field data. For information on collecting field data, see <a href="#measure-cls-in-field">Measure CLS elements in the field</a>.</p> <p>The <a href="https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma">Web Vitals Chrome extension</a> can be used to monitor CLS as you interact with a page, either in a heads up display, or in the console—where you can <a href="/articles/debug-cwvs-with-web-vitals-extension#cls_debug_information">get more details above the elements shifted</a>.</p> <p>As an alternative to using the extension, you can browse your web page while <a href="/articles/cls#measure_layout_shifts_in_javascript">recording layout shifts using a Performance Observer</a> pasted into the console.</p> <p>After you set up shift monitoring, you can try to replicate any post-load CLS issues. CLS often happens while the user scrolls through a page, when lazy-loaded content loads fully without space reserved for it. Content shifting when the user holds the pointer over it is another common post-load CLS cause. Any content shift during either of these interactions counts as unexpected, even if it happens within 500 milliseconds.</p> <p>For more information, see <a href="/articles/debug-layout-shifts">Debug layout shifts</a>.</p> <p>After you&#39;ve identified any common causes of CLS, the <a href="/articles/lighthouse-user-flows#timespans">timespans user flow mode of Lighthouse</a> can also be used to ensure typical user flows do not regress by introducing layout shifts.</p> <h3 id="measure-cls-in-field" data-text="Measure CLS elements in the field" tabindex="-1">Measure CLS elements in the field</h3> <p>Monitoring CLS in the field can be invaluable in determining what circumstances CLS happens in and narrowing down the possible causes. Like most lab tools, field tools measure only the elements that shifted, but that usually provides enough information to identify the cause. You can also use CLS field measurements to determine which issues are the highest priority to fix.</p> <p>The <code translate="no" dir="ltr">web-vitals</code> library has <a href="https://github.com/GoogleChrome/web-vitals#send-attribution-data">attribution functions</a> that let you collect this additional information. For more information, see <a href="/articles/debug-performance-in-the-field">Debug performance in the field</a>. Other RUM providers have also started collecting and presenting this data similarly.</p> <aside class="note"><b>Note: </b> RUM solutions that measure CLS in the field, including the <code translate="no" dir="ltr">web-vitals</code> library, may show differences that CrUX data as explained in the <a href="/articles/crux-and-rum-differences">Why is CrUX data different from my RUM data?</a> post. In particular, CLS that happens in iframes is not measurable from Web APIs but is visible to the user, and is therefore included in CrUX. So while field data can be invaluable for identifying CLS issues, be aware that it may be incomplete in certain scenarios. </aside> <h2 id="common-causes-of-cls" data-text="Common causes of CLS" tabindex="-1">Common causes of CLS</h2> <p>Once you have identified the causes of CLS, you can start working on fixing the issues. In this section we will show some of the more common reasons for CLS, and what you can do to avoid them.</p> <p><a name="images_without_dimensions"></a></p> <h3 id="images-without-dimensions" data-text="Images without dimensions" tabindex="-1">Images without dimensions</h3> <p>Always include <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> size attributes on your images and video elements. Alternatively, reserve the required space with <a href="/articles/aspect-ratio">CSS <code translate="no" dir="ltr">aspect-ratio</code></a> or similar. This approach ensures that the browser can allocate the correct amount of space in the document while the image is loading.</p> <figure> <video controls loop muted poster="https://web.dev/articles/optimize-cls/video/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/8wKRITUkK3Zrp5jvQ1Xw.jpg"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/10TEOBGBqZm1SEXE7KiC.webm" type="video/webm"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/WOQn6K6OQcoElRw0NCkZ.mp4" type="video/mp4"> </video> <figcaption class="wd-caption"> Images without width and height specified. </figcaption> </figure> <figure> <video controls loop muted poster="https://web.dev/articles/optimize-cls/video/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wm4VqJtKvove6qjiIjic.jpg"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/38UiHViz44OWqlKFe1VC.webm" type="video/webm"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/sFxDb36aEMvTPIyZHz1O.mp4" type="video/mp4"> </video> <figcaption class="wd-caption"> Images with width and height specified. </figcaption> </figure> <figure> <img src="/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37.png" alt="Lighthouse report showing the before/after impact to Cumulative Layout Shift after setting dimensions on images" width="800" height="148" srcset="https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_36.png 36w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_48.png 48w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_72.png 72w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_96.png 96w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_480.png 480w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_720.png 720w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_856.png 856w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_960.png 960w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_1440.png 1440w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_1920.png 1920w,https://web.dev/static/articles/optimize-cls/image/lighthouse-report-showing-9556bbb060b37_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> Lighthouse 6.0 impact of setting image dimensions on CLS. </figcaption> </figure> <h4 id="history_of_width_and_height_attributes_on_images" data-text="History of width and height attributes on images" tabindex="-1">History of <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> attributes on images</h4> <p>In the early days of the web, developers would add <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> attributes to their <code translate="no" dir="ltr">&lt;img&gt;</code> tags to ensure sufficient space was allocated on the page before the browser started fetching images. This would minimize reflow and re-layout.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="HTML"><code translate="no" dir="ltr">&lt;img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons"&gt; </code></pre></devsite-code> <p><code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> in this example don&#39;t include units. These &quot;pixel&quot; dimensions would ensure that the browser reserved a 640x360 area in the page&#39;s layout. The image would stretch to fit this space, regardless of whether the true dimensions matched it.</p> <p>When <a href="https://www.smashingmagazine.com/2011/01/guidelines-for-responsive-web-design/">Responsive Web Design</a> was introduced, developers began to omit <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> and started using CSS to resize images instead:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="CSS"><code translate="no" dir="ltr"><span class="devsite-syntax-nt">img</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">width</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-kt">%</span><span class="devsite-syntax-p">;</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-c">/* or max-width: 100%; */</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">height</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-kc">auto</span><span class="devsite-syntax-p">;</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <p>However, because the image size isn&#39;t specified, space can&#39;t be allocated for it until the browser starts to download it and can determine its dimensions. As images load, text shifts down the page to make room for them, creating a confusing and frustrating user experience.</p> <p>This is where aspect ratio comes in. The aspect ratio of an image is the ratio of its width to its height. It&#39;s common to see this expressed as two numbers separated by a colon (for example, 16:9 or 4:3). For an x:y aspect ratio, the image is x units wide and y units high.</p> <p>This means if we know one of the dimensions, the other can be determined. For a 16:9 aspect ratio:</p> <ul> <li>If puppy.jpg has a 360px height, width is 360 x (16 / 9) = 640px</li> <li>If puppy.jpg has a 640px width, height is 640 x (9 / 16) = 360px</li> </ul> <p>Knowing the aspect ratio for an image allows the browser to calculate and reserve sufficient space for the height and associated area.</p> <h4 id="modern_best_practice_for_setting_image_dimensions" data-text="Modern best practice for setting image dimensions" tabindex="-1">Modern best practice for setting image dimensions</h4> <p>Because modern browsers set the default aspect ratio of images based on an image&#39;s <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> attributes, you can prevent layout shifts by setting those attributes on the image and including the preceding CSS in your style sheet.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="HTML"><code translate="no" dir="ltr">&lt;!-- set a 640:360 i.e a 16:9 aspect ratio --&gt; &lt;img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons"&gt; </code></pre></devsite-code> <p>All browsers will then add a <a href="https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images">default aspect ratio</a> based on the element&#39;s existing <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> attributes.</p> <p>This calculates an aspect ratio based on the <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> attributes before the image has loaded. It provides this information at the very start of layout calculation. As soon as an image is told to be a certain width (for example <code translate="no" dir="ltr">width: 100%</code>), the aspect ratio is used to calculate the height.</p> <p>This <code translate="no" dir="ltr">aspect-ratio</code> value is calculated by major browsers as the HTML is processed, rather than with a default User Agent style sheet (see <a href="https://jakearchibald.com/2022/img-aspect-ratio/#width--height-presentational-hints">this post for a deep dive into why</a>), so the value is displayed a little differently. For example, Chrome displays it like this in the Styles section of the Element panel:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="CSS"><code translate="no" dir="ltr"><span class="devsite-syntax-nt">img</span><span class="devsite-syntax-o">[</span><span class="devsite-syntax-nt">Attributes</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nt">Style</span><span class="devsite-syntax-o">]</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">aspect-ratio</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-kc">auto</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mi">640</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">/</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mi">360</span><span class="devsite-syntax-p">;</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <p>Safari behaves similarly, using an <strong>HTML Attributes</strong> style source. Firefox doesn&#39;t display this calculated <code translate="no" dir="ltr">aspect-ratio</code> at all in its <strong>Inspector</strong> panel, but does use it for layout.</p> <p>The <code translate="no" dir="ltr">auto</code> part of the preceding code is important, because it causes the image dimensions to override the default aspect ratio after the image downloads. If the image dimensions are different, this still causes some layout shift after the image loads, but this ensures the image aspect ratio is still used when it becomes available, in case the HTML is incorrect. Even if the actual aspect ratio is different from the default, it still causes less layout shift than the 0x0 default size of an image with no dimensions provided.</p> <aside class="tip"><strong>Tip:</strong><span> If you&#39;re having a hard time understanding aspect ratio, a handy <a href="https://aspectratiocalculator.com/16-9.html">calculator</a> is available to help.</span></aside> <p>For a fantastic deep-dive into aspect ratio with further thinking around responsive images, see <a href="https://blog.logrocket.com/jank-free-page-loading-with-media-aspect-ratios/">jank-free page loading with media aspect ratios</a>.</p> <p>If your image is in a container, you can use CSS to resize the image to the width of the container. We set <code translate="no" dir="ltr">height: auto;</code> to avoid using a fixed value for the image height.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="CSS"><code translate="no" dir="ltr"><span class="devsite-syntax-nt">img</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">height</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-kc">auto</span><span class="devsite-syntax-p">;</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">width</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-kt">%</span><span class="devsite-syntax-p">;</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h4 id="responsive-images" data-text="What about responsive images?" tabindex="-1">What about responsive images?</h4> <p>When working with <a href="/articles/serve-responsive-images">responsive images</a>, <code translate="no" dir="ltr">srcset</code> defines the images you allow the browser to select between and what size each image is. To ensure <code translate="no" dir="ltr">&lt;img&gt;</code> width and height attributes can be set, each image should use the same aspect ratio.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="HTML"><code translate="no" dir="ltr">&lt;img width="1000" height="1000" src="puppy-1000.jpg" srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w" alt="Puppy with balloons" /&gt; </code></pre></devsite-code> <p>Your images&#39; aspect ratios can also change depending on your <a href="https://developer.mozilla.org/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction">art direction</a>. For example, you may want to include a cropped shot of an image for narrow viewports, and display the full image on desktop:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="HTML"><code translate="no" dir="ltr">&lt;picture&gt; &lt;source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" /&gt; &lt;source media="(min-width: 800px)" srcset="puppy-800w.jpg" /&gt; &lt;img src="puppy-800w.jpg" alt="Puppy with balloons" /&gt; &lt;/picture&gt; </code></pre></devsite-code> <p>Chrome, Firefox, and Safari now support setting <code translate="no" dir="ltr">width</code> and <code translate="no" dir="ltr">height</code> on the <code translate="no" dir="ltr">&lt;source&gt;</code> elements within a given <code translate="no" dir="ltr">&lt;picture&gt;</code> element:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="HTML"><code translate="no" dir="ltr">&lt;picture&gt; &lt;source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" width="480" height="400" /&gt; &lt;source media="(min-width: 800px)" srcset="puppy-800w.jpg" width="800" height="400" /&gt; &lt;img src="puppy-800w.jpg" alt="Puppy with balloons" width="800" height="400" /&gt; &lt;/picture&gt; </code></pre></devsite-code> <h3 id="late-loaded-content" data-text="Ads, embeds, and other late-loaded content" tabindex="-1">Ads, embeds, and other late-loaded content</h3> <p>Images aren&#39;t the only type of content that can cause layout shifts. Ads, embeds, iframes, and other dynamically injected content can all cause content appearing after them to shift down, increasing your CLS.</p> <p>Ads are one of the largest contributors to layout shifts on the web. Ad networks and publishers often support dynamic ad sizes. Ad sizes increase performance/revenue due to higher click rates and more ads competing in the auction. Unfortunately, this can lead to a suboptimal user experience due to ads pushing visible content you&#39;re viewing down the page.</p> <p>Embeddable widgets allow you to include portable web content on your page, such as videos from YouTube, maps from Google Maps, and social media posts. However, these widgets often aren&#39;t aware of how large their contents are before they load. As a result, platforms offering embeds don&#39;t always reserve space for their widgets, which causes layout shifts when they finally load.</p> <p>The techniques for dealing with these are all similar. The major differences are how much control you have over the content that will be inserted. If this is inserted by a third-party like an ad partner, you may not know the exact size of content that will be inserted, nor be able to control any layout shifts happening within those embeds.</p> <h4 id="reserve-space" data-text="Reserve space for late-loading content" tabindex="-1">Reserve space for late-loading content</h4> <p>When placing late-loading content in the content flow, layout shifts can be avoided by reserving the space for them in the initial layout.</p> <p>One approach is to add a <code translate="no" dir="ltr">min-height</code> CSS rule to reserve space or—for responsive content such as ads, for example—use the <a href="/articles/aspect-ratio"><code translate="no" dir="ltr">aspect-ratio</code></a> CSS property in a similar manner to the way browsers automatically use this for images with dimensions provided.</p> <figure> <img src="/static/articles/optimize-cls/image/three-mobile-devices-jus-4cbc1f88ecccb.svg" alt="Three mobile devices with just text content in the first device, this is shifted down in the second device, and reserving space with a placeholder as shown in the third device prevents the shift" width="1180" height="600"> <figcaption class="wd-caption"> Reserving space for ads can prevent layout shifts </figcaption> </figure> <p>You may need to account for subtle differences in ad or placeholder sizes across form factors using media queries.</p> <p>For content that may not have a fixed height, like ads, you might not be able to reserve the exact amount of space needed to eliminate the layout shift entirely. If a smaller ad is served, a publisher can style a larger container to avoid layout shifts, or choose the most likely size for the ad slot based on historical data. The downside to this approach is that it increases the amount of blank space on the page.</p> <p>You can instead set the initial size to the smallest size that will be used, and accept some level of shift for larger content. Using <code translate="no" dir="ltr">min-height</code>, as suggested previously, allows the parent element to grow as necessary while reducing the impact of layout shifts, compared to the 0px default size of an empty element.</p> <p>Try to avoid collapsing the reserved space by showing a placeholder if, for example, no ad is returned. Removing the space set aside for elements can cause just as much CLS as inserting content.</p> <h4 id="late-loading-lower" data-text="Place late-loading content lower in the viewport" tabindex="-1">Place late-loading content lower in the viewport</h4> <p>Dynamically injected content closer to the top of the viewport usually causes greater layout shifts than content injected lower in the viewport. However, injecting content anywhere in the viewport still causes some shift. If you can&#39;t reserve space for injected content, we recommend placing it later on the page to reduce the impact on its CLS.</p> <h4 id="avoid_inserting_new_content_without_a_user_interaction" data-text="Avoid inserting new content without a user interaction" tabindex="-1">Avoid inserting new content without a user interaction</h4> <p>You&#39;ve probably experienced layout shifts due to UI that pops-in at the top or bottom of the viewport when you&#39;re trying to load a site. Similar to ads, this often happens with banners and forms that shift the rest of the page&#39;s content:</p> <figure> <video controls loop muted poster="https://web.dev/articles/optimize-cls/video/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PF9ulVHDQOvoWendb6ea.jpg"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/LEicZ7zHqGFrXl67Olve.webm" type="video/webm"> <source src="/static/articles/optimize-cls/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/XFvOHc2OB8vUD9GbpL2w.mp4" type="video/mp4"> </video> <figcaption class="wd-caption"> Dynamic content without space reserved. </figcaption> </figure> <p>If you need to display these types of UI affordances, reserve sufficient space in the viewport for it in advance (for example, using a placeholder or skeleton UI) so that when it loads, it does not cause content in the page to surprisingly shift around. Alternatively, ensure the element is not part of the document flow by overlaying the content where this makes sense. See the <a href="/articles/cookie-notice-best-practices">Best practices for cookie notices</a> post for more recommendations on these types of components.</p> <p>In some cases adding content dynamically is an important part of user experience. For example, when loading more products to a list of items or when updating live feed content. There are several ways to avoid unexpected layout shifts in those cases:</p> <ul> <li>Replace the old content with the new content within a fixed size container or use a carousel and remove the old content after the transition. Remember to disable any links and controls until the transition has completed to prevent accidental clicks or taps while the new content is coming in.</li> <li>Have the user initiate the load of new content, so they are not surprised by the shift (for example with a &quot;Load more&quot; or &quot;Refresh&quot; button). It&#39;s recommended to prefetch the content before the user interaction so that it shows up immediately. As a reminder, <a href="/articles/cls#user-initiated_layout_shifts">layout shifts that occur within 500 milliseconds</a> of user input are not counted towards CLS.</li> <li>Seamlessly load the content offscreen and overlay a notice to the user that it&#39;s available (for example, with a &quot;Scroll up&quot; button).</li> </ul> <figure> <img src="/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94.png" alt="Examples of dynamic content loading without causing unexpected layout shifts from Twitter and the Chloé website" width="800" height="458" srcset="https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_36.png 36w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_48.png 48w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_72.png 72w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_96.png 96w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_480.png 480w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_720.png 720w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_856.png 856w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_960.png 960w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_1440.png 1440w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_1920.png 1920w,https://web.dev/static/articles/optimize-cls/image/examples-dynamic-content-4d11ddda2fa94_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"> <figcaption class="wd-caption"> Examples of dynamic content loading without causing unexpected layout shifts. Left: Live feed content loading on Twitter. Right: "Load More" example on Chloé website. Check out how the YNAP team <a href="https://medium.com/ynap-tech/how-to-optimize-for-cls-when-having-to-load-more-content-3f60f0cf561c">optimized for CLS when loading more content</a>. </figcaption> </figure> <aside class="note"> <b>Note:</b> If content is likely to take more than 500 milliseconds—for example it requires a network fetch—then reserving the expected space within that 500 millisecond timeframe and taking the impact of any future shift up front ensures any shifts won't be included in the CLS score. </aside> <h3 id="animation" data-text="Animations" tabindex="-1">Animations</h3> <p>Changes to CSS property values can require the browser to react to these changes. Some values, such as <code translate="no" dir="ltr">box-shadow</code> and <code translate="no" dir="ltr">box-sizing</code>, trigger re-layout, paint, and composite. Changing the <code translate="no" dir="ltr">top</code> and <code translate="no" dir="ltr">left</code> properties also cause layout shifts, even when the element being moved is on its own layer. Avoid animating using these properties.</p> <p>Other CSS properties can be changed without triggering re-layouts. These include using <code translate="no" dir="ltr">transform</code> animations to translate, scale, rotate, or skew elements.</p> <p>Composited animations using <code translate="no" dir="ltr">translate</code> can&#39;t impact other elements, and so don&#39;t count toward CLS. Non-composited animations also don&#39;t cause re-layout. To learn more about which CSS properties trigger layout shifts, see <a href="/articles/animations-guide">High-performance animations</a>.</p> <h3 id="web-fonts" data-text="Web fonts" tabindex="-1">Web fonts</h3> <p>Downloading and rendering web fonts is typically handled in one of two ways before the web font is downloaded:</p> <ul> <li>The fallback font is swapped with the web font, incurring a Flash of Unstyled Text (FOUT).</li> <li>&quot;Invisible&quot; text is displayed using the fallback font until a web font is available and the text is made visible (FOIT—flash of invisible text).</li> </ul> <p><strong>Both approaches can cause layout shifts</strong>. Even if the text is invisible, it&#39;s still laid out using the fallback font, so when the web font loads, the text block and the surrounding content shift in the same way as for the visible font.</p> <p>The following tools can help you minimize shifting of text:</p> <ul> <li><code translate="no" dir="ltr">font-display: optional</code> can avoid a re-layout as the web font is only used if it is available by the time of initial layout.</li> <li>Ensure the appropriate fallback font is used. For example, using <code translate="no" dir="ltr">font-family: &quot;Google Sans&quot;, sans-serif;</code> will ensure the browser&#39;s <code translate="no" dir="ltr">sans-serif</code> fallback font is used while <code translate="no" dir="ltr">&quot;Google Sans&quot;</code> is loaded. Not specifying a fallback font using just <code translate="no" dir="ltr">font-family: &quot;Google Sans&quot;</code> will mean the default font is used, which on Chrome is &quot;Times&quot;—a serif font which is a worse match than the default <code translate="no" dir="ltr">sans-serif</code> font.</li> <li>Minimize the size differences between the fallback font and the web font using the new <code translate="no" dir="ltr">size-adjust</code>, <code translate="no" dir="ltr">ascent-override</code>, <code translate="no" dir="ltr">descent-override</code>, and <code translate="no" dir="ltr">line-gap-override</code> APIs as detailed in the <a href="https://developer.chrome.com/blog/font-fallbacks">Improved font fallbacks</a> post.</li> <li>The <a href="/articles/optimize-webfont-loading#the_font_loading_api">Font Loading API</a> can reduce the time it takes to get necessary fonts.</li> <li>Load critical web fonts as early as possible using <code translate="no" dir="ltr">&lt;link rel=preload&gt;</code>. A preloaded font will have a higher chance to meet the first paint, in which case there&#39;s no layout shifting.</li> </ul> <p>Read <a href="/articles/font-best-practices">Best practices for fonts</a> for other font best practices.</p> <h2 id="reduce_cls_by_ensuring_pages_are_eligible_for_the_bfcache" data-text="Reduce CLS by ensuring pages are eligible for the bfcache" tabindex="-1">Reduce CLS by ensuring pages are eligible for the bfcache</h2> <p>A highly effective technique for keeping CLS scores low is to ensure your web pages are eligible for the <a href="/articles/bfcache">back/forward cache</a> (bfcache).</p> <p>The bfcache keeps pages in browsers memory for a short period after you navigate away so if you return to them, then they will be restored exactly as you left them. This means the fully loaded page is instantly available—without any shifts which may be normally seen during load due to any of the reasons given earlier.</p> <p>While this does potentially still mean the initial page load encounters layout shifts, when a user goes back through pages they are not seeing the same layout shifts repeatedly. You should always aim to avoid the shifts even on the initial load, but where that is more tricky to resolve fully, you can at least reduce the impact by avoiding them on any bfcache navigations.</p> <p>Back and forward navigations are common on many sites. For example, returning to a contents page, or a category page, or search results.</p> <p>When this <a href="https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/speed/metrics_changelog/2022_01_bfcache.md">was rolled out to Chrome</a>, we saw <a href="https://developer.chrome.com/docs/crux/release-notes#202201">noticeable improvements in CLS</a>.</p> <p>The bfcache is used by default by all browsers, but some sites are ineligible for the bfcache due to a variety of reasons. Read <a href="/articles/bfcache">the bfcache guide</a> for more details on how to test and identify any issues preventing bfcache usage to ensure you are making full use of this feature to help your overall CLS score for your site.</p> <h2 id="conclusion" data-text="Conclusion" tabindex="-1">Conclusion</h2> <p>There are a number of techniques to identify and improve CLS as detailed earlier in this guide. There are allowances built into Core Web Vitals, so even if you cannot eliminate CLS completely, using some of these techniques should allow you to reduce the impact. This will hopefully allow you to stay within those limits, creating a better experience for your website&#39;s users.</p> </div> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> <p>Last updated 2023-05-04 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2023-05-04 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox wd-footer-promo"> <h3 class="devsite-footer-linkbox-heading no-link">web.dev</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <h3 class="devsite-footer-linkbox-heading no-link"> web.dev </h3> <div class="devsite-footer-linkbox-description">We want to help you build beautiful, accessible, fast, and secure websites that work cross-browser, and for all of your users. This site is our home for content to help you on that journey, written by members of the Chrome team, and external experts.</div> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Contribute</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://issuetracker.google.com/issues/new?component=1400680&amp;template=1857359" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > File a bug </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://issuetracker.google.com/issues?q=status:open%20componentid:1400680&amp;s=created_time:desc" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > See open issues </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Related Content</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://developer.chrome.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Chrome for Developers </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://blog.chromium.org/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Chromium updates </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/case-studies" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Case studies </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/shows" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Podcasts &amp; shows </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Follow</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://twitter.com/ChromiumDev" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > @ChromiumDev on X </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.youtube.com/user/ChromeDevelopers" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > YouTube </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.linkedin.com/showcase/chrome-for-developers" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Chrome for Developers on LinkedIn </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/static/blog/feed.xml" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > RSS </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/terms" data-category="Site-Wide Custom Events" data-label="Footer Terms link" > Terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{&#34;at&#34;: &#34;True&#34;, &#34;ga4&#34;: [], &#34;ga4p&#34;: [], &#34;gtm&#34;: [{&#34;id&#34;: &#34;GTM-MZWCJPP&#34;, &#34;purpose&#34;: 0}], &#34;parameters&#34;: {&#34;internalUser&#34;: &#34;False&#34;, &#34;language&#34;: {&#34;machineTranslated&#34;: &#34;False&#34;, &#34;requested&#34;: &#34;en&#34;, &#34;served&#34;: &#34;en&#34;}, &#34;pageType&#34;: &#34;article&#34;, &#34;projectName&#34;: &#34;Articles&#34;, &#34;signedIn&#34;: &#34;False&#34;, &#34;tenant&#34;: &#34;web&#34;, &#34;recommendations&#34;: {&#34;sourcePage&#34;: &#34;&#34;, &#34;sourceType&#34;: 0, &#34;sourceRank&#34;: 0, &#34;sourceIdenticalDescriptions&#34;: 0, &#34;sourceTitleWords&#34;: 0, &#34;sourceDescriptionWords&#34;: 0, &#34;experiment&#34;: &#34;&#34;}, &#34;experiment&#34;: {&#34;ids&#34;: &#34;&#34;}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <script nonce="3hhLwuX7Vbi8C06Ibb63eHVjZ7QKfC"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/js/app_loader.js', '[27,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web","https://web-dot-devsite-v2-prod-3p.appspot.com",1,null,["/_pwa/web/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/favicon.png","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/web/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyCNm9YxQumEXwGJgTDjxoxXK6m1F-9720Q","AIzaSyCc76DZePGtoyUjqKrLdsMGk_ry7sljLbY","web.dev","AIzaSyB9bqgQ2t11WJsOX8qNsCQ6U-w91mmqF-I","AIzaSyAdYnStPdzjcJJtQ0mvIaeaMKj7_t6J_Fg",null,null,null,["MiscFeatureFlags__enable_explain_this_code","Cloud__enable_cloud_shell_fte_user_flow","Concierge__enable_pushui","Profiles__enable_awarding_url","Cloud__enable_cloud_facet_chat","Cloud__enable_cloud_dlp_service","Cloud__enable_cloud_shell","CloudShell__cloud_code_overflow_menu","MiscFeatureFlags__enable_view_transitions","Profiles__enable_completecodelab_endpoint","DevPro__enable_developer_subscriptions","Search__enable_suggestions_from_borg","DevPro__enable_cloud_innovators_plus","Profiles__enable_recognition_badges","MiscFeatureFlags__enable_variable_operator","EngEduTelemetry__enable_engedu_telemetry","TpcFeatures__enable_required_headers","MiscFeatureFlags__enable_firebase_utm","MiscFeatureFlags__enable_project_variables","OnSwitch__enable","MiscFeatureFlags__emergency_css","Profiles__enable_developer_profiles_callout","CloudShell__cloud_shell_button","Search__enable_ai_eligibility_checks","Cloud__enable_llm_concierge_chat","MiscFeatureFlags__developers_footer_dark_image","Cloud__enable_free_trial_server_call","TpcFeatures__enable_mirror_tenant_redirects","Profiles__require_profile_eligibility_for_signin","Experiments__reqs_query_experiments","Cloud__enable_legacy_calculator_redirect","Profiles__enable_profile_collections","Profiles__enable_release_notes_notifications","Search__enable_dynamic_content_confidential_banner","Profiles__enable_page_saving","Profiles__enable_dashboard_curated_recommendations","Analytics__enable_clearcut_logging","Cloud__enable_cloudx_experiment_ids","Search__enable_page_map","MiscFeatureFlags__developers_footer_image","BookNav__enable_tenant_cache_key","Profiles__enable_public_developer_profiles","Profiles__enable_complete_playlist_endpoint","Cloud__enable_cloudx_ping"],null,null,"AIzaSyA58TaKli1DculwmAmbpzLVGuWc8eCQgQc","https://developerscontentserving-pa.googleapis.com","AIzaSyDWBU60w0P9hEkr29kkksYs8Z7gvZ8u_wc","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[27,"web","web.dev","web.dev",null,"web-dot-devsite-v2-prod-3p.appspot.com",null,null,[null,null,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],null,null,null,null,[1,null,1],[1,1,null,1,1]],null,[38,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,1,1,null,null,null,null,null,null,null,null,2,null,null,null,"/images/lockup-dark-theme.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],[1,1]],[[null,null,null,null,null,["GTM-MZWCJPP"],null,null,null,null,null,[["GTM-MZWCJPP",1]],1]],null,4]]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>

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