<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>web.dev</title>
  <subtitle>Let&#39;s build the future of the web.</subtitle>
  <link href="https://web.dev/feed.xml" rel="self"/>
  <link href="https://web.dev"/>
  <updated>2026-04-15T23:21:06Z</updated>
  <id>https://web.dev/</id>
  <author>
    <name>Google Developers</name>
  </author>
  <icon>https://web.dev/images/social.png</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  
    
    
    <entry>
      <title>New to the web platform in September</title>
      <link href="https://web.dev/web-platform-09-2023/"/>
      <updated>2023-10-02T00:00:00Z</updated>
      <id>https://web.dev/web-platform-09-2023/</id>
      <content type="html" mode="escaped">&lt;h2 id=&quot;stable-browser-releases&quot;&gt;Stable browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-09-2023/#stable-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In September 2023 &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/118&quot; rel=&quot;noopener&quot;&gt;Firefox 118&lt;/a&gt;, &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 17&lt;/a&gt;, and &lt;a href=&quot;https://developer.chrome.com/blog/new-in-chrome-117/&quot; rel=&quot;noopener&quot;&gt;Chrome 117&lt;/a&gt; became stable. This post takes a look at what that means for the web platform.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; We include browser compatibility data pulled from MDN in these posts which may not have been updated yet for very recent browser releases. The post will show the correct information as soon as it appears in the &lt;a href=&quot;https://github.com/mdn/browser-compat-data/releases&quot;&gt;browser-compat-data release&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The &lt;code&gt;subgrid&lt;/code&gt; value for &lt;code&gt;grid-template-columns&lt;/code&gt; and &lt;code&gt;grid-template-rows&lt;/code&gt; is included in Chrome 117, making this longed for feature interoperable. You can learn more about subgrid in the article &lt;a href=&quot;https://web.dev/css-subgrid/&quot;&gt;CSS subgrid&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 114, Behind a flag&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox 71, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
71
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 114, Behind a flag&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 16, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
16
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Subgrid#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Chrome also includes three new CSS features to easily add entry and exit animations, and smoothly animate to and from the top layer dismissible elements such as dialogs and popovers. You can learn about the &lt;code&gt;transition-behavior&lt;/code&gt; property, &lt;code&gt;@starting-style&lt;/code&gt; rule, and &lt;code&gt;overlay&lt;/code&gt; property in the article &lt;a href=&quot;https://developer.chrome.com/blog/entry-exit-animations/&quot; rel=&quot;noopener&quot;&gt;Four new CSS features for entry and exit animations&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Also in Chrome 117 is JavaScript array grouping with the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy&quot; rel=&quot;noopener&quot;&gt;Object.groupBy&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy&quot; rel=&quot;noopener&quot;&gt;Map.groupBy&lt;/a&gt; static methods.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Safari 17 includes the &lt;code&gt;popover&lt;/code&gt; attribute, to add support for the &lt;a href=&quot;https://developer.chrome.com/blog/introducing-popover-api/&quot; rel=&quot;noopener&quot;&gt;Popover API&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Safari 17 and Firefox 118 include the HTML &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Element/search&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;&amp;lt;search&amp;gt;&lt;/code&gt;&lt;/a&gt; element. This element represents the parts of the page or application that contain funtionality for search or filtering content.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTML/Element/search#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;There are lots of new CSS features included in Safari 17, including &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@counter-style&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;@counter-style&lt;/code&gt;&lt;/a&gt;. This rule lets you define counter styles that are outside the predefined list of style. This feature is now available in all three engines.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 91, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      91
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 33, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      33
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 91, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      91
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 17, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      17
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/@counter-style#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Firefox 118 includes several additional CSS math functions: &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;sign()&lt;/code&gt;, &lt;code&gt;round()&lt;/code&gt;, &lt;code&gt;mod()&lt;/code&gt;, &lt;code&gt;rem()&lt;/code&gt;, &lt;code&gt;pow()&lt;/code&gt;, &lt;code&gt;sqrt()&lt;/code&gt;, &lt;code&gt;hypot()&lt;/code&gt;, &lt;code&gt;log()&lt;/code&gt;, and &lt;code&gt;exp()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox 112, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
112
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 15.4, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
15.4
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/exp#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Safari 17 also includes support for HEIC/HEIF images, and JPEG XL.&lt;/p&gt;
&lt;h2 id=&quot;beta-browser-releases&quot;&gt;Beta browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-09-2023/#beta-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beta browser versions give you a preview of things that will be in the next stable version of the browser. It&#39;s a great time to test new features, or removals, that could impact your site before the world gets that release. New betas are &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/119&quot; rel=&quot;noopener&quot;&gt;Firefox 119&lt;/a&gt;, &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-17_1-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 17.1&lt;/a&gt;, and &lt;a href=&quot;https://developer.chrome.com/blog/chrome-118-beta/&quot; rel=&quot;noopener&quot;&gt;Chrome 118&lt;/a&gt;. These releases bring many great features to the platform. Check out the release notes for all of the details, here are just a few highlights.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;search&amp;gt;&lt;/code&gt; element, shipping in Firefox and Safari this month is included in Chrome 118, meaning this feature is quickly landing across all three engines.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy&quot; rel=&quot;noopener&quot;&gt;Object.groupBy&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy&quot; rel=&quot;noopener&quot;&gt;Map.groupBy&lt;/a&gt; static methods are part of Firefox 119.&lt;/p&gt;
&lt;p&gt;Chrome 118 includes &lt;a href=&quot;https://drafts.csswg.org/css-cascade-6/#scoped-styles&quot; rel=&quot;noopener&quot;&gt;CSS scoped styles&lt;/a&gt; with the &lt;code&gt;@scope&lt;/code&gt; rule and new media features with &lt;code&gt;prefers-reduced-transparency&lt;/code&gt; and &lt;code&gt;scripting&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Safari 17.1 is currently a release that fixes a range of issues across the platform.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@charlesdeluvio&quot; rel=&quot;noopener&quot;&gt;Charles Deluvio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Effectively loading ads without impacting page speed</title>
      <link href="https://web.dev/loading-ads-page-speed/"/>
      <updated>2023-09-29T00:00:00Z</updated>
      <id>https://web.dev/loading-ads-page-speed/</id>
      <content type="html" mode="escaped">&lt;p&gt;Websites heavily rely on online advertising as a primary source of revenue. However, the presence of ads on websites can sometimes come at the expense of user experience and overall page performance. It&#39;s therefore vital to strike a balance between monetization and performance for website owners and advertisers, and the user experience.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;330&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot; width=&quot;660&quot; style=&quot;--vid-width: 660; --vid-height: 330&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/wV8j1X6xN0L6rYVmtOaY.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;/figure&gt;
&lt;p&gt;Consider a website that extensively places ads within its content, aiming to generate high revenue. However, the overwhelming number of ads frustrates users, leading to a poor user experience and high bounce rates. Despite the potential for substantial revenue from ads, abandonment severely hampers the website&#39;s success.&lt;/p&gt;
&lt;p&gt;On the other end of the spectrum, consider a website with no ads. This ad-free environment attracts a significant number of users due to its fast loading time and seamless browsing experience. However, without a monetization strategy in place, the website struggles to generate revenue, which may hinder its long-term sustainability and growth.&lt;/p&gt;
&lt;p&gt;Both scenarios illustrate the importance of balancing monetization, users and performance.&lt;/p&gt;
&lt;h2 id=&quot;harnessing-core-web-vitals&quot;&gt;Harnessing Core Web Vitals &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#harnessing-core-web-vitals&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Passing &lt;a href=&quot;https://web.dev/web-vitals/&quot;&gt;the Core Web Vitals&lt;/a&gt; is essential when it comes to loading ads without negatively impacting page speed. Core Web Vitals, comprising metrics such as &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt;, &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt;, and &lt;a href=&quot;https://web.dev/fid/&quot;&gt;First Input Delay (FID)&lt;/a&gt; (as well as the upcoming &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP) Core Web Vital metric&lt;/a&gt; slated to replace FID), are user experience metrics that measure the quality of the user experience of your website.&lt;/p&gt;
&lt;h3 id=&quot;largest-contentful-paint-lcp&quot;&gt;Largest Contentful Paint (LCP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#largest-contentful-paint-lcp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Focusing on optimizing LCP is vital, as this metric measures the time it takes for the largest contentful element to become visible within the viewport. By minimizing the loading time of ad content and by prioritizing asynchronous loading techniques, website owners can reduce LCP and decrease rendering time of the most prominent contentful elements on a page.&lt;/p&gt;
&lt;h3 id=&quot;first-input-delay-fid-and-interaction-to-next-paint-inp&quot;&gt;First Input Delay (FID) and Interaction to Next Paint (INP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#first-input-delay-fid-and-interaction-to-next-paint-inp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Secondly, &lt;a href=&quot;https://web.dev/how-to-optimize-inp/&quot;&gt;improving INP&lt;/a&gt; (and by extension, &lt;a href=&quot;https://web.dev/optimize-fid/&quot;&gt;optimizing FID&lt;/a&gt;) is crucial for interactivity. FID measures the time it takes for the browser to respond to the first user interaction, such as a click or tap. The INP metric, slated to replace FID in March of 2024, goes much further by measuring a page&#39;s overall ability to process all click, keyboard, and tap interactions throughout the page lifecycle.&lt;/p&gt;
&lt;p&gt;Ads that delay user interactions negatively impact INP and FID. This may frustrate users by creating experiences that feel sluggish, or even altogether broken in extreme cases. Implementing lazy loading for ads and deferring non-critical JavaScript execution can help reduce page INP and FID, and therefore improve overall page responsiveness.&lt;/p&gt;
&lt;h3 id=&quot;cumulative-layout-shift-cls&quot;&gt;Cumulative Layout Shift (CLS) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#cumulative-layout-shift-cls&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lastly, CLS measures a page&#39;s visual stability by measuring the amount of unexpected layout shifts that occur during page load. Ads that dynamically load or resize can result in layout instability, leading to a poor user experiences where users either lose track of where they are on a page, or even unintentionally tap on the wrong elements due to unexpected layout shifts. To mitigate this, website owners should &lt;a href=&quot;https://web.dev/optimize-cls/&quot;&gt;optimize CLS&lt;/a&gt; to ensure that ads have reserved space to prevent layout shifts, and ad sizes should be optimized to avoid sudden content reflows.&lt;/p&gt;
&lt;h2 id=&quot;structuring-your-webpage-into-distinct-content-blocks&quot;&gt;Structuring your webpage into distinct content blocks &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#structuring-your-webpage-into-distinct-content-blocks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Structuring your web page with content blocks for both text, image, and ad content, while also using &lt;a href=&quot;https://web.dev/content-visibility/&quot;&gt;the CSS &lt;code&gt;content-visibility:&lt;/code&gt; property&lt;/a&gt;, can significantly improve overall rendering time in modern browsers.&lt;/p&gt;
&lt;p&gt;By strategically applying the &lt;code&gt;content-visibility:&lt;/code&gt; property within these content blocks, you optimize the rendering process for text, image, and ad content. This ensures that only the content currently in the viewport is fully rendered, resulting in a faster initial page load and smoother user interactions. This performance enhancement is particularly valuable when dealing with lengthy or pages with many ads.&lt;/p&gt;
&lt;h2 id=&quot;prioritize-important-ad-slots&quot;&gt;Prioritize important ad slots &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#prioritize-important-ad-slots&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;500&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot; width=&quot;660&quot; style=&quot;--vid-width: 660; --vid-height: 500&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RswuozE5OAer8BMfvoUQ.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;/figure&gt;
&lt;p&gt;Not all ad slots are equal. For example, above-the-fold ad slots are usually more valuable than those that are below the fold in terms of viewability and monetization. This is because above-the-fold ads are more likely to be seen by users, as they are visible without scrolling in the first viewport. Below-the-fold ads become visible after the user scrolls down the page far enough to see them.&lt;/p&gt;
&lt;h3 id=&quot;above-the-fold-ads&quot;&gt;Above the fold ads &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#above-the-fold-ads&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A visual representation of the &amp;#x27;above-the-fold&amp;#x27; ad concept.&quot; decoding=&quot;async&quot; height=&quot;500&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 660px) 660px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/KaYluIMHNvotxWL9c2y0.png?auto=format&amp;w=1320 1320w&quot; width=&quot;660&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Above the fold ad slots refer to the portion of a webpage that is visible without scrolling, and hold significant value in digital advertising. These prime placements are considered valuable for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Advertisements placed above the fold are immediately visible for users upon loading a webpage. Users are more likely to notice and engage with these ads, resulting in higher click-through rates.&lt;/li&gt;
&lt;li&gt;Advertisers often consider the top portion of a webpage as the most valuable real estate. It&#39;s the first impression users get when they visit a site, making it a crucial area for showcasing high-impact and premium ads.&lt;/li&gt;
&lt;li&gt;Ads above the fold have the highest viewability rates because they are in the user&#39;s direct line of sight. This ensures that the majority of users who visit the page will see these ads without having to scroll down.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, it&#39;s important to strike a balance between monetization and the user experience when utilizing above the fold ad slots in the initial view. Here are some key considerations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First screen ad slots should load as fast as possible in the user&#39;s initial viewport. Slow-loading ads can negatively impact user experience and increase bounce rates. Optimizing ad load times is crucial to maintain a smooth user and browsing experience.&lt;/li&gt;
&lt;li&gt;While above the fold ad placements are valuable, it&#39;s important to not overload this prime space with too many ads. Excessive ads clutter the page, disrupt content readability, and detract from the user experience. Strive for a balance between monetization and maintaining a clean, user-friendly layout.&lt;/li&gt;
&lt;li&gt;Ensure above the fold ad slots are compatible with different screen sizes and devices. &lt;a href=&quot;https://web.dev/learn/design/&quot;&gt;Responsive design practices&lt;/a&gt; can help maintain a consistent and visually appealing layout regardless of the user&#39;s screen size.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;below-the-fold-ads&quot;&gt;Below the fold ads &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#below-the-fold-ads&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A visual representation of the &amp;#x27;below-the-fold&amp;#x27; ad concept.&quot; decoding=&quot;async&quot; height=&quot;500&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 660px) 660px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6deTpSz4wdfubdlPV9rc.png?auto=format&amp;w=1320 1320w&quot; width=&quot;660&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Below the fold ad slots—that is, ads placed within the portion of a webpage that becomes visible only after scrolling down—also hold considerable value in the world of digital advertising. These placements offer unique advantages that complement above the fold placements.&lt;/p&gt;
&lt;p&gt;Ads located below the fold benefit from users who scroll down to explore more content. These placements capture the attention of engaged users who are actively seeking additional information, making them valuable for brands looking to convey more complex messages or storytelling.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ad slots which are not initially visible can align with the content next to them, providing an opportunity for contextual relevance. This alignment can lead to higher user engagement as users discover ads that are related to the content they are exploring.&lt;/li&gt;
&lt;li&gt;When designed thoughtfully, below the fold ads can seamlessly integrate with the surrounding content, appearing less disruptive to users. This integration—also known as &lt;a href=&quot;https://support.google.com/admanager/answer/6366845?hl=en&quot; rel=&quot;noopener&quot;&gt;native advertising&lt;/a&gt;—can result in a more harmonious user experience.&lt;/li&gt;
&lt;li&gt;Scroll required ad placements offer more creative design and format flexibility, with ample space and freedom to experiment. Video ads, interactive elements, and larger images can be lazy loaded to capture user attention without disrupting their experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, the following considerations should be given for below the fold ad placements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;While below the fold ad placements can be effective, it&#39;s essential to ensure that users are encouraged to scroll down. Implementing visual cues or content teasers can entice users to explore further, increasing the likelihood of ad visibility.&lt;/li&gt;
&lt;li&gt;The placements of ads below the fold should not compromise content quality or readability. Maintaining a balance between ads and content to avoid overwhelming users and to ensure positive user experience.&lt;/li&gt;
&lt;li&gt;Unlike above the fold ad placements, below the fold ads may not need to load immediately. Delaying the loading of these ads until they are close to entering the user&#39;s viewport can help improve overall page load speed and reduce initial page rendering times.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When used strategically, below the fold ads can complement above the fold ads, and provide a platform for creative ad formats and contextual relevance. However, optimizing visibility, balancing content, and managing ad load timing are key considerations to ensure a positive user experience.&lt;/p&gt;
&lt;p&gt;Current Google Publisher Tag (GPT) best practices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/publisher-tag/guides/general-best-practices&quot; rel=&quot;noopener&quot;&gt;General best practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/publisher-tag/guides/ad-best-practices&quot; rel=&quot;noopener&quot;&gt;Ad Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/publisher-tag/guides/minimize-layout-shift&quot; rel=&quot;noopener&quot;&gt;Minimize layout shift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/publisher-tag/guides/monitor-performance&quot; rel=&quot;noopener&quot;&gt;Monitor performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/publisher-tag/common_implementation_mistakes&quot; rel=&quot;noopener&quot;&gt;Avoiding common implementation mistakes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;lazy-load-ads-where-appropriate&quot;&gt;Lazy load ads where appropriate &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#lazy-load-ads-where-appropriate&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A visualization of lazy loading versus not lazy loading resources. When resources are lazy loaded, bandwidth is conserved during page load, and resources are deferred to the point at which the user is likeliest to see them.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/mqnHutBAvzdSUQBensax.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/lazy-loading-best-practices/&quot;&gt;Lazy loading&lt;/a&gt; is a technique that defers loading non-critical resources until they are needed. Applying lazy loading for ads which are not immediately visible (that is, below-the-fold ads) ensures that they are only loaded when they come into view, conserving bandwidth and improving overall page speed. Browsers now include &lt;a href=&quot;https://web.dev/iframe-lazy-loading/&quot;&gt;native lazy loading for iframes&lt;/a&gt; with a simple &lt;code&gt;loading=lazy&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;By implementing lazy loading, ads are fetched dynamically when they are about to enter the user&#39;s viewport, reducing the initial load time and &lt;a href=&quot;https://web.dev/tbt/&quot;&gt;Total Blocking Time (TBT)&lt;/a&gt; (which is &lt;a href=&quot;https://almanac.httparchive.org/en/2022/performance#inp-and-tbt&quot; rel=&quot;noopener&quot;&gt;highly correlated with INP&lt;/a&gt;) on the main thread at that crucial part of the page lifecycle, therefore minimizing negative impacts on the user experience.&lt;/p&gt;
&lt;h2 id=&quot;refresh-ads-without-refreshing-the-page&quot;&gt;Refresh ads without refreshing the page &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#refresh-ads-without-refreshing-the-page&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A visualization of ads refreshing on the page, without the top-level page being refreshed.&quot; decoding=&quot;async&quot; height=&quot;367&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p4RuRhkucV695thelCNv.gif?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;An additional technique that can balance page performance with loading ads is the ability to refresh ads every 30 to 120 seconds without reloading the entire page. This approach allows for dynamic updates of ad content without disrupting the user&#39;s browsing experience or causing unnecessary delays.&lt;/p&gt;
&lt;p&gt;On mobile apps, refreshing ads in existing web views provides better performance compared to reloading the entire page or recreating WebViews because it minimizes the data and resource overhead, leading to faster content updates and a smoother user experience without the latency associated with starting from scratch.&lt;/p&gt;
&lt;p&gt;By refreshing ads asynchronously, website owners can keep the page content intact while seamlessly updating the ad content in-place and in real time. This not only improves page speed by eliminating the need to reload the entire page, but also ensures that displayed ads remain relevant and engaging. With this technique, website owners can strike a balance between monetization and performance, delivering timely and engaging ad content while minimizing negative effects on the user experience.&lt;/p&gt;
&lt;p&gt;Refreshing ad slots is particularly valuable on pages where users tend to stay longer, such as recipe pages, DIY tutorials, or other content-rich websites. For example, on a DIY crafting page where users may spend a considerable amount of time following the tutorials, refreshing ad slots strategically during breaks between the steps, or while viewing image galleries, can enhance both the user experience and ad revenue. Similarly on a recipe page, refreshing ad slots after users have scrolled through the ingredients list or instructions can maintain user interest.&lt;/p&gt;
&lt;h2 id=&quot;prioritize-asynchronous-loading&quot;&gt;Prioritize asynchronous loading &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#prioritize-asynchronous-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the most impactful strategies to improve page speed while serving ads is &lt;a href=&quot;https://developers.google.com/publisher-ads-audits/reference/audits/async-ad-tags&quot; rel=&quot;noopener&quot;&gt;asynchronous loading&lt;/a&gt;. Asynchronous loading loads ads independently of the main web page content allows the page to continue rendering and become interactive without waiting for ads to fully load.
This significantly reduces perceived loading time, enhancing user satisfaction.&lt;/p&gt;
&lt;p&gt;Include the &lt;code&gt;async&lt;/code&gt; attribute in the script tag definition. For example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AdSense:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;AdSense (auto ads):&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-ad-client&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ca-pub-xxxxxxxxxxxxxxxx&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Google Publisher Tag:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://securepubads.g.doubleclick.net/tag/js/gpt.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;optimize-ad-sizes,-position-and-formats&quot;&gt;Optimize ad sizes, position and formats &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#optimize-ad-sizes,-position-and-formats&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img alt=&quot;An illustration of devices at varying viewport sizes, with ad placements stylized as green boxes, each reading &amp;#x27;Ad&amp;#x27;.&quot; decoding=&quot;async&quot; height=&quot;222&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/DFxKqN3avsKFmFaU1CXL.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The size, position, and format for ads can have a significant impact on page speed. Large ad sizes can slow down page load, leading to frustrated users. To mitigate this, website owners should work closely with advertisers to &lt;a href=&quot;https://web.dev/learn/images/&quot;&gt;optimize ad sizes and formats&lt;/a&gt;. Encouraging the use of compressed image formats and efficient ad creative design helps reduce file sizes without compromising visual quality. These optimizations not only improve page speed, but also minimize data consumption for users with limited bandwidth.&lt;/p&gt;
&lt;h2 id=&quot;better-ads-standards&quot;&gt;Better Ads Standards &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#better-ads-standards&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;s essential to adhere to the &lt;a href=&quot;https://www.betterads.org/standards/&quot; rel=&quot;noopener&quot;&gt;Better Ads Standard&lt;/a&gt; for displaying ads, because doing so not only enhances the user experience by reducing intrusive and disruptive ad formats, but also positively impacts ad delivery position and page load time.&lt;/p&gt;
&lt;p&gt;By following these standards, ads are more likely to be placed in positions that are less obstructive and intrusive, which can result in a higher user engagement and click-through rates.&lt;/p&gt;
&lt;p&gt;Furthermore, adhering to these guidelines can also lead to faster page loading speeds since lighter, less resource-intensive ad formats are favored, improving overall website performance and user satisfaction.&lt;/p&gt;
&lt;h2 id=&quot;strategic-evaluation-of-ad-networks-and-providers&quot;&gt;Strategic evaluation of ad networks and providers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#strategic-evaluation-of-ad-networks-and-providers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not all ad networks and providers are created equal in terms of performance. To ensure optimal page speed, website owners should meticulously evaluate the performance of different ad networks, header bidding implementation, and providers.&lt;/p&gt;
&lt;p&gt;Forging partnerships with providers that prioritize speed—and have a track record of delivering lightweight ad content efficiently—can significantly increase page performance and improve the user experience.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/loading-ads-page-speed/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Achieving a balance between monetization and performance is crucial for website owners seeking to provide an exceptional user experience while maximizing revenue through online advertising.&lt;/p&gt;
&lt;p&gt;By using techniques such as asynchronous loading, lazy loading, optimizing ad formats and sizes, leveraging intelligent caching and carefully evaluating ad networks, and header bidding and providers, website owners can successfully navigate the challenges of loading ads without compromising page performance. Prioritizing efficient delivery of ads ultimately ensures user stratification, increased engagement, and sustainable revenue generation.&lt;/p&gt;
</content>
      <author>
          <name>Markus Bordihn</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>CSS Subgrid</title>
      <link href="https://web.dev/css-subgrid/"/>
      <updated>2023-09-28T00:00:00Z</updated>
      <id>https://web.dev/css-subgrid/</id>
      <content type="html" mode="escaped">&lt;style&gt;
  .auto-aspect {
    aspect-ratio: auto;
  }

  figcaption {
    text-wrap: balance;
  }
&lt;/style&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/learn/css/grid/&quot;&gt;CSS grid&lt;/a&gt; is a very powerful layout engine,
but the row and column tracks created on a parent grid can only be used to
position direct children of the grid container. Any author defined &lt;a href=&quot;https://web.dev/learn/css/grid/#named-grid-lines&quot;&gt;named grid
areas and lines&lt;/a&gt; were lost on
any other element than a direct child. With &lt;code&gt;subgrid&lt;/code&gt;, track sizing, templates
and names can be shared with nested grids. This article explains how it works.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-good-bg color-state-good-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 128 128&quot; style=&quot;enable-background:new 0 0 128 128&quot; xml:space=&quot;preserve&quot;&gt;&lt;path d=&quot;M7.5 123.3c2.2 2.4 11.6-1.9 19-5.3C32 115.4 54 106.3 65 101.6c3-1.2 7.3-2.9 10.4-7 2.8-3.6 10-19-4.6-34.7-15-16-30.4-11.5-36.2-7.5A28.5 28.5 0 0 0 27.3 63c-5.2 11.6-12.7 32.9-15.7 41.3-2.3 6.1-6.4 16.5-4.1 19z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M18 86.8s.7 6.5 6.1 14.6c6.3 9.6 15 11.2 15 11.2l-5.8 2.4s-6.5-2-12.7-10.4c-3.8-5.3-5-11.6-5-11.6l2.3-6.2zm-5.6 15.4s1.5 5.6 4.7 9.7c3.8 5 8.6 6.5 8.6 6.5l-4.5 2s-3.3-.8-7-5.5c-2.9-3.5-3.7-7.6-3.7-7.6l1.9-5.1z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M10 116.4c-.2-.5-.2-1 0-1.4l25.4-53 4.2 16-26.8 38.7c-.7 1-2.3 1-2.8-.2z&quot; style=&quot;opacity:.44&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M41.6 83.2c12 14 25.5 12.2 30 8.6 4.5-3.5 8.1-15.6-3.7-29.3C55.3 48.2 41.3 52.2 38 55.3s-7.4 15.1 3.5 27.9z&quot; style=&quot;fill: var(--color-state-good-bg);&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M82.5 89c-4.3-3.7-6.6-3-9.7-1.8a26 26 0 0 1-18.9 0l2.6-6.2c5 1.7 8.7 1 12-1 4-2.4 9.6-5.6 18.3 1.6 3.6 3 7.3 5.1 10 4.2 2-.7 3-3.6 3.6-6l.2-1.3c.4-3.7 1.2-11.6 7.1-15.7 6.4-4.3 13-4.3 13-4.3l1.2 12c-3-.5-5.2.1-7 1-6.7 3.8-.8 18.2-11.3 23-10.1 4.8-18.4-3.3-21-5.6zM45.4 73.7l-4.3-3.9c8-8.9 5.8-15.4 4.3-20.2A26.4 26.4 0 0 1 44 38.8c-3-3.8-4.4-7.8-4.5-8-1.9-5.7-.5-11.2 2.8-16.4C48.7 4 60.5 4 60.5 4l4 10.5c-3-.1-12.8 0-15.8 4.8-3.8 6-1.3 9.6-1.2 10 .8-1 1.5-1.7 2.2-2.3 4.8-4.2 9-4.8 11.6-4.6a11 11 0 0 1 7.6 4.2c2 2.7 3 6.2 2.3 9.4a11 11 0 0 1-5.8 7.4 16 16 0 0 1-13 1.5v.3l.6 2c1.8 5.4 5 14.1-7.6 26.5zm7.4-37.5c.5.4 1.1.8 1.8 1 2 .8 4.4.6 7-.8 1.5-.9 1.7-1.7 1.7-2 .2-.9 0-2-.7-2.8a2.8 2.8 0 0 0-2-1.2c-1.6-.2-3.6.8-5.6 2.6-1 .9-1.7 2-2.3 3.2zm10 39.1-6.2-.1s3-16.7 12.5-19.5c1.8-.5 3.7-1 5.7-1.3l4-.8c.1-1.6-.5-3.6-1.3-5.9-.6-1.7-1.2-3.5-1.5-5.5-.6-3.9.4-7.3 3-9.6 3-2.9 7.9-3.8 13.4-2.5 3.2.7 5.5 2.2 7.6 3.6 2.9 2 4.6 3 8.2.5 4.3-2.9-1.4-14.3-4.4-21l11.3-4.6c1.5 3.3 8.8 20.3 4 30a11.5 11.5 0 0 1-8.1 6.2c-8 1.8-12.6-1.3-16-3.6-1.6-1-3-1.9-4.6-2.3-10.6-3 4.2 12.6-2.7 19.6-4.2 4.2-14.4 5.3-15 5.5-6.6 1.6-10 11.3-10 11.3z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M44 38.8c-.2 2.2-.3 3.5.3 6.4 2.7 2 8.7 2 8.7 2l-.6-2v-.3c-6.1-3-8.4-6.1-8.4-6.1zm-12.5 9.8-10.3-5 5.1-7.5 8.2 5.4zm-15.2-14A26 26 0 0 1 5 28.9l5.2-6c1.6 1.2 5 3.5 7.2 3.8l-1.1 7.9zM25.6 21.3 18 18.8a18 18 0 0 0 .7-8.3l7.9-1.3c.6 4 .3 8.2-1 12zM73 15.3l7.9-1.7L83 23.9l-7.8 1.7zM92.5 17.8 87 12c2.8-2.8 3.5-6.3 3.5-6.4L98.4 7c-.1.6-1.1 6.3-6 10.9zM95.5 48.6l7-2.2 2.3 7.7-7 2.1zM97.5 113l-7.9-1c.3-2.7-1.8-6.2-2.4-7l6.4-4.8c.5.6 4.7 6.4 4 12.8zM120.4 102.9c-3-.5-6-.6-9.1-.5l-.3-8c3.5-.2 7 0 10.6.6l-1.2 7.9zM109.6 113.9l5.6-5.7 7.8 7.6-5.6 5.7zM93.1 63.3 99 70l-6.6 5.8-5.8-6.6z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;strong&gt;Celebration&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Special thanks to Microsoft Edge&#39;s Web Platform engineers for their contribution of subgrid to Chromium! This CSS feature was made available thanks to their great work: Alison Maher, Ethan Jimenez, Kurt Catti-Schmidt, Ana Sollano Kim and Daniel Libby. An additional special thanks to Ian Kilpatrick from the Google Chromium team for helping this land as well. Shout outs and kudos all around! &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; subgrid, content was often hand tailored to avoid ragged layouts like
this one.&lt;/p&gt;
&lt;img alt=&quot;Three cards are shown side by side, each with three bits of content: header, paragraph and link. Each are of a different text length, creating some awkward alignments in the cards as they sit next to each other.&quot; decoding=&quot;async&quot; height=&quot;412&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/UnomSiV22ITeHGkI8aFV.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; subgrid, aligning the variably sized content is possible.&lt;/p&gt;
&lt;img alt=&quot;Three cards are shown side by side, each with three bits of content: header, paragraph and link. Each are of a different text length, but subgrid has fixed the alignments by allowing the tallest of each content item to set the row height, fixing any alignment issues.&quot; decoding=&quot;async&quot; height=&quot;412&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/Dq1MzAIwsk8AJFtSJbWZ.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 114, Behind a flag&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox 71, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
71
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 114, Behind a flag&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 16, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
16
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Subgrid#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;subgrid-basics&quot;&gt;Subgrid basics &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-subgrid/#subgrid-basics&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a straightforward use case introducing the basics of CSS &lt;code&gt;subgrid&lt;/code&gt;. A
grid is defined with two named columns, the first is &lt;code&gt;20ch&lt;/code&gt; wide and the second
is &amp;quot;the rest&amp;quot; of the space &lt;code&gt;1fr&lt;/code&gt;. The column names aren&#39;t required but they&#39;re
great for illustrative and educational purposes.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.grid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; [column-1] 20ch [column-2] 1fr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then, a child of that grid, spans those two columns, is set as a grid container,
and adopts the columns of its parent by setting &lt;code&gt;grid-template-columns&lt;/code&gt; to
&lt;code&gt;subgrid&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.grid &gt; .subgrid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;grid-column&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; span 2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; subgrid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* 20ch 1fr */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the CSS grid DevTools, showing two columns side by side with a name at the start of their column line.&quot; decoding=&quot;async&quot; height=&quot;278&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/BS5avtsMBdfLsPFACRwO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    &lt;a href=&quot;https://codepen.io/web-dot-dev/pen/NWezjXv&quot;&gt;https://codepen.io/web-dot-dev/pen/NWezjXv&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;That&#39;s it, a parent grid&#39;s columns have been effectively passed down a level to
a subgrid. This subgrid can now assign children to either of those columns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenge!&lt;/strong&gt; Repeat the same demo but do it for &lt;code&gt;grid-template-rows&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;sharing-a-page-level-macro-grid&quot;&gt;Sharing a page level &amp;quot;macro&amp;quot; grid &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-subgrid/#sharing-a-page-level-macro-grid&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Designers often work with shared grids, drawing lines over an entire design,
aligning any element they want to it. Now web developers can too! This exact
workflow can now be achieved, plus many more.&lt;/p&gt;
&lt;figure data-size=&quot;full&quot;&gt;
  &lt;video autoplay=&quot;&quot; class=&quot;auto-aspect&quot; controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/vS06HQ1YTsbMKSFTIPl2iogUQP73/dGp49ObaTqFrp7eNADZx.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;From macro grid to finished design.
  Grid named areas are created upfront
  and later components are placed as desired.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Implementing the most common designer grid workflow can provide excellent
insights into the capabilities, workflows, and potentials of &lt;code&gt;subgrid&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s a screenshot taken from Chrome DevTools of a mobile page layout macro
grid. The lines have names and there are clear areas for component placement.&lt;/p&gt;
&lt;img alt=&quot;A screenshot from Chrome CSS grid DevTools showing a mobile sized grid layout where rows and columns are named for quick identification: fullbleed, system-status, primary-nav, primary-header, main, footer and system-gestures.&quot; decoding=&quot;async&quot; height=&quot;625&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8DcaxQKfWCUTYvM0jX5W.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The following CSS creates this grid, with named rows and columns for the device
layout. Each row and column has a size.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.device&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      [system-status] 3.5rem&lt;br /&gt;      [primary-nav] 3rem&lt;br /&gt;      [primary-header] 4rem&lt;br /&gt;      [main] auto&lt;br /&gt;      [footer] 4rem&lt;br /&gt;      [system-gestures] 2rem&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; [fullbleed-start] 1rem [main-start] auto [main-end] 1rem [fullbleed-end]&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Some additional styles give the following design.&lt;/p&gt;
&lt;img alt=&quot;Same CSS DevTools grid overlay as before, but this time with some of the mobile system UI present, some shadows and a little color. Helps see where the design is going.&quot; decoding=&quot;async&quot; height=&quot;625&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/3ApdWnQMSsdHp4HxLFiU.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Inside this parent, are various nested elements. The design requires a full
width image under the nav and header rows. The furthest left and right column
line names are &lt;code&gt;fullbleed-start&lt;/code&gt; and &lt;code&gt;fullbleed-end&lt;/code&gt;. Naming grid lines this way
enables children to align to each simultaneously with the &lt;a href=&quot;https://rachelandrew.co.uk/archives/2017/06/01/breaking-out-with-css-grid-explained/&quot; rel=&quot;noopener&quot;&gt;placement
shorthand&lt;/a&gt;
of &lt;code&gt;fullbleed&lt;/code&gt;. It’s very convenient as you’ll soon see.&lt;/p&gt;
&lt;img alt=&quot;A zoomed in screenshot of the grid overlay from DevTools, focusing specifically on the fullbleed-start and fullbleed-end column names.&quot; decoding=&quot;async&quot; height=&quot;207&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/8Og87j0has0wdFnSWjt4.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;With the overall device layout created with nice named rows and columns, use
&lt;code&gt;subgrid&lt;/code&gt; to pass the well named rows and columns to nested grid layouts. This
is that &lt;code&gt;subgrid&lt;/code&gt; magic moment. The device layout passes the named rows and
columns to the app container, which then passes it on to every one of its
children.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.device &gt; .app,&lt;br /&gt;.app &gt; *&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; subgrid / subgrid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* same as */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; subgrid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; subgrid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;CSS subgrid is a value used in place of a list of grid tracks.&lt;/strong&gt; The rows and
columns the element is spanning from its parent, are now the same rows and
columns it offers. This makes the line names from the &lt;code&gt;.device&lt;/code&gt; grid available
to children of &lt;code&gt;.app&lt;/code&gt;, instead of only &lt;code&gt;.app&lt;/code&gt;. Elements inside of &lt;code&gt;.app&lt;/code&gt; were
not able to reference the grid tracks created by &lt;code&gt;.device&lt;/code&gt; before subgrid.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; &lt;code&gt;display: grid&lt;/code&gt; is required on every element that wishes to subscribe or pass on rows and columns. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;With this all defined, the nested image is now able to go full bleed in the
layout thanks to &lt;code&gt;subgrid&lt;/code&gt;. No negative values or tricks, instead a nice
one-liner that says “my layout spans from &lt;code&gt;fullbleed-start&lt;/code&gt; to &lt;code&gt;fullbleed-end&lt;/code&gt;.”&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.app &gt; main img&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;grid-area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; fullbleed&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;The finished macro layout, complete with a full width nested image sitting properly undeath the primary nav and header rows and extending to each of the fullbleed named column lines.&quot; decoding=&quot;async&quot; height=&quot;625&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/6QIh2ogOS21KjBwcfFuf.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    &lt;a href=&quot;https://codepen.io/web-dot-dev/pen/WNLyjzX&quot;&gt;https://codepen.io/web-dot-dev/pen/WNLyjzX&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There you have it, a macro grid like designers use, implemented in CSS. This
concept can scale and grow with you as needed.&lt;/p&gt;
&lt;h2 id=&quot;checking-for-support&quot;&gt;Checking for support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-subgrid/#checking-for-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Progressive enhancement with CSS and subgrid is familiar and straightforward.
Use &lt;code&gt;@supports&lt;/code&gt; and inside the parenthesis ask the browser if it understands
subgrid as a value for template columns or rows. The following example checks if
the &lt;code&gt;grid-template-columns&lt;/code&gt; property supports the &lt;code&gt;subgrid&lt;/code&gt; keyword, which if
true, means that subgrid can be used&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; subgrid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* safe to enhance to */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;codepen-embed-wrap&quot; style=&quot;height: 500px; width: 100%&quot;&gt;
&lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;&quot; loading=&quot;lazy&quot; src=&quot;https://codepen.io/web-dot-dev/embed/KKrJPZQ?height=500&amp;theme-id=light&amp;default-tab=css%2Cresult&amp;editable=true&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;Pen KKrJPZQ by web-dot-dev on Codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/web-dot-dev/embed/KKrJPZQ&quot;&gt;Pen KKrJPZQ by web-dot-dev on Codepen&lt;/a&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h2 id=&quot;devtools&quot;&gt;Devtools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-subgrid/#devtools&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chrome, Edge, Firefox and Safari all have great CSS grid DevTools, and Chrome,
Edge and Firefox have specific tools for helping with subgrid. &lt;a href=&quot;https://developer.chrome.com/blog/new-in-devtools-115/#subgrid&quot; rel=&quot;noopener&quot;&gt;Chrome
announced their tools in
115&lt;/a&gt; while
Firefox has had them for a year or more.&lt;/p&gt;
&lt;img alt=&quot;Screenshot preview of the subgrid badge found on elements in the Elements panel.&quot; decoding=&quot;async&quot; height=&quot;201&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/stbBs4EgwIRBfmkLHN9x.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The subgrid badge acts like the grid badge but visually distinguishes which
grids are subgrids and which aren’t.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-subgrid/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This list is a compilation of subgrid articles, demos and overall inspiration
for getting started. If you’re looking for the next step for your subgrid
education, have fun exploring all these great resources!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_grid_layout/Subgrid&quot;&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/rachelandrew/pen/VVGZVW&quot;&gt;Rachel Andrew with aligned captions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://12daysofweb.dev/2022/css-subgrid/&quot;&gt;Rachel Andrew with 10 great examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gridbyexample.com/examples/#css-grid-level-2-examples&quot;&gt;Rachel Andrew with a site of examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ishadeed.com/article/learn-css-subgrid/&quot;&gt;Ahmad Shadeed article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/tueTFd2TQUA?t=2266&quot;&gt;Michelle Barker at CSS Day 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cards
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/jh3y/pen/abKaYqO&quot;&gt;Codepen by Jhey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/shadeed/pen/qBpQNQY&quot;&gt;Codepen by Ahmad Shadeed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/tonkotsuboy/pen/LYexpZp&quot;&gt;Codepen by Takeshi Kano&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/ArvidW/pen/rNrGjvW&quot;&gt;Codepen by Arvid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/chriscoyier/pen/bGRXmEe&quot;&gt;Codepen by Chris Coyier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/miriamsuzanne/pen/xxKRpmq&quot;&gt;Codepen by Miriam Suzanne&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/chriscoyier/pen/YzxqJap&quot;&gt;Chris Coyier with forms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/facundocorradini/pen/wvBBpJM&quot;&gt;Facundo Corradini with form alignment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/chriscoyier/pen/mdemZaw&quot;&gt;Chris Coyier with aligning list item markers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/michellebarker/pen/wvyBjOz&quot;&gt;Michelle Barker popping out of container to align with parent grid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/miriamsuzanne/pen/ZEEbxro&quot;&gt;Miriam Suzanne showing named line names and subgrid interactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/kevinpowell/pen/RwgvMMb&quot;&gt;Kevin Powell with named area basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/kevinpowell/pen/XWgoWRx&quot;&gt;Kevin Powell with aligned lists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/shannonmoeller/pen/poLQLoO&quot;&gt;Shannon Moeller with aligned lists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/kevinpowell/pen/LYVmpqY&quot;&gt;Kevin Powell with a page level grid passed down to components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/elad2412/pen/KKaXOPG&quot;&gt;Elad Shechter with a devtool overlay and fallback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/aaroniker/pen/OeyayK&quot;&gt;Aaron Iker with a nice typographic use of subgrid for baseline alignment of footnotes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/argyleink/pen/ExbzqWp&quot;&gt;Adam Argyle with a fullbleed image inside an article&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
      <author>
          <name>Adam Argyle</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Submit your proposals for Interop 2024</title>
      <link href="https://web.dev/interop-2024-proposals/"/>
      <updated>2023-09-14T00:00:00Z</updated>
      <id>https://web.dev/interop-2024-proposals/</id>
      <content type="html" mode="escaped">&lt;p&gt;Over the past two years the Chrome team has successfully worked with our partners to improve the interoperability of the web. For &lt;a href=&quot;https://web.dev/interop-2022-wrapup/&quot;&gt;Interop 2022&lt;/a&gt; all major browser vendors and other stakeholders worked together to improve top browser compatibility issues identified by web developers. We repeated the process with &lt;a href=&quot;https://web.dev/interop-2023/&quot;&gt;Interop 2023&lt;/a&gt;, which still has a few months to run yet is already seeing a huge improvement in scores. For Interop 2023, we also requested public proposals for features to include, which led to many great suggestions representing the needs of the wider web ecosystem.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The Scores for Interop overall: 62, Investigations: 0, and the scores per browser - 86 for Chrome and Edge, 74 for Firefox, 86 for Safari Technology Preview.&quot; decoding=&quot;async&quot; height=&quot;866&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/RYmV5NPuMZRoF3PVwIXTUpdYeQ23/rK7xV8u6Jvf9oSl7VkCT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;January 2023.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The scores for Interop overall: 81, Investigations 59, and per browser, 96 for Chrome Dev and Edge Dev, 88 for Firefox Nightly, and 92 for Safari Technology Preview.&quot; decoding=&quot;async&quot; height=&quot;808&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/25TJc2Fc8gJ4Qp9vQUNA.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;September 2023.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It&#39;s been a huge success, with many features reaching interoperability, and we&#39;re happy to announce that Interop 2024 is happening.&lt;/p&gt;
&lt;p&gt;The first step is to gather suggested features, once again including ideas from the wider community, so the Interop 2024 proposal process is now open for submissions. Suggestions can include features that behave differently across browsers, or features that are not yet implemented in all browsers. Keep in mind that proposals with high quality specifications and web platform tests are &lt;a href=&quot;https://github.com/web-platform-tests/interop/blob/main/README.md#requirements-for-focus-area-proposals&quot; rel=&quot;noopener&quot;&gt;more likely to be included&lt;/a&gt;, as this project is about reaching interoperability rather than specifying new features. The proposal submission process ends October 5, 2023.&lt;/p&gt;
&lt;p&gt;Once the proposal period ends, the collected submissions will be discussed by browser vendors and other partners to determine the final list. It&#39;s likely that there will be more proposals than can be achieved during 2024, so some high quality proposals may not be selected. We are looking forward to reviewing &lt;a href=&quot;https://github.com/orgs/web-platform-tests/projects/3&quot; rel=&quot;noopener&quot;&gt;all the submissions&lt;/a&gt;, and we&#39;ll post the final list here once Interop 2024 gets underway.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/web-platform-tests/interop/issues/new/choose&quot; rel=&quot;noopener&quot;&gt;Submit your proposals here&lt;/a&gt;.&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author><author>
          <name>Robert Nyman</name>
        </author><author>
          <name>Philip Jägenstedt</name>
        </author><author>
          <name>Nandu Nair</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Four common types of code coverage</title>
      <link href="https://web.dev/ta-code-coverage/"/>
      <updated>2023-09-06T00:00:00Z</updated>
      <id>https://web.dev/ta-code-coverage/</id>
      <content type="html" mode="escaped">&lt;p&gt;Have you heard the phrase &amp;quot;code coverage&amp;quot;? In this post, we will explore what code coverage in tests is and four common ways to measure it.&lt;/p&gt;
&lt;h2 id=&quot;what-is-code-coverage&quot;&gt;What is code coverage? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#what-is-code-coverage&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Code coverage is a metric that measures the percentage of source code your tests execute. It helps you identify areas that may lack proper testing.&lt;/p&gt;
&lt;p&gt;Often, recording these metrics looks like this:&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
  .tg {
    border: 1px solid var(--color-stroke);
  }

  .tg tbody {
    background-color: var(--color-mid-bg);
  }
  .tg-zo2y span {
    color: var(--color-state-bad-text);
  }
  .tg-bsyc span {
    color: var(--color-state-good-text);
  }
  .tg-kfug span {
    color: var(--color-state-warn-text);
  }
&lt;/style&gt;
&lt;table class=&quot;tg&quot;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;File&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;% Statements&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;% Branch&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;% Functions&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;% Lines&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&quot;tg-1wig&quot;&gt;&lt;span&gt;Uncovered lines&lt;/span&gt;&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-0lax&quot;&gt;&lt;span&gt;file.js&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-bsyc&quot;&gt;&lt;span&gt;90%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-bsyc&quot;&gt;&lt;span&gt;100%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-bsyc&quot;&gt;&lt;span&gt;90%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-bsyc&quot;&gt;&lt;span&gt;80%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-zo2y&quot;&gt;&lt;span&gt;89,256&lt;/span&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&quot;tg-0lax&quot;&gt;&lt;span&gt;coffee.js&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-kfug&quot;&gt;&lt;span&gt;55.55%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-bsyc&quot;&gt;&lt;span&gt;80%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-kfug&quot;&gt;&lt;span&gt;50%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-kfug&quot;&gt;&lt;span&gt;62.5%&lt;/span&gt;&lt;/td&gt;
    &lt;td class=&quot;tg-zo2y&quot;&gt;&lt;span&gt;10-11, 18&lt;/span&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you add new features and tests, increasing code coverage percentages can give you more confidence that your application has been thoroughly tested. However, there is more to discover.&lt;/p&gt;
&lt;h2 id=&quot;four-common-types-of-code-coverage&quot;&gt;Four common types of code coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#four-common-types-of-code-coverage&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are four common ways to collect and calculate code coverage: function, line, branch, and statement coverage.&lt;/p&gt;
&lt;img alt=&quot;Four types of text coverage.&quot; decoding=&quot;async&quot; height=&quot;449&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/W9iaHL2YtKeBz5vRmWFQ.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;To see how each type of code coverage calculates its percentage, consider the following code example for calculating coffee ingredients:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* coffee.js */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;coffeeName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; espresso&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coffeeName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    espresso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; espresso &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coffeeName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    espresso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; water &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; espresso&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isValidCoffee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocha&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The tests that verify the &lt;code&gt;calcCoffeeIngredient&lt;/code&gt; function are:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* coffee.test.js */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; describe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; expect&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; assert&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; it &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;vitest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; calcCoffeeIngredient &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../src/coffee-incomplete&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Coffee&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should have espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deep&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;espresso&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should have nothing&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deep&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can run the code and tests on this &lt;a href=&quot;https://stackblitz.com/edit/vitest-coffee-coverage?file=README.md&quot; rel=&quot;noopener&quot;&gt;live demo&lt;/a&gt; or check out the &lt;a href=&quot;https://github.com/leichteckig/vitest-coffee-example&quot; rel=&quot;noopener&quot;&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;function-coverage&quot;&gt;Function coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#function-coverage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Code coverage: 50%&lt;/strong&gt;&lt;/p&gt;
&lt;style&gt;del {text-decoration: none; !important}&lt;/style&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;/* coffee.js */&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;export function calcCoffeeIngredient(coffeeName, cup = 1) {&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  // ...&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;}&lt;/ins&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;&lt;/del&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;function isValidCoffee(name) {&lt;/del&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;  // ...&lt;/del&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;}&lt;/del&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;Function coverage&lt;/em&gt; is a straightforward metric. It captures the percentage of functions in your code that your tests call.&lt;/p&gt;
&lt;p&gt;In the code example, there are two functions: &lt;code&gt;calcCoffeeIngredient&lt;/code&gt; and &lt;code&gt;isValidCoffee&lt;/code&gt;. The tests only call the &lt;code&gt;calcCoffeeIngredient&lt;/code&gt; function, so the function coverage is 50%.&lt;/p&gt;
&lt;h3 id=&quot;line-coverage&quot;&gt;Line coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#line-coverage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Code coverage: 62.5%&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;/* coffee.js */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;export function calcCoffeeIngredient(coffeeName, cup = 1) {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  let espresso, water;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  if (coffeeName === &#39;espresso&#39;) {&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    espresso = 30 * cup;&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    return { espresso };&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  if (coffeeName === &#39;americano&#39;) {&lt;/ins&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;    espresso = 30 * cup; water = 70 * cup;&lt;/del&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;    return { espresso, water };&lt;/del&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  return {};&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;export function isValidCoffee(name) {&lt;/span&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;  return [&#39;espresso&#39;, &#39;americano&#39;, &#39;mocha&#39;].includes(name);&lt;/del&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;Line coverage&lt;/em&gt; measures the percentage of executable code lines that your test suite executed. If a line of code remains unexecuted, it means that some part of the code hasn&#39;t been tested.&lt;/p&gt;
&lt;p&gt;The code example has eight lines of executable code (highlighted in red and green)  but the tests don’t execute the &lt;code&gt;americano&lt;/code&gt; condition (two lines) and the &lt;code&gt;isValidCoffee&lt;/code&gt; function (one line). This results in a line coverage of 62.5%.&lt;/p&gt;
&lt;p&gt;Note that line coverage doesn’t take into account declaration statements, such as &lt;code&gt;function isValidCoffee(name)&lt;/code&gt; and &lt;code&gt;let espresso, water;&lt;/code&gt;, because they are not executable.&lt;/p&gt;
&lt;h3 id=&quot;branch-coverage&quot;&gt;Branch coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#branch-coverage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Code coverage: 80%&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;/* coffee.js */&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;export function calcCoffeeIngredient(coffeeName, cup = 1) {&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  // ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  if (coffeeName === &#39;espresso&#39;) {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    // ...&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    return { espresso };&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  if (coffeeName === &#39;americano&#39;) {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    // ...&lt;/span&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;    return { espresso, water };&lt;/del&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  return {};&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;…&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;Branch coverage&lt;/em&gt; measures the percentage of executed branches or decision points in the code, such as if statements or loops. It determines whether tests examine both the true and false branches of conditional statements.&lt;/p&gt;
&lt;p&gt;There are five branches in the code example:&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
  li img.custom-icon {
    margin-top:0 !important;
    display:inline;
  }
&lt;/style&gt;
&lt;ol&gt;
&lt;li&gt;Calling &lt;code&gt;calcCoffeeIngredient&lt;/code&gt; with just &lt;code&gt;coffeeName&lt;/code&gt; &lt;img alt=&quot;Chek mark.&quot; class=&quot;custom-icon&quot; decoding=&quot;async&quot; height=&quot;20&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CpHz0pF9m750yTrbDveT.svg&quot; width=&quot;20&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Calling &lt;code&gt;calcCoffeeIngredient&lt;/code&gt; with &lt;code&gt;coffeeName&lt;/code&gt; and &lt;code&gt;cup&lt;/code&gt; &lt;img alt=&quot;Chek mark.&quot; class=&quot;custom-icon&quot; decoding=&quot;async&quot; height=&quot;20&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CpHz0pF9m750yTrbDveT.svg&quot; width=&quot;20&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Coffee is Espresso &lt;img alt=&quot;Chek mark.&quot; class=&quot;custom-icon&quot; decoding=&quot;async&quot; height=&quot;20&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CpHz0pF9m750yTrbDveT.svg&quot; width=&quot;20&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Coffee is Americano &lt;img alt=&quot;X mark.&quot; class=&quot;custom-icon&quot; decoding=&quot;async&quot; height=&quot;20&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/ufOsI388YJ9gqjrXjZuQ.svg&quot; width=&quot;20&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Other coffee &lt;img alt=&quot;Chek mark.&quot; class=&quot;custom-icon&quot; decoding=&quot;async&quot; height=&quot;20&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/CpHz0pF9m750yTrbDveT.svg&quot; width=&quot;20&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The tests cover all branches except the &lt;code&gt;Coffee is Americano&lt;/code&gt; condition. So branch coverage is 80%.&lt;/p&gt;
&lt;h3 id=&quot;statement-coverage&quot;&gt;Statement coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#statement-coverage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Code coverage: 55.55%&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;/* coffee.js */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;export function calcCoffeeIngredient(coffeeName, cup = 1) {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  let espresso, water;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  if (coffeeName === &#39;espresso&#39;) {&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    espresso = 30 * cup;&lt;/ins&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;    return { espresso };&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  if (coffeeName === &#39;americano&#39;) {&lt;/ins&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;    espresso = 30 * cup; water = 70 * cup;&lt;/del&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;    return { espresso, water };&lt;/del&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ins class=&quot;highlight-line highlight-line-add&quot;&gt;  return {};&lt;/ins&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;export function isValidCoffee(name) {&lt;/span&gt;&lt;br /&gt;&lt;del class=&quot;highlight-line highlight-line-remove&quot;&gt;  return [&#39;espresso&#39;, &#39;americano&#39;, &#39;mocha&#39;].includes(name);&lt;/del&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;Statement coverage&lt;/em&gt; measures the percentage of statements in your code that your tests execute. At first glance, you might wonder, “isn’t this the same as line coverage?” Indeed, statement coverage is similar to line coverage but takes into account single lines of code that contain multiple statements.&lt;/p&gt;
&lt;p&gt;In the code example, there are eight lines of executable code, but there are nine statements. Can you spot the line containing two statements?&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
  Check your answer
&lt;/summary&gt;
It&#39;s the following line: `espresso = 30 * cup; water = 70 * cup;`
&lt;/details&gt;
&lt;p&gt;The tests cover only five of the nine statements, therefore the statement coverage is 55.55%.&lt;/p&gt;
&lt;p&gt;If you always write one statement per line, your line coverage will be similar to your statement coverage.&lt;/p&gt;
&lt;h2 id=&quot;what-type-of-code-coverage-should-you-choose&quot;&gt;What type of code coverage should you choose? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#what-type-of-code-coverage-should-you-choose&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most code coverage tools include these four types of common code coverage. Choosing which code coverage metric to prioritize depends on specific project requirements, development practices, and testing goals.&lt;/p&gt;
&lt;p&gt;In general, statement coverage is a good starting point because it is a simple and easy-to-understand metric. Unlike statement coverage, branch coverage and function coverage measure whether tests call a condition (branch) or a function. Therefore, they are a natural progression &lt;em&gt;after&lt;/em&gt; statement coverage.&lt;/p&gt;
&lt;p&gt;Once you have achieved high statement coverage, you can then move on to branch coverage and function coverage.&lt;/p&gt;
&lt;h2 id=&quot;is-test-coverage-the-same-as-code-coverage&quot;&gt;Is test coverage the same as code coverage? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#is-test-coverage-the-same-as-code-coverage&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;No. Test coverage and code coverage are often confused but they are different:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Test coverage&lt;/strong&gt;: A qualitative metric that measures how well the test suite covers the features of the software. It helps determine the level of risk involved.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code coverage&lt;/strong&gt;: A quantitative metric that measures the proportion of code executed during testing. It is about how much code the tests cover.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a simplified analogy: imagine a web application as a house.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test coverage measures how well the tests cover the rooms in the house.&lt;/li&gt;
&lt;li&gt;Code coverage measures how much of the house the tests have walked through.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;100percent-code-coverage-doesnt-mean-no-bugs&quot;&gt;100% code coverage doesn’t mean no bugs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#100percent-code-coverage-doesnt-mean-no-bugs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it is certainly desirable to achieve high code coverage in testing, 100% code coverage doesn’t guarantee the absence of bugs or flaws in your code.&lt;/p&gt;
&lt;h3 id=&quot;a-meaningless-way-to-achieve-100percent-code-coverage&quot;&gt;A meaningless way to achieve 100% code coverage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#a-meaningless-way-to-achieve-100percent-code-coverage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider the following test:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* coffee.test.js */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Warning: Do not do this&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;is meaningless&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;isValidCoffee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mocha&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// not meaningful assertion&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This test achieves 100% function, line, branch, and statement coverage, but it doesn’t make sense because it doesn’t actually test the code. The &lt;code&gt;expect(true).toBe(true)&lt;/code&gt; assertion will always pass regardless of whether the code works correctly.&lt;/p&gt;
&lt;h3 id=&quot;a-bad-metric-is-worse-than-no-metric&quot;&gt;A bad metric is worse than no metric &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#a-bad-metric-is-worse-than-no-metric&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A bad metric can give you a false sense of security, which is worse than having no metric at all. For example, if you have a test suite that achieves 100% code coverage but the tests are all meaningless, then you may get a false sense of security that your code is well tested. If you accidentally delete or break a part of the application code, the tests will still pass, even though the application no longer works correctly.&lt;/p&gt;
&lt;p&gt;To avoid this scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Test review.&lt;/strong&gt; Write and review tests to make sure they are meaningful and test the code in a variety of different scenarios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use code coverage as a guideline&lt;/strong&gt;, not as the only measure of test effectiveness or code quality.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;using-code-coverage-in-different-types-of-testing&quot;&gt;Using code coverage in different types of testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#using-code-coverage-in-different-types-of-testing&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s take a closer look at how you can use code coverage with the &lt;a href=&quot;https://web.dev/ta-what-to-test/#test-specifics-dos-and-donts&quot;&gt;three common types of test&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit tests.&lt;/strong&gt; They are the best test type for gathering code coverage because they are designed to cover multiple small scenarios and testing paths.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests.&lt;/strong&gt; They can help collect code coverage for integration tests, but use them with caution. In this case, you calculate the coverage of a larger portion of the source code, and it can be difficult to determine which tests actually cover which parts of the code. Nonetheless, calculating code coverage of integration tests may be useful for legacy systems that don’t have well-isolated units.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-end (E2E) tests.&lt;/strong&gt; Measuring code coverage for E2E tests is difficult and challenging due to the intricate nature of these tests. Instead of using code coverage, requirement coverage might be the better way to go. This is because the focus of E2E tests is to cover the requirements of your test, not to focus on the source code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-code-coverage/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Code coverage can be a useful metric for measuring the effectiveness of your tests. It can help you to improve the quality of your application by ensuring that the crucial logic in your code is well tested.&lt;/p&gt;
&lt;p&gt;However, remember that code coverage is just one metric. Make sure to also consider other factors, such as the quality of your tests and your application requirements.&lt;/p&gt;
&lt;p&gt;Aiming for 100% code coverage is not the goal. Instead, you should use code coverage along with a well-rounded testing plan that incorporates a variety of testing methods, including unit tests, integration tests, end-to-end tests, and manual tests.&lt;/p&gt;
&lt;p&gt;See the full code example and tests with good code coverage. You can also run the code and tests with this &lt;a href=&quot;https://stackblitz.com/edit/vitest-coffee-coverage?file=README.md&quot; rel=&quot;noopener&quot;&gt;live demo&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* coffee.js - a complete example */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;coffeeName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidCoffee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coffeeName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; espresso&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coffeeName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    espresso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; espresso &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coffeeName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    espresso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; water &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; cup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; espresso&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; water &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;coffeeName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; not found&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isValidCoffee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocha&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* coffee.test.js - a complete test suite */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; describe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; expect&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; it &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;vitest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; calcCoffeeIngredient &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../src/coffee-complete&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Coffee&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should have espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;espresso&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deep&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;espresso&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should have americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;americano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;espresso&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;water&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should throw error&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mocha&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;func&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toThrowError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mocha not found&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should have nothing&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calcCoffeeIngredient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deep&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This blog post was written by Ramona and &lt;a href=&quot;https://web.dev/authors/jecelynyeen/&quot;&gt;Jecelyn Yeen&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/jecfish&quot;&gt;Twitter&lt;/a&gt;), with input and review from &lt;a href=&quot;https://www.linkedin.com/in/michael-hablich-2128646/&quot;&gt;Michael Hablich&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/MHablich&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://web.dev/authors/rachelandrew/&quot;&gt;Rachel Andrew&lt;/a&gt;, and &lt;a href=&quot;https://www.linkedin.com/in/sofia-yemelianova/&quot;&gt;Sofia Emelianova&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
</content>
      <author>
          <name>Ramona Schwering</name>
        </author><author>
          <name>Jecelyn Yeen</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>How prefetching helped Terra increase ads click-through rate by 30% and speed up Largest Contentful Paint.</title>
      <link href="https://web.dev/terra-prefetching-case-study/"/>
      <updated>2023-09-01T00:00:00Z</updated>
      <id>https://web.dev/terra-prefetching-case-study/</id>
      <content type="html" mode="escaped">&lt;p&gt;Prefetching is a technique used to speed up page loading by downloading resources—or even entire pages—which are likely to be needed in the near future. Research has shown that &lt;a href=&quot;https://wpostats.com/&quot; rel=&quot;noopener&quot;&gt;faster load times result in higher conversion rates&lt;/a&gt; and better user experiences.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.terra.com/&quot; rel=&quot;noopener&quot;&gt;Terra&lt;/a&gt; is one of the largest content portals from Brazil, offering entertainment, news, and sports with more than 63 million unique visitors per month. We’ve collaborated with Terra’s engineering team to improve the loading time of articles by using prefetching techniques on certain sections of their website.&lt;/p&gt;
&lt;p&gt;This case study describes Terra’s journey implementation which resulted in a 11% ads click-through rate (CTR) increase on mobile, 30% ads CTR on desktop, and 50% reduction in the &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; times.&lt;/p&gt;
&lt;h2 id=&quot;prefetching-strategy&quot;&gt;Prefetching strategy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/terra-prefetching-case-study/#prefetching-strategy&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Prefetching has been around for a while, but it is important to use it carefully as it consumes extra bandwidth for resources that are not immediately necessary. This technique should be applied thoughtfully to avoid unnecessary data usage. In the case of Terra, articles are prefetched if the following conditions are met:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visibility of links to prefetched articles:&lt;/strong&gt; Terra used the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API&quot; rel=&quot;noopener&quot;&gt;Intersection Observer API&lt;/a&gt; to detect viewability of the section containing the articles that they wanted to prefetch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Favorable conditions for increased data usage:&lt;/strong&gt; As mentioned previously, prefetching is a speculative performance improvement that consumes extra data, and that may not be a desirable outcome in every situation. To reduce the likelihood of wasting bandwidth, Terra uses the &lt;a href=&quot;https://wicg.github.io/netinfo/&quot; rel=&quot;noopener&quot;&gt;Network Information API&lt;/a&gt; along with the &lt;a href=&quot;https://developer.chrome.com/blog/device-memory/&quot; rel=&quot;noopener&quot;&gt;Device Memory API&lt;/a&gt; to determine whether to fetch the next article. Terra only fetches the next article when:
&lt;ul&gt;
&lt;li&gt;The connection speed is at least 3G and the device has at least 4GB of memory,&lt;/li&gt;
&lt;li&gt;or if the device is running iOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU idle:&lt;/strong&gt; Finally, Terra checks if the CPU is idle and able to perform extra work by using &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/requestIdleCallback&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;requestIdleCallback&lt;/code&gt;&lt;/a&gt;, which takes a callback to be processed when the main thread is idle, or by a specific (optional) deadline—whichever comes first.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adhering to these conditions ensures that Terra only fetches data when necessary, which saves bandwidth and battery life, and minimizes the impact of prefetches that end up going unused.&lt;/p&gt;
&lt;p&gt;When these conditions are met, Terra prefetches the articles present in the sections: &amp;quot;Related Content&amp;quot; and &amp;quot;Recommended for you&amp;quot; highlighted in blue below.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the two sections on the Terra website in which links were prefetched. At left, the &amp;#x27;Related content&amp;#x27; section is highlighted, whereas on the right, the &amp;#x27;Recommended for you&amp;#x27; section is highlighted.&quot; decoding=&quot;async&quot; height=&quot;494&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/Z5yUqXEgRMMMUqXtYCw1.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;business-impact&quot;&gt;Business Impact &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/terra-prefetching-case-study/#business-impact&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to measure the impact of this technique, Terra first launched this feature in the &amp;quot;Related content&amp;quot; section of the article page. A UTM code helped them to differentiate between prefetched and non-prefetched articles for comparison purposes. After two weeks of successful A/B testing, Terra decided to add the prefetching functionality to the &amp;quot;Recommended for you&amp;quot; section.&lt;/p&gt;
&lt;p&gt;As a result of prefetching articles, an overall increase of ads metrics and a reduction of LCP and &lt;a href=&quot;https://web.dev/ttfb/&quot;&gt;Time to First Byte (TTFB)&lt;/a&gt; times were observed:&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Metric&lt;/th&gt;
        &lt;th&gt;Mobile&lt;/th&gt;
        &lt;th&gt;Desktop&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Ads CTR&lt;/td&gt;
        &lt;td&gt;+11%&lt;/td&gt;
        &lt;td&gt;+30%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Ads viewability&lt;/td&gt;
        &lt;td&gt;+10.5%&lt;/td&gt;
        &lt;td&gt;+6%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;LCP&lt;/td&gt;
        &lt;td&gt;-51%&lt;/td&gt;
        &lt;td&gt;-73%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;TTFB&lt;/td&gt;
        &lt;td&gt;-83%&lt;/td&gt;
        &lt;td&gt;-84%&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Prefetching—when used with care—greatly improves page load time, increases ads metrics, and reduces LCP time.&lt;/p&gt;
&lt;h2 id=&quot;technical-details&quot;&gt;Technical details &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/terra-prefetching-case-study/#technical-details&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Prefetching can be achieved through the use of resource hints such as &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/Prefetch&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rel=prefetch&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/rel/preload&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rel=preload&lt;/code&gt;&lt;/a&gt;, via libraries such as &lt;a href=&quot;https://github.com/GoogleChromeLabs/quicklink&quot; rel=&quot;noopener&quot;&gt;quicklink&lt;/a&gt; or &lt;a href=&quot;https://github.com/guess-js&quot; rel=&quot;noopener&quot;&gt;Guess.js&lt;/a&gt;, or using the newer Speculation Rules API. Terra has chosen to implement this by using the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Fetch_API&quot; rel=&quot;noopener&quot;&gt;fetch API&lt;/a&gt; with a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/fetch#:~:text=priority&quot; rel=&quot;noopener&quot;&gt;low priority&lt;/a&gt; in combination with an Intersection Observer instance. Terra made this choice as it allows them to support Safari, which doesn&#39;t yet support other prefetching methods like &lt;code&gt;rel=prefetch&lt;/code&gt; or the Speculation Rules API, and a full-featured JavaScript library wasn&#39;t necessary for Terra&#39;s needs.&lt;/p&gt;
&lt;p&gt;The below JavaScript is approximately equivalent to the code used by Terra:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prefetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nodeLists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Exclude slow ECTs &amp;lt; 3g&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;effectiveType &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;slow-2g&#39;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;effectiveType &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;2g&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Exclude low end device which is device with memory &amp;lt;= 2GB&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deviceMemory &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deviceMemory &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fetchLinkList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; observer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IntersectionObserver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    entries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isIntersecting&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;fetchLinkList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          fetchLinkList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;          &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;priority&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;low&#39;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        observer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unobserve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; idleCallback &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;requestIdleCallback &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;didTimeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function-variable function&quot;&gt;timeRemaining&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;idleCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;prefetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nodeLists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;prefetch&lt;/code&gt; function first checks for a minimum connection quality and device memory before initiating prefetching.&lt;/li&gt;
&lt;li&gt;Then it uses an &lt;code&gt;IntersectionObserver&lt;/code&gt; to monitor when elements become visible in the viewport, and subsequently adds URLs to a list for prefetching.&lt;/li&gt;
&lt;li&gt;The prefetch process is scheduled with &lt;code&gt;requestIdleCallback&lt;/code&gt;, aiming to execute the &lt;code&gt;prefetch&lt;/code&gt; function when the main thread is idle.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/terra-prefetching-case-study/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When used with care, prefetching can significantly reduce load times for future navigation requests, thereby reducing friction in the user journey and increasing engagement. Prefetching results in loading of extra bytes that may not be used, so Terra took extra steps to only prefetch under good network conditions and on capable devices, where this information is available.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to Gilberto Cocchi, Harry Theodoulou, Miguel Carlos Martínez Díaz, Barry Pollard, Jeremy Wagner, and Leonardo Bellini and Lucca Paradeda from Terra&#39;s Engineering team for their contribution to this work.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Guilherme Moser de Souza</name>
        </author><author>
          <name>Thierno Thiam</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>New to the web platform in August</title>
      <link href="https://web.dev/web-platform-08-2023/"/>
      <updated>2023-08-31T00:00:00Z</updated>
      <id>https://web.dev/web-platform-08-2023/</id>
      <content type="html" mode="escaped">&lt;h2 id=&quot;stable-browser-releases&quot;&gt;Stable browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-08-2023/#stable-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In August 2023 &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/116&quot; rel=&quot;noopener&quot;&gt;Firefox 116&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/117&quot; rel=&quot;noopener&quot;&gt;Firefox 117&lt;/a&gt;, &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 16.6&lt;/a&gt;, and &lt;a href=&quot;https://developer.chrome.com/blog/new-in-chrome-116/&quot; rel=&quot;noopener&quot;&gt;Chrome 116&lt;/a&gt; became stable. This post takes a look at what that means for the web platform.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; We include browser compatibility data pulled from MDN in these posts which may not have been updated yet for very recent browser releases. The post will show the correct information as soon as it appears in the &lt;a href=&quot;https://github.com/mdn/browser-compat-data/releases&quot;&gt;browser-compat-data release&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Firefox 116 supports the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Audio_Output_Devices_API&quot; rel=&quot;noopener&quot;&gt;Audio Output Devices API&lt;/a&gt; on all platforms except for Android. This API allows web applications to redirect audio output to a permitted Bluetooth headset, speakerphone, or other device, instead of having to use the browser or underlying OS default.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox preview, Preview&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;preview&quot; title=&quot;Preview&quot; aria-label=&quot;Preview&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/MediaDevices/selectAudioOutput#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Chrome 116 includes CSS Motion Path allowing any graphical object to be animated it along a path specified by the developer. This allows a number of powerful new transform possibilities, such as positioning using polar coordinates (with the &lt;code&gt;ray()&lt;/code&gt; function) rather than the standard rectangular coordinates used by the &lt;code&gt;translate()&lt;/code&gt; function, or animating an element along a defined path. This makes it easier to define complex and beautiful 2d spatial transitions. A path can be specified as &lt;code&gt;circle()&lt;/code&gt;, &lt;code&gt;ellipse()&lt;/code&gt;, &lt;code&gt;rect()&lt;/code&gt;, &lt;code&gt;inset()&lt;/code&gt;, &lt;code&gt;xywh()&lt;/code&gt;, &lt;code&gt;polygon()&lt;/code&gt;, &lt;code&gt;ray()&lt;/code&gt; and &lt;code&gt;url()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Also in Chrome 116 is the &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/document-picture-in-picture/&quot; rel=&quot;noopener&quot;&gt;Document Picture-in-Picture API&lt;/a&gt;. This enables an always-on-top window that can be populated with arbitrary HTMLElements. This is an expansion upon the existing HTMLVideoElement API that only allows for an HTMLVideoElement to be put into a Picture-in-Picture (PiP) window.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Firefox 117 supports &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_nesting&quot; rel=&quot;noopener&quot;&gt;CSS Nesting&lt;/a&gt; and the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/Nesting_selector&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; nesting selector&lt;/a&gt;. This enables the nesting of one style rule inside another. This makes CSS Nesting interoperable with a caveat, Safari and Chrome implemented an older version of the spec, which did not allow nesting of &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/Type_selectors&quot; rel=&quot;noopener&quot;&gt;type selectors&lt;/a&gt;. Firefox has implemented the new version of the spec which does not require the &lt;code&gt;&amp;amp;&lt;/code&gt; nesting selector. You can see examples of both versions in &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/CSS_nesting/Using_CSS_nesting&quot; rel=&quot;noopener&quot;&gt;Using CSS Nesting&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 112, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      112
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 112, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
112
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 16.5, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
16.5
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/Nesting_selectors#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;beta-browser-releases&quot;&gt;Beta browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-08-2023/#beta-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beta browser versions give you a preview of things that will be in the next stable version of the browser. It&#39;s a great time to test new features, or removals, that could impact your site before the world gets that release. New betas are &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/118&quot; rel=&quot;noopener&quot;&gt;Firefox 118&lt;/a&gt; and &lt;a href=&quot;https://developer.chrome.com/blog/chrome-117-beta/&quot; rel=&quot;noopener&quot;&gt;Chrome 117&lt;/a&gt;. The &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 17&lt;/a&gt; beta is still ongoing. These releases bring many great features to the platform. Check out the release notes for all of the details, here are just a few highlights.&lt;/p&gt;
&lt;p&gt;There&#39;s not a lot of information available as yet for the next Firefox release. However, Chrome 117 promises some exciting features. For example, some new CSS features that &lt;a href=&quot;https://developer.chrome.com/blog/entry-exit-animations/&quot; rel=&quot;noopener&quot;&gt;enable entry and exit animations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;subgrid&lt;/code&gt; value for &lt;code&gt;grid-template-columns&lt;/code&gt; and &lt;code&gt;grid-template-rows&lt;/code&gt; is included in Chrome 117, making this longed for feature interoperable.&lt;/p&gt;
&lt;p&gt;Also in Chrome 117 is JavaScript array grouping with the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy&quot; rel=&quot;noopener&quot;&gt;Object.groupBy&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy&quot; rel=&quot;noopener&quot;&gt;Map.groupBy&lt;/a&gt; static methods.&lt;/p&gt;
&lt;p&gt;Safari 17 beta includes the &lt;code&gt;popover&lt;/code&gt; attribute, to add support for the &lt;a href=&quot;https://developer.chrome.com/blog/introducing-popover-api/&quot; rel=&quot;noopener&quot;&gt;Popover API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@courtneymcook&quot; rel=&quot;noopener&quot;&gt;Courtney Cook&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>To test or not to test, a technical perspective</title>
      <link href="https://web.dev/ta-what-to-test/"/>
      <updated>2023-08-23T00:00:00Z</updated>
      <id>https://web.dev/ta-what-to-test/</id>
      <content type="html" mode="escaped">&lt;p&gt;The &lt;a href=&quot;https://web.dev/ta-types/&quot;&gt;previous article&lt;/a&gt; covered the basics of test cases and what they should contain. This article delves deeper into the creation of test cases from a technical perspective, detailing what should be included in each test and what to avoid. Essentially, you&#39;ll learn the answer to the age-old questions of &amp;quot;What to test&amp;quot; or &amp;quot;What not to test&amp;quot;.&lt;/p&gt;
&lt;img alt=&quot;What to test or not to test.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/lwKU8pzIWPZiDg8ss7ad.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;general-guidelines-and-patterns&quot;&gt;General guidelines and patterns &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#general-guidelines-and-patterns&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;s worth noting that specific patterns and points are crucial, regardless of whether you&#39;re conducting unit, integration, or end-to-end tests. These principles can and should be applied to both types of testing, so they are a good place to start.&lt;/p&gt;
&lt;h3 id=&quot;keep-it-simple&quot;&gt;Keep it simple &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#keep-it-simple&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When it comes to writing tests, one of the most important things to remember is to keep it simple. It&#39;s important to consider the brain&#39;s capacity. The main production code takes up significant space, leaving little room for additional complexity. This is especially true for testing.&lt;/p&gt;
&lt;p&gt;If there&#39;s less headspace available, you may become more relaxed in your testing efforts. That&#39;s why it&#39;s crucial to prioritize simplicity in testing. In fact, Yoni Goldberg&#39;s &lt;a href=&quot;https://github.com/goldbergyoni/javascript-testing-best-practices#%EF%B8%8F-0-the-golden-rule-design-for-lean-testing&quot; rel=&quot;noopener&quot;&gt;JavaScript testing best practices&lt;/a&gt; emphasize the importance of the Golden Rule—your test should feel like an assistant and not like a complex mathematical formula. In other words, you should be able to understand your test&#39;s intent at first glance.&lt;/p&gt;
&lt;img alt=&quot;Don&amp;#x27;t make tests complex, they shouldn&amp;#x27;t feel this way.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/3r1qa9Ai1EMhb47Yiuuq.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;You should aim for simplicity in all types of tests, regardless of their complexity. In fact, the more complex a test is, the more critical it is to simplify it. One way to achieve this is through a flat test design, where tests are kept as simple as possible, and to only test what is necessary. This means each test should contain only one test case, and the test case should be focused on testing a single, specific functionality or feature.&lt;/p&gt;
&lt;p&gt;Think about it from this perspective: it should be easy to identify what went wrong when reading a failing test. This is why keeping tests simple and easy to understand is important. Doing so lets you quickly identify and fix issues when they arise.&lt;/p&gt;
&lt;h3 id=&quot;test-whats-worth-it&quot;&gt;Test what&#39;s worth it &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#test-whats-worth-it&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The flat test design also encourages focus and helps ensure your tests are meaningful. Remember, you don&#39;t want to create tests just for the sake of coverage—they should always have a purpose.&lt;/p&gt;
&lt;img alt=&quot;Don&amp;#x27;t test all the things.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/halb4R8zvaEdr85qhIIT.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In our &lt;a href=&quot;https://web.dev/ta-types/&quot;&gt;previous article&lt;/a&gt;, we discussed three key points to remember when prioritizing your testing efforts. These three priorities may help you decide whether the case in question should be included in your test. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;dont-test-implementation-details&quot;&gt;Don&#39;t test implementation details &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#dont-test-implementation-details&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One common problem in testing is that tests are often designed to test implementation details, such as using selectors in components or end-to-end tests. Implementation details refer to things that users of your code will not typically use, see, or even know about. This can lead to two major problems in tests: false negatives and false positives.&lt;/p&gt;
&lt;p&gt;False negatives occur when a test fails, even though the tested code is correct. This can happen when the implementation details change due to a refactoring of the application code. On the other hand, false positives occur when a test passes, even though the code being tested is incorrect.&lt;/p&gt;
&lt;p&gt;One solution to this problem is to consider the different types of users you have. End users and developers can differ in their approach, and they may interact with the code differently. When planning tests, it is essential to consider what users will see or interact with, and make the tests dependent on those things instead of the implementation details.&lt;/p&gt;
&lt;p&gt;For example, choosing selectors that are less prone to change can make tests more reliable: data-attributes instead of CSS selectors. For more details, refer to &lt;a href=&quot;https://kentcdodds.com/blog/testing-implementation-details&quot; rel=&quot;noopener&quot;&gt;Kent C. Dodds&#39; article&lt;/a&gt; on this topic, or stay tuned—an article on this topic is coming later.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; On the contrary, if you write tests well, this can also have positive implications on your source code structure, for example, when you consider the testability of your code. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;mocking-dont-lose-control&quot;&gt;Mocking: Don&#39;t lose control &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#mocking-dont-lose-control&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Mocking is a broad concept used in unit testing and sometimes in integration testing. It involves creating fake data or components to simulate dependencies that have complete control over the application. This allows for isolated testing.&lt;/p&gt;
&lt;p&gt;Using mocks in your tests can improve predictability, separation of concerns, and performance. And, if you need to conduct a test that requires human involvement (such as passport verification), you&#39;ll have to conceal it using a mock. For all these reasons, mocks are a valuable tool to consider.&lt;/p&gt;
&lt;p&gt;At the same time, mocking may affect the accuracy of the test because they are mocks, not the real user experiences. So you need to be mindful when using mocks and stubs.&lt;/p&gt;
&lt;h4 id=&quot;should-you-mock-in-end-to-end-tests&quot;&gt;Should you mock in end-to-end tests? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#should-you-mock-in-end-to-end-tests&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In general, no. However, mocking can be a lifesaver sometimes—so let&#39;s not rule it out completely.&lt;/p&gt;
&lt;p&gt;Imagine this scenario: you&#39;re writing a test for a feature involving a third-party payment provider service. You&#39;re in a sandbox environment that they have provided, meaning no real transactions are taking place. Unfortunately, the sandbox is malfunctioning, thereby causing your tests to fail. The fix needs to be done by the payment provider. All you can do is wait for the issue to be resolved by the provider.&lt;/p&gt;
&lt;p&gt;In this case, it might be more beneficial to lessen the dependency on services you cannot control.
It&#39;s still advisable to use mocking carefully in integration or end-to-end tests as it decreases the confidence level of your tests.&lt;/p&gt;
&lt;h2 id=&quot;test-specifics-dos-and-donts&quot;&gt;Test specifics: Dos and don&#39;ts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#test-specifics-dos-and-donts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So, all in all, what does a test contain? And are there differences between the testing types? Let&#39;s take a closer look at some specific aspects tailored to the main testing types.&lt;/p&gt;
&lt;h3 id=&quot;what-belongs-to-a-good-unit-test&quot;&gt;What belongs to a good unit test? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#what-belongs-to-a-good-unit-test&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An ideal and effective unit test should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Concentrate on specific aspects.&lt;/li&gt;
&lt;li&gt;Operate independently.&lt;/li&gt;
&lt;li&gt;Encompass small-scale scenarios.&lt;/li&gt;
&lt;li&gt;Use descriptive names.&lt;/li&gt;
&lt;li&gt;Follow the AAA pattern if applicable.&lt;/li&gt;
&lt;li&gt;Guarantee comprehensive test coverage.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Do ✅&lt;/th&gt;
&lt;th&gt;Don&#39;t ❌&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keep the tests as small as possible. Test one thing per test case.&lt;/td&gt;
&lt;td&gt;Write tests over large units.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always keep tests isolated and mock the things you need which are outside your unit.&lt;/td&gt;
&lt;td&gt;Include other components or services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep tests independent.&lt;/td&gt;
&lt;td&gt;Rely on previous tests or share test data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cover &lt;a href=&quot;https://web.dev/ta-test-cases/#test-paths-typical-kinds-of-test-cases&quot;&gt;different scenarios and paths&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Limit yourself to the happy path or negative tests at maximum.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use descriptive test titles, so you can immediately see what your test is about.&lt;/td&gt;
&lt;td&gt;Test by function name only, not being descriptive enough as a result: &lt;code&gt;testBuildFoo()&lt;/code&gt; or &lt;code&gt;testGetId()&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aim for good code coverage or a broader range of test cases, especially at this stage.&lt;/td&gt;
&lt;td&gt;Test from every class down to database (I/O) level.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;h3 id=&quot;what-belongs-to-a-good-integration-test&quot;&gt;What belongs to a good integration test? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#what-belongs-to-a-good-integration-test&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An ideal integration test shares some criteria with unit tests, too. However, there are a couple of additional points that you need to consider. A great integration test should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simulate interactions between components.&lt;/li&gt;
&lt;li&gt;Cover real-world scenarios, and use mocks or stubs.&lt;/li&gt;
&lt;li&gt;Consider performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Do ✅&lt;/th&gt;
&lt;th&gt;Don&#39;t ❌&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Test the integration points: verify that each unit works together gracefully when integrated with each other.&lt;/td&gt;
&lt;td&gt;Test each unit in isolation—that&#39;s what unit tests are for.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test real-world scenarios: use test data derived from real-world data.&lt;/td&gt;
&lt;td&gt;Use repetitive auto-generated test data or other data which doesn&#39;t reflect real-world use cases.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use mocks and stubs for external dependencies to maintain control of your complete test.&lt;/td&gt;
&lt;td&gt;Create dependencies on third-party services, for example, network requests to outside services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use a clean-up routine before and after each test.&lt;/td&gt;
&lt;td&gt;Forget to use clean-up measures inside your tests, otherwise this can lead to test failures or false positives, due to lack of proper test isolation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;h3 id=&quot;what-belongs-to-a-good-end-to-end-test&quot;&gt;What belongs to a good end-to-end test? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-what-to-test/#what-belongs-to-a-good-end-to-end-test&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A comprehensive end-to-end test should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Replicate user interactions.&lt;/li&gt;
&lt;li&gt;Encompass vital scenarios.&lt;/li&gt;
&lt;li&gt;Span multiple layers.&lt;/li&gt;
&lt;li&gt;Manage asynchronous operations.&lt;/li&gt;
&lt;li&gt;Verify results.&lt;/li&gt;
&lt;li&gt;Account for performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Do ✅&lt;/th&gt;
&lt;th&gt;Don&#39;t ❌&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Use API-driven shortcuts. &lt;a href=&quot;https://docs.cypress.io/guides/references/best-practices#Organizing-Tests-Logging-In-Controlling-State&quot; rel=&quot;noopener&quot;&gt;Learn more&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Use UI interactions for every step, including the &lt;code&gt;beforeEach&lt;/code&gt; hook.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use a clean-up routine before each test. Take even more care of test isolation than you do in unit and integration tests because there&#39;s a higher risk of side effects here.&lt;/td&gt;
&lt;td&gt;Forget to clean up after each test. If you don&#39;t clean up the leftover state, data or side effects, they will affect other tests executed later.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regard end-to-end tests as system tests. This means you need to test the whole application stack.&lt;/td&gt;
&lt;td&gt;Test each unit in isolation—that&#39;s what unit tests are for.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use minimal or no mocking inside the test. Consider carefully if you want to mock external dependencies.&lt;/td&gt;
&lt;td&gt;Rely heavily on mocks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consider performance and workload by, for example, not over-testing large scenarios in the same test.&lt;/td&gt;
&lt;td&gt;Cover large workflows without using shortcuts.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This blog post was written by Ramona, with input and review from &lt;a href=&quot;https://web.dev/authors/jecelynyeen/&quot;&gt;Jecelyn Yeen&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/jecfish&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/michael-hablich-2128646/&quot;&gt;Michael Hablich&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/MHablich&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://web.dev/authors/rachelandrew/&quot;&gt;Rachel Andrew&lt;/a&gt;, and &lt;a href=&quot;https://www.linkedin.com/in/sofia-yemelianova/&quot;&gt;Sofia Emelianova&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
</content>
      <author>
          <name>Ramona Schwering</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Defining test cases and priorities</title>
      <link href="https://web.dev/ta-test-cases/"/>
      <updated>2023-08-09T00:00:00Z</updated>
      <id>https://web.dev/ta-test-cases/</id>
      <content type="html" mode="escaped">&lt;p&gt;In the &lt;a href=&quot;https://web.dev/ta-strategies/&quot;&gt;previous post&lt;/a&gt;, you learned about testing strategies, the number of tests needed to test an application, and how to find the best fit to gain the most confidence in the results while bearing in mind your resources. However, this only gives us an idea of how much to test. You still need to determine exactly what to test.
The following three criteria can be helpful in understanding what to expect in a test and to see what testing type and level of detail might fit best:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Take care of your happy path&lt;/strong&gt;. This is the most generic or primary user story of your application, where your user will notice an error very quickly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decide carefully on the level of detail&lt;/strong&gt;. Get into more detail if your use case is vulnerable or where an error would cause high damage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prioritize lower-level tests&lt;/strong&gt;, such as unit and integration tests, over higher-level end-to-end tests whenever possible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The rest of this article explores these criteria, and how they apply as you define test cases.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-test-case&quot;&gt;What is a test case? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-test-cases/#what-is-a-test-case&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In software development, a test case is a sequence of actions or circumstances that are devised to confirm the effectiveness of a software program or application.
A test case aims to ensure that the software operates as planned and that all its features and functions perform correctly. Software testers or developers typically create these test cases to guarantee that the software meets the specified requirements and specifications.&lt;/p&gt;
&lt;img alt=&quot;Test case is verifying.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/Am7IXUF5DVMprZQsSA5p.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;When a test case is run, the software performs a series of checks to ensure it produces the desired results. While doing that, a test fulfills the following tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Verification&lt;/strong&gt;. The process of thoroughly checking software to ensure it functions without errors. Determining whether the created product meets all the necessary non-functional requirements and successfully achieves its intended purpose is crucial. The question it answers is: “Are we building the product right?”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation&lt;/strong&gt;. The process of ensuring that the software product meets the necessary standards or high-level requirements. It involves checking whether the actual product aligns with the expected product. Essentially, we’re answering the question: “Are we building the right product for the user’s requirements?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suppose the program fails to deliver the expected outcome. In that case, the test case will be the messenger—thus reporting an unsuccessful result, and the developer or tester will need to investigate the issue and find a solution.
Think of the checks and actions as paths the computer follows, regardless of the testing type.  Groups of input data or conditions used for checking are called &amp;quot;equivalence classes&amp;quot;. They should get similar behavior or results from the system under test. The specific paths executed inside a test may vary but should match the activities and assertions done in your test.&lt;/p&gt;
&lt;h2 id=&quot;test-paths-typical-kinds-of-test-cases&quot;&gt;Test paths: Typical kinds of test cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-test-cases/#test-paths-typical-kinds-of-test-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In software development, a &lt;a href=&quot;https://en.wikipedia.org/wiki/Happy_path&quot; rel=&quot;noopener&quot;&gt;test case&lt;/a&gt; is a code execution scenario from which a certain behavior is expected and tested. Typically, there are three scenarios to form test cases from.&lt;/p&gt;
&lt;img alt=&quot;The happy path.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/SyLaoC8VQymTbBwIUd11.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The first one is the most well known, which you are probably already using. It’s the &lt;em&gt;happy path&lt;/em&gt;, also known as the “happy day scenario” or “golden path”. It defines the most common use case of your feature, application, or change—the way it should work out for the customer.&lt;/p&gt;
&lt;img alt=&quot;The scary path.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/NJdAV9UgKuN8AhoaPBquL7giZQo1/7F0MGozRfVyyi3vn65No.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The second most crucial test path to cover in your test cases is often left out as it’s uncomfortable—as its name may imply. It’s the “scary path” or, in other words, the &lt;em&gt;negative test&lt;/em&gt;. This path targets scenarios that cause the code to misbehave or enter an error state. Testing these scenarios is especially important if you have highly vulnerable use cases imposing a high risk on the stakeholders or users.&lt;/p&gt;
&lt;p&gt;There are some other paths you might want to know about and consider using, but typically they are less commonly used. The following table summarizes them:&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test path&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Angry path&lt;/td&gt;
&lt;td&gt;This leads to an error, but an expected one; for example, if you want to ensure error handling works correctly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delinquent path&lt;/td&gt;
&lt;td&gt;This path takes care of any security-related scenarios your application needs to fulfill.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desolate path&lt;/td&gt;
&lt;td&gt;The path testing the scenario in your application doesn’t get enough data to function, for example, testing null values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetful path&lt;/td&gt;
&lt;td&gt;Testing the behavior of your application with insufficient resources, for example, triggering a data loss.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Indecisive path&lt;/td&gt;
&lt;td&gt;Testing with a user who is trying to do actions or following user stories in your application but hasn’t completed those workflows. This could be the case, for example, when the user interrupts their workflow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greedy path&lt;/td&gt;
&lt;td&gt;Trying to test using vast amounts of inputs or data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stressful path&lt;/td&gt;
&lt;td&gt;Trying to put a load on your application by any means necessary until it no longer functions (similar to a load test).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;There are several methods to categorize those paths. Two common approaches are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Equivalence partitioning&lt;/strong&gt;. A testing method that categorizes test cases into groups or partitions and, as a result, helps create equivalence classes. This is based on the idea that if one test case in a partition uncovers a defect, other test cases in the same partition will likely reveal similar defects. As all inputs within a specific equivalence class should exhibit identical behavior, you can decrease the number of test cases. &lt;a href=&quot;https://en.wikipedia.org/wiki/Equivalence_partitioning&quot; rel=&quot;noopener&quot;&gt;Learn more about equivalence partitioning&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limit analysis&lt;/strong&gt;. A testing method, also known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Boundary-value_analysis&quot; rel=&quot;noopener&quot;&gt;boundary-value analysis&lt;/a&gt;, that examines the limits or extremes of input values to find any potential issues or errors that might arise at the system&#39;s limits of capabilities or constraints.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;best-practice-writing-test-cases&quot;&gt;Best practice: Writing test cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-test-cases/#best-practice-writing-test-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A classical test case written by a tester will contain specific data to help you grasp the content of the test you want to conduct and, of course, execute the test. A typical tester would document their testing efforts in a table. There are two patterns we can use at this stage, helping us to structure our test cases and later, our tests themselves, too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Arrange, act, assert&lt;/strong&gt; pattern. The &amp;quot;arrange, act, assert&amp;quot; (also known as the &amp;quot;AAA&amp;quot; or &amp;quot;Triple A&amp;quot;) testing pattern is a way of organizing tests into three distinct steps: arranging the test, then performing the test, and last but not least, drawing conclusions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Given, when, then&lt;/strong&gt; pattern. This pattern is similar to the AAA pattern but has some roots in &lt;a href=&quot;https://en.wikipedia.org/wiki/Behavior-driven_development&quot; rel=&quot;noopener&quot;&gt;behavior-driven development&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Future articles will go into more details on these patterns, as soon as we cover the structure of a test itself. If you want to go deeper into these patterns at this stage, check out these two articles: &lt;a href=&quot;https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/&quot; rel=&quot;noopener&quot;&gt;Arrange-Act-Assert: A pattern for writing good tests&lt;/a&gt; and &lt;a href=&quot;https://martinfowler.com/bliki/GivenWhenThen.html&quot; rel=&quot;noopener&quot;&gt;Given-When-Then&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;According to all the learnings from this article, the following table summarizes a classic example:&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Information&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prerequisites&lt;/td&gt;
&lt;td&gt;Everything which needs to be done before writing the test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object under test&lt;/td&gt;
&lt;td&gt;What needs to be verified?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input data&lt;/td&gt;
&lt;td&gt;Variables and their values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steps to be executed&lt;/td&gt;
&lt;td&gt;All the things you will do to bring your test to life: all actions or interactions you do in your tests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expected result&lt;/td&gt;
&lt;td&gt;What should happen and which expectations are to be fulfilled.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actual result&lt;/td&gt;
&lt;td&gt;What actually happens.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;In automated testing, you don’t need to document all these test cases in the way that a tester needs to, even though it’s undoubtedly helpful to do so. You can find all this information in your test if you pay attention. So let’s translate this classical test case into an automated test.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Information&lt;/th&gt;
&lt;th&gt;Translation into test automation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prerequisites&lt;/td&gt;
&lt;td&gt;All the things you need, arranging the test, and thinking about what is given to make your test’s scenario happen.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object under test&lt;/td&gt;
&lt;td&gt;This “object” can be various things: an application, flow, unit, or component under test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input data&lt;/td&gt;
&lt;td&gt;Parameter values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steps to be executed&lt;/td&gt;
&lt;td&gt;All the actions and commands executed inside your test, the things you act upon, and finding out what happens when you do certain things.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expected result&lt;/td&gt;
&lt;td&gt;The assertion you use to validate your application, the things you assert upon in your application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actual result&lt;/td&gt;
&lt;td&gt;The result of your automated test.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This blog post was written by Ramona, with input and review from &lt;a href=&quot;https://web.dev/authors/jecelynyeen/&quot;&gt;Jecelyn Yeen&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/jecfish&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/michael-hablich-2128646/&quot;&gt;Michael Hablich&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/MHablich&quot;&gt;Twitter&lt;/a&gt;), and &lt;a href=&quot;https://web.dev/authors/rachelandrew/&quot;&gt;Rachel Andrew&lt;/a&gt;. Special thanks to &lt;a href=&quot;https://www.linkedin.com/in/sofia-yemelianova/&quot;&gt;Sofia Emelianova&lt;/a&gt; for supporting the publication process. &lt;/div&gt;&lt;/aside&gt;
</content>
      <author>
          <name>Ramona Schwering</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>New to the web platform in July</title>
      <link href="https://web.dev/web-platform-07-2023/"/>
      <updated>2023-07-31T00:00:00Z</updated>
      <id>https://web.dev/web-platform-07-2023/</id>
      <content type="html" mode="escaped">&lt;h2 id=&quot;stable-browser-releases&quot;&gt;Stable browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#stable-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In July 2023 &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/115&quot; rel=&quot;noopener&quot;&gt;Firefox 115&lt;/a&gt; and &lt;a href=&quot;https://developer.chrome.com/blog/new-in-chrome-115/&quot; rel=&quot;noopener&quot;&gt;Chrome 115&lt;/a&gt; became stable. This post takes a look at what that means for the web platform.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; We include browser compatibility data pulled from MDN in these posts which may not have been updated yet for very recent browser releases. The post will show the correct information as soon as it appears in the &lt;a href=&quot;https://github.com/mdn/browser-compat-data/releases&quot;&gt;browser-compat-data release&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;multiple-values-for-the-css-display-property&quot;&gt;Multiple values for the CSS &lt;code&gt;display&lt;/code&gt; property &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#multiple-values-for-the-css-display-property&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Chrome 115 includes multiple values for the CSS &lt;code&gt;display&lt;/code&gt; property. This means that &lt;code&gt;display: flex&lt;/code&gt; becomes &lt;code&gt;display: block flex&lt;/code&gt; and &lt;code&gt;display: block&lt;/code&gt; becomes &lt;code&gt;display: block flow&lt;/code&gt;. The single values are maintained as legacy keywords, these values are now available in the three major engines.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 115, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      115
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 70, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      70
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 115, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      115
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;scroll-driven-animations&quot;&gt;Scroll-driven animations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#scroll-driven-animations&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also in Chrome 115 are the &lt;code&gt;ScrollTimeline&lt;/code&gt; and &lt;code&gt;ViewTimeline&lt;/code&gt; extensions to the Web Animations specification. These enable &lt;a href=&quot;https://developer.chrome.com/articles/scroll-driven-animations/&quot; rel=&quot;noopener&quot;&gt;scroll-driven animations&lt;/a&gt; via CSS and JavaScript.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 115, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      115
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 115, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
115
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/ScrollTimeline#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;privacy-sandbox-apis&quot;&gt;Privacy Sandbox APIs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#privacy-sandbox-apis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Privacy Sandbox &lt;a href=&quot;https://developer.chrome.com/blog/privacy-sandbox-launch/&quot; rel=&quot;noopener&quot;&gt;relevance and measurement APIs&lt;/a&gt; shipped in Chrome 115. This includes the Topics, Protected Audience, Attribution Reporting, Private Aggregation, Shared Storage, and Fenced Frames APIs.&lt;/p&gt;
&lt;p&gt;To understand more about these APIs check out the &lt;a href=&quot;https://developer.chrome.com/blog/privacy-sandbox-demos/&quot; rel=&quot;noopener&quot;&gt;Privacy Sandbox demos&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-animation-composition-property&quot;&gt;The &lt;code&gt;animation-composition&lt;/code&gt; property &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#the-animation-composition-property&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Firefox 115 supports the CSS &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/animation-composition&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;animation-composition&lt;/code&gt;&lt;/a&gt; property. Making &lt;code&gt;animation-composition&lt;/code&gt; supported in all three major engines. Learn more in the article &lt;a href=&quot;https://developer.chrome.com/articles/css-animation-composition/&quot; rel=&quot;noopener&quot;&gt;Specify how multiple animation effects should composite with animation-composition&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 112, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      112
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 115, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      115
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 112, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      112
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 16, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/animation-composition#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;array-methods&quot;&gt;Array methods &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#array-methods&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also reaching interoperability with Firefox 115 are a set of methods for &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;TypedArray&lt;/code&gt;.  &lt;code&gt;Array.toReversed()&lt;/code&gt;, &lt;code&gt;Array.toSorted()&lt;/code&gt;, &lt;code&gt;Array.toSpliced()&lt;/code&gt;, &lt;code&gt;Array.with()&lt;/code&gt;, &lt;code&gt;TypedArrays.toReversed()&lt;/code&gt;, &lt;code&gt;TypedArrays.toSorted()&lt;/code&gt;, and &lt;code&gt;TypedArrays.with()&lt;/code&gt; return a new array with elements that have been shallow copied.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 110, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      110
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 115, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      115
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 110, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      110
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 16, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/toReversed#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;beta-browser-releases&quot;&gt;Beta browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-07-2023/#beta-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beta browser versions give you a preview of things that will be in the next stable version of the browser. It&#39;s a great time to test new features, or removals, that could impact your site before the world gets that release. New betas are &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/116&quot; rel=&quot;noopener&quot;&gt;Firefox 116&lt;/a&gt; and &lt;a href=&quot;https://developer.chrome.com/blog/chrome-116-beta/&quot; rel=&quot;noopener&quot;&gt;Chrome 116&lt;/a&gt;. The &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 17&lt;/a&gt;  and &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 16.6&lt;/a&gt; betas are still ongoing. These releases bring many great features to the platform. Check out the release notes for all of the details, here are just a few highlights.&lt;/p&gt;
&lt;p&gt;Firefox 116 supports the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Audio_Output_Devices_API&quot; rel=&quot;noopener&quot;&gt;Audio Output Devices API&lt;/a&gt; on all platforms except for Android. This API allows web applications to redirect audio output to a permitted Bluetooth headset, speakerphone, or other device, instead of having to use the browser or underlying OS default.&lt;/p&gt;
&lt;p&gt;Chrome 116 includes CSS Motion Path allowing any graphical object to be animated it along a path specified by the developer. This allows a number of powerful new transform possibilities, such as positioning using polar coordinates (with the &lt;code&gt;ray()&lt;/code&gt; function) rather than the standard rectangular coordinates used by the &lt;code&gt;translate()&lt;/code&gt; function, or animating an element along a defined path. This makes it easier to define complex and beautiful 2d spatial transitions. A path can be specified as &lt;code&gt;circle()&lt;/code&gt;, &lt;code&gt;ellipse()&lt;/code&gt;, &lt;code&gt;rect()&lt;/code&gt;, &lt;code&gt;inset()&lt;/code&gt;, &lt;code&gt;xywh()&lt;/code&gt;, &lt;code&gt;polygon()&lt;/code&gt;, &lt;code&gt;ray()&lt;/code&gt; and &lt;code&gt;url()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also in Chrome 116 is the &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/document-picture-in-picture/&quot; rel=&quot;noopener&quot;&gt;Document Picture-in-Picture API&lt;/a&gt;. This enables an always-on-top window that can be populated with arbitrary HTMLElements. This is an expansion upon the existing HTMLVideoElement API that only allows for an HTMLVideoElement to be put into a Picture-in-Picture (PiP) window.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ninjason&quot; rel=&quot;noopener&quot;&gt;Jason Leung&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Adapting typography to user preferences with CSS</title>
      <link href="https://web.dev/adapting-typography-to-user-preferences-with-css/"/>
      <updated>2023-07-27T00:00:00Z</updated>
      <id>https://web.dev/adapting-typography-to-user-preferences-with-css/</id>
      <content type="html" mode="escaped">&lt;p&gt;Bringing the user into the design process has been an exciting time for users,
designers and developers. Users can land on your experience and seamlessly begin
consuming content, their preferences richly integrated into the design result.&lt;/p&gt;
&lt;p&gt;This blog post explores using CSS media queries with a variable font to tailor
the reading experience even further. Font grade and weight can be customized
with &lt;code&gt;font-variation-settings&lt;/code&gt;, allowing microtuning given various preferences
and contexts, like a preference for dark mode or high contrast. We can take
these preferences and tailor a variable font for that user experience.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dark mode gets a slightly reduced gradation.&lt;/li&gt;
&lt;li&gt;High contrast gets a bolder font.&lt;/li&gt;
&lt;li&gt;Low contrast gets a thinner font.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-size=&quot;full&quot;&gt;
  &lt;video autoplay=&quot;&quot; controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/vS06HQ1YTsbMKSFTIPl2iogUQP73/cgGryLwncKVnBUQ8iQOF.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    &lt;a href=&quot;https://codepen.io/argyleink/pen/mdQrqvj&quot;&gt;https://codepen.io/argyleink/pen/mdQrqvj&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Follow along to understand each portion of the CSS and variable font that enable
this meaningful moment!&lt;/p&gt;
&lt;h2 id=&quot;getting-setup&quot;&gt;Getting setup &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#getting-setup&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To help focus on the CSS and font variation setting values, but also give us
something to read and see, here&#39;s the markup you can use to preview the work:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Variable font weight based on contrast preference&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  Lorem ipsum dolor sit amet consectetur adipisicing elit.&lt;br /&gt;  Officia, quod? Quidem, nemo aliquam, magnam rerum distinctio&lt;br /&gt;  itaque nisi nam, cupiditate dolorum ad sint. Soluta nemo&lt;br /&gt;  labore aliquid ex, dicta corporis.&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Without adding any CSS, the font size is already adaptive to user preferences.
Here&#39;s a video from another demo showing how setting &lt;code&gt;font-size&lt;/code&gt; in pixels will
squash any user preferences, and why you should set your font size in rems:&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/vS06HQ1YTsbMKSFTIPl2iogUQP73/8mxSKsYmv6K7zoqDor0F.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Lastly, to center and support the demo, a little CSS:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo.support&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;place-content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size-5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size-5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;text-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; balance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img alt=&quot;A screenshot preview of the demo so far, in both dark and light themes.&quot; decoding=&quot;async&quot; height=&quot;327&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/upVZBhu250ETgmczvTeh.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;This demo setup lets you begin testing and implementing this neat typography UX
feature.&lt;/p&gt;
&lt;h2 id=&quot;loading-the-roboto-flex-variable-font&quot;&gt;Loading the Roboto Flex variable font &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#loading-the-roboto-flex-variable-font&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The adaptive strategy depends on a variable font with meaningful axes for
customization, specifically you need &lt;code&gt;GRAD&lt;/code&gt; and &lt;code&gt;wght&lt;/code&gt;. The target adaptive user
preferences in this article are for color scheme and contrast, both of which
will tailor these axes to match the user&#39;s desired preference.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; A variable font is not required to achieve this user experience that matches preferences, however, using one achieves the effect without loading multiple weights or versions of a font. See &lt;a href=&quot;https://codepen.io/web-dot-dev/pen/zYMmevQ&quot;&gt;this demo&lt;/a&gt; for an example of this UX without a dependency on a variable font. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Load the variable font using the &lt;code&gt;@font-face&lt;/code&gt; API of CSS:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@font-face&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Roboto Flex&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string url&quot;&gt;&#39;https://assets.codepen.io/2585/RobotoFlex&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;truetype&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Next, apply the font to some content. The following CSS applies it to
everything:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo.support&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Roboto Flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img alt=&quot;A screenshot preview of the demo so far, with the font now in Roboto Flex in both dark and light themes.&quot; decoding=&quot;async&quot; height=&quot;327&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/vS06HQ1YTsbMKSFTIPl2iogUQP73/hfdJqPvkp2v8HvsH7x4o.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;css-custom-properties-and-media-queries-for-the-win&quot;&gt;CSS custom properties and media queries for the win &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#css-custom-properties-and-media-queries-for-the-win&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With the font loaded, you can query for user preferences and adapt the variable
font settings to match.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; If you need a review on some of these styles, check out the &lt;a href=&quot;https://web.dev/learn/css/&quot;&gt;Learn CSS&lt;/a&gt; module on &lt;a href=&quot;https://web.dev/learn/design/media-queries/&quot;&gt;media queries&lt;/a&gt; or this post on &lt;a href=&quot;https://web.dev/building-a-color-scheme/&quot;&gt;building an adaptive color scheme with custom properties&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;settings-when-theres-no-preferences-default&quot;&gt;Settings when there&#39;s no preferences (default) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#settings-when-theres-no-preferences-default&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The following initial styles will be the default styles, or another way to look
at it, the styles for users without any preferences.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;wght&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;GRAD&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-grade&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;settings-when-the-preference-is-for-high-contrast&quot;&gt;Settings when the preference is for high contrast &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#settings-when-the-preference-is-for-high-contrast&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For users who have indicated a preference for high contrast in their system
settings, increase the &lt;code&gt;--base-weight&lt;/code&gt; value from &lt;code&gt;400&lt;/code&gt; to &lt;code&gt;700&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; more&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 700&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now there&#39;s more contrast while reading.&lt;/p&gt;
&lt;h3 id=&quot;settings-when-the-preference-is-for-low-contrast&quot;&gt;Settings when the preference is for low contrast &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#settings-when-the-preference-is-for-low-contrast&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For users who have indicated a preference for low contrast in their system
settings, decrease the &lt;code&gt;--base-weight&lt;/code&gt; value from &lt;code&gt;400&lt;/code&gt; to &lt;code&gt;200&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; less&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now there&#39;s less contrast while reading.&lt;/p&gt;
&lt;h3 id=&quot;settings-when-the-preference-is-for-dark-mode&quot;&gt;Settings when the preference is for dark mode &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#settings-when-the-preference-is-for-dark-mode&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -25&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now the perceptual differences of light on dark vs dark on light have been
accounted for.&lt;/p&gt;
&lt;h3 id=&quot;all-together-now&quot;&gt;All together now &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/adapting-typography-to-user-preferences-with-css/#all-together-now&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;wght&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;GRAD&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-grade&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; more&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 700&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; less&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -25&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Or, for fun, all together with &lt;a href=&quot;https://developer.chrome.com/articles/css-nesting/&quot; rel=&quot;noopener&quot;&gt;CSS nesting&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@layer&lt;/span&gt; demo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;wght&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;GRAD&quot;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--base-grade&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; more&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 700 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; less&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--base-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--base-grade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -25 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The result is a reading experience that adapts the font to match the user&#39;s
preferences. Full source code is available below in the Codepen.&lt;/p&gt;
&lt;div class=&quot;codepen-embed-wrap&quot; style=&quot;height: 500px; width: 100%&quot;&gt;
&lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;&quot; loading=&quot;lazy&quot; src=&quot;https://codepen.io/web-dot-dev/embed/rNQZMzo?height=500&amp;theme-id=light&amp;default-tab=result&amp;editable=true&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;Pen rNQZMzo by web-dot-dev on Codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/web-dot-dev/embed/rNQZMzo&quot;&gt;Pen rNQZMzo by web-dot-dev on Codepen&lt;/a&gt;&lt;/iframe&gt;&lt;/div&gt;
</content>
      <author>
          <name>Adam Argyle</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Designing the user experience of passkeys on Google accounts</title>
      <link href="https://web.dev/passkey-google-ux/"/>
      <updated>2023-07-26T00:00:00Z</updated>
      <id>https://web.dev/passkey-google-ux/</id>
      <content type="html" mode="escaped">&lt;p&gt;Passkeys are a simple and &lt;a href=&quot;https://security.googleblog.com/2023/05/so-long-passwords-thanks-for-all-phish.html&quot; rel=&quot;noopener&quot;&gt;secure cross-device authentication
technology&lt;/a&gt;
that enables creating online accounts and signing in to them without entering a
password. To log in to an account, users are simply shown a prompt to to use the
screen lock on their device, such as touching the fingerprint sensor.&lt;/p&gt;
&lt;p&gt;Google has been working with the FIDO Alliance for years, alongside Apple and
Microsoft, to bring passkeys to the world. In 2022 we rolled out platform
support for passkeys so that
&lt;a href=&quot;https://android-developers.googleblog.com/2022/10/bringing-passkeys-to-android-and-chrome.html&quot; rel=&quot;noopener&quot;&gt;Android&lt;/a&gt;
and
&lt;a href=&quot;https://blog.chromium.org/2022/12/introducing-passkeys-in-chrome.html&quot; rel=&quot;noopener&quot;&gt;Chrome&lt;/a&gt;
users can seamlessly sign in to apps and websites across all their devices. In
May 2023, we enabled signing in to &lt;a href=&quot;https://blog.google/technology/safety-security/the-beginning-of-the-end-of-the-password/&quot; rel=&quot;noopener&quot;&gt;Google Accounts with
passkeys&lt;/a&gt;,
bringing the security and convenience of passkeys to our users.&lt;/p&gt;
&lt;p&gt;Google is in a unique position, as we are both working on the infrastructure for
passkeys and are one of the largest services using them. We are rolling out
passkeys for Google Accounts carefully and deliberately, so we can measure the
results and use that feedback to continue to improve the passkey infrastructure
and the Google account experience.&lt;/p&gt;
&lt;h2 id=&quot;transitioning-users-to-passkeys&quot;&gt;Transitioning users to passkeys &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#transitioning-users-to-passkeys&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Passwords have been the standard sign-in method since the advent of personalized
online experiences. How do we introduce the passwordless experience of passkeys?&lt;/p&gt;
&lt;p&gt;Research indicates that when it comes to authentication, users value the
convenience the most. They want a smooth and fast transition to the real
experience, which only comes after signing in.&lt;/p&gt;
&lt;p&gt;Still, the transition to passkeys requires changing muscle memory and users need
to be convinced it&#39;s worth making a switch.&lt;/p&gt;
&lt;p&gt;The user experience of passkeys for &lt;a href=&quot;http://google.com/&quot; rel=&quot;noopener&quot;&gt;Google.com&lt;/a&gt; has been
strategically designed to emphasize two principles at every step of the
authentication process: ease of use and security.&lt;/p&gt;
&lt;h3 id=&quot;leading-with-convenience&quot;&gt;Leading with convenience &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#leading-with-convenience&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
&lt;img alt=&quot;For most users, this will be the first time they see passkeys&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/UI5EioUkpDiMtUAdARnw.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;For most users, this will be the first time they see passkeys.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The first passkey screen users see is light and easy-to-digest.  The header is
focusing on the user benefit, saying &amp;quot;Simplify your sign in.&amp;quot;&lt;/p&gt;
&lt;p&gt;The body copy explains &amp;quot;With passkeys you can now use your fingerprint, face or
screen lock to verify it&#39;s really you&amp;quot;.&lt;/p&gt;
&lt;p&gt;The illustration is intended to ground the message in the value proposition made
by the page. The large blue primary action invites the user to proceed. &amp;quot;Not
now&amp;quot; is included as a secondary action to allow users to choose whether or not
to opt in at this time, leaving the user in control. And &amp;quot;Learn more&amp;quot; is offered
for the most curious users who would like to understand passkeys better before
proceeding.&lt;/p&gt;
&lt;p&gt;We explored many iterations of the pages used to introduce users to passkeys
during sign in. This included trying content that emphasized the security,
technology, and other aspects of passkeys—yet convenience was really what
resonated most. Google&#39;s content strategy, illustration, and interaction design
demonstrates this core principle for our implementation of passkeys.&lt;/p&gt;
&lt;h3 id=&quot;associating-the-term-passkeys-with-familiar-security-experiences&quot;&gt;Associating the term &amp;quot;passkeys&amp;quot; with familiar security experiences &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#associating-the-term-passkeys-with-familiar-security-experiences&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Passkeys are a new term for most users so we are intentionally gently exposing
the users to the term to build familiarity. Guided by internal research, we are
strategically associating passkeys with security.&lt;/p&gt;
&lt;p&gt;The word &amp;quot;passkey&amp;quot; is included throughout the sign-in flow in the less-prominent
body copy position.  It&#39;s consistently nestled amongst the familiar security
experiences that enable passkey use: fingerprint, face scan, or other device
screen lock.&lt;/p&gt;
&lt;p&gt;Our research has shown that many users associate biometrics with security. While
passkeys don&#39;t require biometrics (a passkey can be used with a device PIN, for
example), we are leaning into the association of passkeys with biometrics to
boost user perception of passkeys&#39; security benefits.&lt;/p&gt;
&lt;p&gt;The additional content behind the &amp;quot;Learn more&amp;quot; has lots of valuable information
for users, including reassurance for users that their sensitive, biometric data
stays on their personal device and is never stored or shared when creating or
using passkeys. We took this approach because most users found the convenience
aspect of passkeys appealing, but only a few took into account the biometric
element during testing.&lt;/p&gt;
&lt;h3 id=&quot;introducing-passkeys-when-its-relevant-to-the-user&quot;&gt;Introducing passkeys when it&#39;s relevant to the user &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#introducing-passkeys-when-its-relevant-to-the-user&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Google&#39;s heuristics carefully determine who will see the introductory screen.
Some of the factors are whether a user has two-step verification enabled and
whether they access that account regularly from the same device.&lt;/p&gt;
&lt;p&gt;Users who are most likely to succeed with passkeys are selected first, and over
time more users will be introduced (though, anyone can get started at
&lt;a href=&quot;http://g.co/passkeys&quot; rel=&quot;noopener&quot;&gt;g.co/passkeys&lt;/a&gt; today).&lt;/p&gt;
&lt;p&gt;Select users are prompted to create a passkey after signing in with a username
and password. There are a few reasons we chose this point in the user journey:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user has just signed in, they&#39;re aware of their credentials and second
step.&lt;/li&gt;
&lt;li&gt;We are confident that the user is on their device–they just signed in, so it&#39;s
unlikely they walked away or put their device down.&lt;/li&gt;
&lt;li&gt;Statistically, signing in isn&#39;t always successful the first time–so a message
around making it easier next time has tangible value.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;positioning-passkeys-as-an-alternative-to-passwords-and-not-yet-a-replacement&quot;&gt;Positioning passkeys as an alternative to passwords and not yet a replacement &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#positioning-passkeys-as-an-alternative-to-passwords-and-not-yet-a-replacement&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Initial user research shows that many users still want passwords as a backup
sign-in method. And not all users will have the &lt;a href=&quot;https://support.google.com/accounts/answer/13548313?hl=en&amp;amp;sjid=17510595681178318776-NA&quot; rel=&quot;noopener&quot;&gt;technology necessary to adopt
passkeys&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So while the industry, Google included, is moving towards a &amp;quot;passwordless
future&amp;quot;, Google is intentionally positioning passkeys as a simple and secure
&lt;strong&gt;alternative&lt;/strong&gt; to passwords. Google&#39;s UI focuses on the benefits of passkeys
and avoids language that implies getting rid of passwords.&lt;/p&gt;
&lt;h2 id=&quot;the-creation-moment&quot;&gt;The creation moment &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#the-creation-moment&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When users choose to enroll, they&#39;ll see a browser-specific UI modal that
enables them to create a passkey.&lt;/p&gt;
&lt;p&gt;The passkey itself is shown with the industry-aligned icon and the information
used to create it. This includes the display name (a friendly name for your
passkey, like your user&#39;s real name) and the username (a unique name on your
service–an email address can work great here). When it comes to working with the
passkeys icon, &lt;a href=&quot;https://media.fidoalliance.org/wp-content/uploads/2023/05/FIDO-Alliance-UX-Guidelines-for-Passkey-Creation-and-Sign-ins.pdf&quot; rel=&quot;noopener&quot;&gt;the FIDO alliance recommends using the proven passkeys
icon&lt;/a&gt;–and
encourages making it your own with customizations.&lt;/p&gt;
&lt;p&gt;Passkeys icon is shown consistently across the user journey to create a
familiarity with what the user will see when using or managing the passkey. The
passkey icon is never presented without context or supporting material.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;When users create their passkey, they&amp;#x27;ll see this page&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;When users create their passkey, they&#39;ll see this page.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Above, we outlined how the user and the platform work together to create a
passkey. When the user clicks &amp;quot;Continue&amp;quot; they&#39;ll be presented with a unique UI
depending on the platform.&lt;/p&gt;
&lt;p&gt;With that in mind, we learned through internal research that a confirmation
screen once the passkey is created can be very helpful in terms of comprehension
and closure at this step of the process.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Once the passkey has been created, users will see this page&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/sNqODRG8qqaGQc8ygbjO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;Once the passkey has been created, users will see this page.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The confirmation screen is a deliberate ‘pause&#39; to bookend the journey of
introducing a user to passkeys and going through the process of creating one of
their own. As it is (likely) the first time a user has engaged with passkeys,
this page aims to provide clear closure to the journey. We chose a standalone
page after trying some other tools like smaller notifications, and even a
post-creation email–simply to provide a structured, stable end to end
experience.&lt;/p&gt;
&lt;p&gt;Once the user clicks &amp;quot;Continue&amp;quot; here, they&#39;re brought to their destination.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;When users sign in again, they&amp;#x27;ll likely see this page&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/u7ugXsWYbGcylhCWZ21M.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;When users sign in again, they&#39;ll likely see this page.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;signing-in&quot;&gt;Signing in &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#signing-in&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Next time a user tries to sign in, they&#39;ll be greeted with this page. This uses
the same layout, illustration, and primary call to action to evoke the first
‘creation&#39; experience outlined above. Once the user has made a choice to enroll
in passkeys, this page should feel familiar and they will recognize what steps
they need to take to sign in.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;The user will use this WebAuthn UI to sign in&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kPbCZqaBDx5AFTZyi54a.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;The user will use this WebAuthn UI to sign in.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The same principle of familiarity applies here. Intentionally, this uses the
same iconography, illustration, layout and text. The text within the WebAuthn UI
is kept brief, broad, and re-usable–so everyone can use this both for
authentication and reauthentication.&lt;/p&gt;
&lt;h2 id=&quot;passkeys-management&quot;&gt;Passkeys management &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#passkeys-management&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Introducing a whole new page within the Google Account settings pages required
careful consideration to ensure a cohesive, intuitive, and consistent user
experience.&lt;/p&gt;
&lt;p&gt;To achieve this, we analyzed the patterns regarding navigation, content,
hierarchy, structure, and established expectations that existed across the
Google Account.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Passkeys management page in the Google Account&quot; decoding=&quot;async&quot; height=&quot;655&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/C0xuS6j8vd98Y17jckE3.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;Passkeys management page in the Google Account.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;describe-passkeys-by-ecosystem&quot;&gt;Describe passkeys by ecosystem &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#describe-passkeys-by-ecosystem&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To create a high level category system that would be logical to understand we
settled on describing passkeys by
&lt;a href=&quot;https://developers.google.com/identity/passkeys/supported-environments&quot; rel=&quot;noopener&quot;&gt;ecosystem&lt;/a&gt;.
This way, a user could recognize where a passkey was created and where it is
used. Each identity provider (Google, Apple, and Microsoft) has a name for their
ecosystem, so we chose to use those (Google Password Manager, iCloud keychain,
and Windows Hello respectively).&lt;/p&gt;
&lt;p&gt;To support this, we added additional metadata, such as when it was created, when
it was last used, and the specific OS that it was used on. In terms of user
management actions, the API only supports renaming, revoking, and creating.&lt;/p&gt;
&lt;p&gt;Renaming allows users to assign personally meaningful names to passkeys, which
could help particular cohorts of users keep track and understand them more
easily.&lt;/p&gt;
&lt;p&gt;Revoking a passkey doesn&#39;t delete it from the user&#39;s personal credential manager
(like Google Password Manager), but renders it unusable until it is set up
again. That&#39;s why we chose a cross, instead of a trash or delete icon, to
represent the action of revoking a passkey.&lt;/p&gt;
&lt;p&gt;When describing the action of adding a passkey to their account, the phrase
&amp;quot;Create passkey&amp;quot; resonated better with users compared to &amp;quot;Add a passkey.&amp;quot; This
is a subtle language choice to distinguish passkeys from tangible, hardware
security keys (though it should be noted that &lt;a href=&quot;https://support.google.com/accounts/answer/13548313?hl=en&amp;amp;sjid=17510595681178318776-NA&quot; rel=&quot;noopener&quot;&gt;passkeys can be stored on some
hardware security
keys&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;providing-additional-content&quot;&gt;Providing additional content &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#providing-additional-content&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Internal research showed that using passkeys is a relatively seamless and
familiar experience. However as with any new technology, there are lingering
questions and concerns that will come up for some users.&lt;/p&gt;
&lt;p&gt;How the technology works behind the screen lock, what makes it more secure, and
the most common &amp;quot;what if&amp;quot; scenarios Google came across in testing are addressed
in &lt;a href=&quot;https://support.google.com/accounts/answer/13548313?hl=en&amp;amp;sjid=17510595681178318776-NA&quot; rel=&quot;noopener&quot;&gt;Google&#39;s passkey Help Center
content&lt;/a&gt;.
Having support content ready with launch of passkeys is critical for an easy
transition for users on any site.&lt;/p&gt;
&lt;h3 id=&quot;falling-back-from-passkeys&quot;&gt;Falling back from passkeys &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#falling-back-from-passkeys&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Reverting to the old system is as simple as clicking &amp;quot;try another way&amp;quot; when a
user is asked to authenticate with a passkey. Additionally, exiting the WebAuthn
UI will start users on a path to try their passkey again, or sign into their
Google Account in traditional ways.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-google-ux/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We are still in the early days of passkeys, so when designing the user
experience keep a few principles in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce passkeys when it&#39;s relevant to the user.&lt;/li&gt;
&lt;li&gt;Highlight the benefits of passkeys.&lt;/li&gt;
&lt;li&gt;Use opportunities to build familiarity the concept of passkeys.&lt;/li&gt;
&lt;li&gt;Position passkeys as an alternative to passwords and not a replacement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The choices we made for passkeys for Google Accounts were informed by best
practices and internal research and we&#39;ll continue to evolve the user experience
as we gain new insights from users in the real world.&lt;/p&gt;
</content>
      <author>
          <name>Mitchell Galavan</name>
        </author><author>
          <name>Court Jacinic</name>
        </author><author>
          <name>Silvia Convento</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Pyramid or Crab? Find a testing strategy that fits</title>
      <link href="https://web.dev/ta-strategies/"/>
      <updated>2023-07-26T00:00:00Z</updated>
      <id>https://web.dev/ta-strategies/</id>
      <content type="html" mode="escaped">&lt;p&gt;Welcome back! The &lt;a href=&quot;https://web.dev/ta-types&quot;&gt;last article&lt;/a&gt; laid down lots of groundwork about how to approach the different testing types and what they contain, and clarified the testing type definitions. Remember this &lt;a href=&quot;https://web.dev/ta-types/#testing-in-all-shapes-how-does-this-all-work-together&quot;&gt;little meme image&lt;/a&gt;? You might have wondered how all those testing types you learned about could work together.&lt;/p&gt;
&lt;img alt=&quot;A cupboard with two drawers you can open at the same time.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/n3LPuwApNcCRT5S3zaoq.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Next, you will learn exactly that. This article gives an introduction on how to combine these testing types into reasonable strategies and choose one that matches your project.&lt;/p&gt;
&lt;p&gt;You can compare the strategies to a number of shapes to better grasp their meaning. Here&#39;s a list of strategies with respective sizes and development scopes.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;
          Application size
        &lt;/th&gt;
        &lt;th&gt;
          Team composition
        &lt;/th&gt;
        &lt;th&gt;
          Reliance on manual testing
        &lt;/th&gt;
        &lt;th&gt;
          Testing strategy
        &lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Small&lt;/td&gt;
        &lt;td&gt;Developers only&lt;/td&gt;
        &lt;td&gt;High&lt;/td&gt;
        &lt;td&gt;Testing Ice Cone&lt;br /&gt;Testing Crab&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Small&lt;/td&gt;
        &lt;td&gt;Developers &amp; QA engineers&lt;/td&gt;
        &lt;td&gt;High&lt;/td&gt;
        &lt;td&gt;Testing Ice Cone&lt;br /&gt;Testing Crab&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Small&lt;/td&gt;
        &lt;td&gt;Developers only&lt;/td&gt;
        &lt;td&gt;Low&lt;/td&gt;
        &lt;td&gt;Test Pyramid&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Large&lt;/td&gt;
        &lt;td&gt;Developers only&lt;/td&gt;
        &lt;td&gt;High&lt;/td&gt;
        &lt;td&gt;Testing Trophy&lt;br /&gt;Testing Diamond&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Large&lt;/td&gt;
        &lt;td&gt;Developers &amp; QA engineers&lt;/td&gt;
        &lt;td&gt;High&lt;/td&gt;
        &lt;td&gt;Testing Trophy&lt;br /&gt;Testing Crab&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Large&lt;/td&gt;
        &lt;td&gt;Developers only&lt;/td&gt;
        &lt;td&gt;Low&lt;/td&gt;
        &lt;td&gt;Testing Trophy&lt;br /&gt;Testing Honeycomb&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Let&#39;s take a closer look at the strategies and learn the meaning behind their names.&lt;/p&gt;
&lt;h2 id=&quot;determine-testing-goals-what-do-you-want-to-achieve-with-these-tests&quot;&gt;Determine testing goals: What do you want to achieve with these tests? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#determine-testing-goals-what-do-you-want-to-achieve-with-these-tests&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you can start building a good strategy, figure out your testing goal. When do you consider that your application has been sufficiently tested?&lt;/p&gt;
&lt;p&gt;Achieving high test coverage is often viewed as the ultimate goal for developers when it comes to testing. But is it always the best approach? There might be another critical factor to consider when deciding on a testing strategy—serving your users&#39; needs.&lt;/p&gt;
&lt;p&gt;As a developer, you also use many other applications and devices. In this respect, you are the user who relies on all these systems to “just work”. In turn, you rely on countless developers to do their best to make their applications and devices work. To turn this back around, as a developer, you also strive to live up to this trust. So your first goal should always be to ship working software and serve your users. This extends to the tests you write to ensure application quality. &lt;a href=&quot;https://kentcdodds.com/about&quot; rel=&quot;noopener&quot;&gt;Kent C. Dodds&lt;/a&gt; sums it up very well in his &lt;a href=&quot;https://kentcdodds.com/blog/static-vs-unit-vs-integration-vs-e2e-tests&quot; rel=&quot;noopener&quot;&gt;Static vs Unit vs Integration vs E2E Testing for Frontend Apps&lt;/a&gt; post:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    The more your tests resemble the way your software is used, the more confidence they can give you.
  &lt;/p&gt;
  &lt;cite&gt;
    by Kent C. Dodds
  &lt;/cite&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kent describes it as gaining confidence in tests. The closer you get to the users by choosing a testing type that fits, the more you can trust your tests to have valid results. In other words, the higher up you climb the pyramid, the more confident you get. But wait, what is the pyramid?&lt;/p&gt;
&lt;h2 id=&quot;determining-test-strategies-how-to-choose-a-testing-strategy&quot;&gt;Determining test strategies: How to choose a testing strategy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#determining-test-strategies-how-to-choose-a-testing-strategy&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a first step, determine which parts of the requirements you need to check to make sure they are met. Find out what test types to use and at what level of detail you can achieve the most confidence while maintaining an efficient cost structure. Many developers approach this topic by using analogies. Here are the most common ones, starting with the well-known classic.&lt;/p&gt;
&lt;img alt=&quot;A lot of shapes like pyramid, diamonds, ice cone, honeycombs and a trophy; representing test strategies.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/btUEUtD2bmqNwX2DcH4j.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;the-classic-the-test-pyramid&quot;&gt;The classic: The test pyramid &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#the-classic-the-test-pyramid&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As soon as you start looking for test strategies, you will probably come across the test automation pyramid as the first analogy. Mike Cohn introduced this concept in his book &amp;quot;Succeeding with Agile&amp;quot;. Later, Martin Fowler expanded upon the concept in his &lt;a href=&quot;https://martinfowler.com/articles/practical-test-pyramid.html&quot; rel=&quot;noopener&quot;&gt;Practical Test Pyramid&lt;/a&gt; article. You can represent the pyramid visually as the following:&lt;/p&gt;
&lt;img alt=&quot;The test pyramid.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/iEtr9phjNjENxQlFfJYv.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;As shown in this drawing, the test pyramid consists of three layers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Unit&lt;/strong&gt;. You find these tests at the base layer of the pyramid because they are fast to execute and simple to maintain. They are isolated and target the most minor test units. For example, see a typical &lt;a href=&quot;https://github.com/leichteckig/phpmagazin-jest-example/blob/main/product.test.js&quot; rel=&quot;noopener&quot;&gt;unit test&lt;/a&gt; for a very small product.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;. These tests are in the middle of the pyramid, because they have an acceptable execution speed but bring you closer to the user than the unit tests can. An example of an integration test is an &lt;a href=&quot;https://github.com/cypress-io/cypress-realworld-app/blob/develop/cypress/tests/api/api-users.spec.ts&quot; rel=&quot;noopener&quot;&gt;API test&lt;/a&gt;. You can also classify &lt;a href=&quot;https://github.com/leichteckig/nuxt-leichteckig/blob/main/test/components/MediaGrid.spec.js&quot; rel=&quot;noopener&quot;&gt;component tests&lt;/a&gt; as this type.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;E2E tests&lt;/strong&gt; (also called &lt;strong&gt;UI tests&lt;/strong&gt;). These tests simulate a genuine user and their interaction. Such tests need more time to execute and thus are more expensive. They are at at the top of the pyramid.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;confidence-versus-resources&quot;&gt;Confidence versus resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#confidence-versus-resources&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As briefly covered before, the order of the layers is no coincidence. They show the priorities and the corresponding costs. This gives you a clear picture of how many tests you should write for each layer. You have already seen this in the definition of the testing types.&lt;/p&gt;
&lt;p&gt;Because E2E tests are closest to your users, they give you the most confidence that you application is working as intended. However, they require a complete application stack and a simulated user, therefore, they are also potentially the most expensive. So the confidence is in direct competition with the resources you need to execute the tests.&lt;/p&gt;
&lt;img alt=&quot;The test pyramid with arrows showing the direction of confidence and resources required for different testing types.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/DT57buwCB4uDyJp61Rzb.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The pyramid tries to solve this problem by making you focus more on unit tests and strictly prioritize the cases covered by E2E tests. For example, your most crucial user journeys or the places most vulnerable to defects. As Martin Fowler emphasizes, the two most essential points in Cohn&#39;s pyramid are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write tests with different granularity.&lt;/li&gt;
&lt;li&gt;The more high level you get, the fewer tests you should have.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;pyramid-evolved-adaptations-of-the-test-pyramids&quot;&gt;Pyramid evolved! Adaptations of the test pyramids &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#pyramid-evolved-adaptations-of-the-test-pyramids&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For several years, discussions have revolved around the pyramid. The pyramid seems to oversimplify testing strategies, leaves out a lot of testing types, and no longer fits all the real-world projects. Therefore, it may be misleading. Has the pyramid fallen out of shape?
&lt;a href=&quot;https://rauchg.com/about&quot; rel=&quot;noopener&quot;&gt;Guillermo Rauch&lt;/a&gt; has an opinion about it:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    Write tests. Not too many. Mostly integration.
  &lt;/p&gt;
  &lt;cite&gt;
    by Guillermo Rauch
  &lt;/cite&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&#39;s one of the most commonly cited quotes on this subject, so let&#39;s break it down:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Write tests&amp;quot;. Not only because it builds trust, but also because it saves time in maintenance.&lt;/li&gt;
&lt;li&gt;&amp;quot;Not too many&amp;quot;. 100% coverage is not always good because then your testing isn&#39;t prioritized and there will be a lot of maintenance.&lt;/li&gt;
&lt;li&gt;&amp;quot;Mostly integration&amp;quot;. Here again the emphasis is on integration tests: they have the most business value by giving you a daily high confidence level while maintaining a reasonable execution time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This makes you think again about the testing pyramid and shift your focus to integration testing. Over the last few years, many adaptations have been proposed, so let&#39;s look at the most common ones.&lt;/p&gt;
&lt;h3 id=&quot;test-diamond&quot;&gt;Test diamond &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#test-diamond&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first adaptation removes the overemphasis on unit testing, as seen in the test pyramid. Imagine that you have reached 100% coverage on unit tests. However, the next time you refactor, you will have to update many of these unit tests and you might be tempted to skip them. So they erode.&lt;/p&gt;
&lt;p&gt;As a result, and together with the higher focus on integration testing, the following shape may arise:&lt;/p&gt;
&lt;img alt=&quot;The test diamond.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/vSFAkoSqbL4p984xf48k.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;A pyramid evolves into a diamond. You can see the previous three layers, but with a different size, and the unit layer has been cut:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit&lt;/strong&gt;. Write unit tests the way you defined them before. However, because they tend to erode, prioritize and cover only the most critical cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;. The integration tests you know, testing the combination of single units.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E2E&lt;/strong&gt;. This layer handles the UI tests similar to the test pyramid. Take care to only write E2E tests for the most critical test cases.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;testing-honeycomb&quot;&gt;Testing honeycomb &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#testing-honeycomb&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There is another adaptation, introduced by &lt;a href=&quot;https://engineering.atspotify.com/2018/01/testing-of-microservices/&quot; rel=&quot;noopener&quot;&gt;Spotify&lt;/a&gt;, that is similar to the test diamond but further specialized for microservices-based software systems. The testing honeycomb is another visual analogy for the granularity, scope, and number of tests to write for a &lt;a href=&quot;https://notes.paulswail.com/public/Testing+microservices&quot; rel=&quot;noopener&quot;&gt;microservices-based software system&lt;/a&gt;. Due to their small size, the most considerable complexity in a microservice is not within the service itself, but in how it interacts with others. So a testing strategy for a microservice should primarily focus on integration tests.&lt;/p&gt;
&lt;img alt=&quot;The testing honeycomb.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/mrM4QK1kEZgvRvltyiMn.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;This shape reminds us of a honeycomb, thus the name. It has the following layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Integrated tests&lt;/strong&gt;. The article by Spotify uses a quote from &lt;a href=&quot;https://blog.thecodewhisperer.com/permalink/integrated-tests-are-a-scam&quot; rel=&quot;noopener&quot;&gt;J. B. Rainsberger&lt;/a&gt; to define this layer: “A test that will pass or fail based on the correctness of another system.” Such tests have external dependencies that you need to consider, and on the contrary, your system might be a dependency that breaks other systems. Similar to E2E tests in other analogies, use these tests carefully, only for the most essential cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests&lt;/strong&gt;. Similar to other adaptations, you should focus on this layer. It contains tests that verify the correctness of your service in a more isolated fashion, but still in combination with other services. That means the tests will include some other systems too and focus on the interaction points, for example, via API tests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests on implementation details&lt;/strong&gt;. These tests resemble unit tests—tests that focus on parts of the code that are naturally isolated and thus have their own internal complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to find out more about this testing strategy, see the &lt;a href=&quot;https://martinfowler.com/articles/2021-test-shapes.html&quot; rel=&quot;noopener&quot;&gt;post that compares the test pyramid to the honeycomb&lt;/a&gt; by Martin Fowler and the &lt;a href=&quot;https://engineering.atspotify.com/2018/01/testing-of-microservices/&quot; rel=&quot;noopener&quot;&gt;original article from Spotify&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;testing-trophy&quot;&gt;Testing trophy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#testing-trophy&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can already see a repeating focus on integration tests. However, another type you came across in the previous article is not testing in theory but is still an important aspect you should consider in a testing strategy. Static analysis is missing from the test pyramid and in most of the adaptations you have seen so far. There&#39;s the testing trophy adaptation that takes static analysis into account while maintaining the focus on integration tests. The testing trophy originated from the earlier quote by Guillermo Rauch and was developed by Kent C. Dodds:&lt;/p&gt;
&lt;img alt=&quot;The testing trophy.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/ULNWIc7KY4jVjxPW5CdX.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The testing trophy is an analogy depicting the granularity of tests in a slightly different way. It has four layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Static analysis&lt;/strong&gt;. It plays a vital role in this analogy and lets you catch typos, style mistakes, and other bugs by merely running the debugging steps already outlined.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unit tests&lt;/strong&gt;. They ensure that your smallest unit is appropriately tested, but the testing trophy won&#39;t emphasize them to the same extent as the test pyramid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;. This is the main focus as it balances the cost and the higher confidence in the best way, as with other adaptations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI tests&lt;/strong&gt;. Including E2E and visual tests, they are at the top of the testing trophy, similar to their role in the test pyramid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To read more about the testing trophy, see the &lt;a href=&quot;https://kentcdodds.com/blog/static-vs-unit-vs-integration-vs-e2e-tests&quot; rel=&quot;noopener&quot;&gt;blog post by Kent C. Dodds&lt;/a&gt; on this subject.&lt;/p&gt;
&lt;h2 id=&quot;some-more-ui-focused-approaches&quot;&gt;Some more UI-focused approaches &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#some-more-ui-focused-approaches&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That&#39;s all well and good but no matter how you call your strategy, a “pyramid”, “honeycomb,” or “diamond”, there&#39;s still something missing. While test automation is valuable, it&#39;s important to remember that manual testing is still essential. Automated testing should alleviate routine tasks and free the quality assurance engineers to focus on crucial areas. Instead of replacing manual testing, automation should complement it. Is there a way to integrate manual testing with automation for optimal results?&lt;/p&gt;
&lt;h3 id=&quot;testing-ice-cone-and-testing-crab&quot;&gt;Testing ice cone and testing crab &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#testing-ice-cone-and-testing-crab&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are indeed two adaptations of the testing pyramid that focus more on these UI-focused ways of testing. Both have the advantage of high confidence, but are naturally more costly due to slower test execution.&lt;/p&gt;
&lt;p&gt;The first one, the test ice cone, looks like the pyramid in reverse. Without the manual testing step, it is also known as the testing pizza.&lt;/p&gt;
&lt;img alt=&quot;The testing ice cone.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/QdBKM36jvq93jrERrSCP.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The ice cone has bigger focus on manual or UI testing and the least focus on unit testing. It often takes shape in projects where developers started work with only a few thoughts on the testing strategy. The ice code is considered an anti-pattern and rightfully so. It is costly in terms of resources and manual work.&lt;/p&gt;
&lt;p&gt;The test crab is similar to the test ice cone, but with more emphasis on E2E and visual testing:&lt;/p&gt;
&lt;img alt=&quot;The testing crab.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/uY4XiFIldA1JySM9ZbHD.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;This testing strategy includes one more aspect: it verifies that your application functions and looks good. The testing crab highlights the importance of &lt;a href=&quot;https://docs.cypress.io/guides/tooling/visual-testing&quot; rel=&quot;noopener&quot;&gt;visual testing&lt;/a&gt;, defined in the &lt;a href=&quot;https://web.dev/ta-types/#visual-ui-testing&quot;&gt;previous article&lt;/a&gt;. Integration testing, divided into component and API testing, moves further into the background, and unit testing plays an even more secondary role here. You can find further details on this testing strategy in this &lt;a href=&quot;https://changelog.com/posts/the-testing-pyramid-should-look-more-like-a-crab&quot; rel=&quot;noopener&quot;&gt;article on the testing crab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While being more costly, these two testing strategies have their place: for example, in smaller projects where fewer tests are needed, or less complexity needs to be covered. In this case, a full-blown testing strategy focusing on integration testing might be over-engineered.&lt;/p&gt;
&lt;p&gt;Although these two testing strategies are more costly, they have their place, for example, in smaller projects that require fewer tests and don&#39;t need to cover a lot of complexity. In this case, a full scale testing strategy focused on integration testing may be unnecessarily complex.&lt;/p&gt;
&lt;h2 id=&quot;practical-advice-lets-strategize&quot;&gt;Practical advice: Let&#39;s strategize! &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-strategies/#practical-advice-lets-strategize&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You have now learned about the most common testing strategies. You started with the classic—the test pyramid—and got to know its many adaptations. Now you need to evaluate them for your product and decide which is be the best for your project. The answer to this question should start with everyone&#39;s favorite &amp;quot;&lt;strong&gt;It depends&lt;/strong&gt;&amp;quot;. That doesn&#39;t make it any less accurate though.&lt;/p&gt;
&lt;img alt=&quot;It depends.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/u1yCzUoUXkXAHUCgyrz2.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The choice of the most appropriate testing strategy from those described—and even the ones left out—depends on your application. It should fir your architecture, your requirements, and last but not least, your users and their requirements. All this might differ from application to application. That&#39;s completely normal. Remember that your most important goal is to serve your users, not a textbook definition.&lt;/p&gt;
&lt;p&gt;More often than not, real-world tests are difficult to separate and define individually. Even Martin Fowler himself emphasizes the &lt;a href=&quot;https://martinfowler.com/articles/2021-test-shapes.html&quot; rel=&quot;noopener&quot;&gt;positive aspect of differing definitions&lt;/a&gt;, such as in the case of unit tests. As &lt;a href=&quot;https://justin.searls.co/about/&quot; rel=&quot;noopener&quot;&gt;Justin Searls&lt;/a&gt; states correctly in &lt;a href=&quot;https://twitter.com/searls/status/1393385209089990659&quot; rel=&quot;noopener&quot;&gt;his tweet&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    […] write expressive tests that establish clear boundaries, run quickly &amp; reliably, and only fail for useful reasons.
  &lt;/p&gt;
  &lt;cite&gt;
    by Justin Searls
  &lt;/cite&gt;
&lt;/blockquote&gt;
&lt;p&gt;Focus on the tests that report actual errors that the users might encounter, and don&#39;t get distracted from your goal. Tests should be designed to benefit the user, not just provide 100% coverage or to debate which percentage of which testing type to write.&lt;/p&gt;
&lt;p&gt;Focus on tests that report real-life errors that your users might encounter and don&#39;t get distracted from your goal. Tests should be designed to benefit the user, not just provide 100% coverage or spark debates on what percentage of a particular testing type you should write.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This blog post was written by Ramona, with input and review from &lt;a href=&quot;https://web.dev/authors/jecelynyeen/&quot;&gt;Jecelyn Yeen&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/jecfish&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/michael-hablich-2128646/&quot;&gt;Michael Hablich&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/MHablich&quot;&gt;Twitter&lt;/a&gt;), and &lt;a href=&quot;https://www.linkedin.com/in/sofia-yemelianova/&quot;&gt;Sofia Emelianova&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
</content>
      <author>
          <name>Ramona Schwering</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>How Back/forward Cache Helped Yahoo! JAPAN News Increase Revenue by 9% on Mobile</title>
      <link href="https://web.dev/yahoo-japan-news-bfcache/"/>
      <updated>2023-07-25T00:00:00Z</updated>
      <id>https://web.dev/yahoo-japan-news-bfcache/</id>
      <content type="html" mode="escaped">&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/bfcache/&quot;&gt;Back/forward cache&lt;/a&gt; (or bfcache) is a browser optimization that enables instant back and forward navigation. It significantly improves the browsing experience for users, especially for websites that involve many back and forth navigations.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;web.dev article on bfcache &lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yahoo! JAPAN News, one of the most popular news platforms in Japan, drove a concerted effort to improve their bfcache hit rate and saw significant user experience and business improvements as a result. Specifically, the results of the A/B test they conducted showed that pages that use bfcache had a &lt;strong&gt;9% increase in ads revenue&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This case study will explain how Yahoo! JAPAN News removed the blockers for bfcache, and how bfcache drastically improved the user experience.&lt;/p&gt;
&lt;h2 id=&quot;removing-blockers-for-bfcache&quot;&gt;Removing blockers for bfcache &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-news-bfcache/#removing-blockers-for-bfcache&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;bfcache has been available since Chrome 86, and is also available on all modern browsers. However, taking full advantage of bfcache requires removing potential blockers on one&#39;s website. Some major blockers that Yahoo! JAPAN News faced were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use of &lt;code&gt;unload&lt;/code&gt; handlers&lt;/li&gt;
&lt;li&gt;Use of the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control#no-store&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;no-store&lt;/code&gt; directive&lt;/a&gt; on &lt;code&gt;Cache-control&lt;/code&gt; headers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can check what major blockers there are for your website by going to &lt;strong&gt;Chrome Dev Tools &amp;gt; Applications &amp;gt; Back/forward Cache&lt;/strong&gt; (&lt;a href=&quot;https://web.dev/bfcache/#test-to-ensure-your-pages-are-cacheable&quot;&gt;more details&lt;/a&gt;), or by using the &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/bfcache-notrestoredreasons/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;notRestoredReasons&lt;/code&gt; API&lt;/a&gt; to get a more comprehensive view of blockers based on actual usage in the field.&lt;/p&gt;
&lt;p&gt;Here&#39;s how Yahoo! JAPAN News has removed their blockers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unload Handlers:&lt;/strong&gt; Use the &lt;code&gt;pagehide&lt;/code&gt; event instead of &lt;code&gt;unload&lt;/code&gt; event, as the &lt;code&gt;unload&lt;/code&gt; event is &lt;a href=&quot;https://web.dev/bfcache/#never-use-the-unload-event&quot;&gt;very unreliable&lt;/a&gt;. Also, &lt;code&gt;permission-policy: unload&lt;/code&gt; was &lt;a href=&quot;https://chromestatus.com/feature/5579556305502208&quot; rel=&quot;noopener&quot;&gt;launched in Chrome 115&lt;/a&gt; so that the websites can reliably remove &lt;code&gt;unload&lt;/code&gt; handlers for specific origins. Chrome is also planning to &lt;a href=&quot;https://github.com/fergald/docs/blob/master/explainers/permissions-policy-deprecate-unload.md#logistics-of-deprecation&quot; rel=&quot;noopener&quot;&gt;gradually deprecate &lt;code&gt;unload&lt;/code&gt; handlers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Cache-control: no-store&lt;/code&gt;&lt;/strong&gt; (or CCNS for short): Changing the &lt;code&gt;Cache-control&lt;/code&gt; header from &lt;strong&gt;&lt;code&gt;no-store&lt;/code&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;code&gt;no-cache&lt;/code&gt;&lt;/strong&gt; can enable bfcache. Chrome is also planning to start &lt;a href=&quot;https://chromestatus.com/feature/6705326844805120&quot; rel=&quot;noopener&quot;&gt;caching for bfcache even with a &lt;code&gt;no-store&lt;/code&gt; header in certain circumstances&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CCNS is intended for pages that should never be cached under any circumstances. This comes with the caveat that any page with CCNS will not be able to benefit from any caching technology, including CDN edge servers and local caches.&lt;/p&gt;
&lt;p&gt;If you have a CCNS header, this is a great opportunity to discuss what the right &lt;code&gt;Cache-control&lt;/code&gt; strategies are for your website. Here are the main differences between &lt;code&gt;no-store&lt;/code&gt; and &lt;code&gt;no-cache&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;&lt;code&gt;Cache-control: &lt;strong&gt;no-store&lt;/strong&gt;&lt;/code&gt;&lt;/th&gt;
        &lt;th&gt;&lt;code&gt;Cache-control: &lt;strong&gt;no-cache&lt;/strong&gt;&lt;/code&gt;&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;ul&gt;
            &lt;li&gt;The response is not allowed to be stored in caches.&lt;/li&gt;
            &lt;li&gt;Consequently, the response is fetched in full on every request.&lt;/li&gt;
            &lt;li&gt;This should be used for private responses.&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/td&gt;
        &lt;td&gt;
          &lt;ul&gt;
            &lt;li&gt;The response is allowed to be stored in caches as long as it&#39;s revalidated with the server before each use.&lt;/li&gt;
            &lt;li&gt;This should be public responses you want revalidated every time (for example, the home page of a news website - though even then a very short caching time can improve performance and offload work from the main servers).&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;If you are interested in learning more about &lt;code&gt;Cache-control&lt;/code&gt; options, &lt;a href=&quot;https://web.dev/http-cache/?hl=en#flowchart&quot;&gt;this flowchart&lt;/a&gt; is a great help.&lt;/p&gt;
&lt;h2 id=&quot;impact-of-bfcache-in-numbers&quot;&gt;Impact of bfcache in numbers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-news-bfcache/#impact-of-bfcache-in-numbers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To measure the impact of bfcache, Yahoo! JAPAN News conducted an A/B test for 2 weeks, where they served a version of their pages with their bfcache fixes to one group, and a version with pages ineligible for bfcache to another. They picked the URL paths with a significant amount of traffic so that the test could achieve meaningful results. There were no other visual or functional difference between the 2 versions.&lt;/p&gt;
&lt;p&gt;Here&#39;s a video comparing the website with bfcache and without bfcache. You can see that the website with bfcache enabled loads significantly faster during a back or forward navigation.&lt;/p&gt;
&lt;style&gt;
  .bfcache-video video {
    height: auto;
  }
&lt;/style&gt;
&lt;figure class=&quot;bfcache-video&quot;&gt;
  &lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;800&quot; loop=&quot;&quot; muted=&quot;&quot; width=&quot;800&quot; style=&quot;--vid-width: 800; --vid-height: 800&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/2qqiTs9XuedWvtjfKuMu.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;/figure&gt;
&lt;p&gt;What&#39;s really promising is that the group with bfcache enabled had a &lt;strong&gt;significant increase in page views and ads revenue&lt;/strong&gt;, especially on mobile devices.&lt;/p&gt;
&lt;p&gt;Here are details about the impact observed by Yahoo! JAPAN News with their bfcache A/B test. (Further information can be found in &lt;a href=&quot;https://techblog.yahoo.co.jp/entry/2023072430429932/&quot; rel=&quot;noopener&quot;&gt;their case study article&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;/thead&gt;&lt;td&gt;
        &lt;strong&gt;Metrics&lt;/strong&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Uplift % (mobile)&lt;/strong&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Uplift % (desktop)&lt;/strong&gt;
      &lt;/td&gt;
    
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;bfcache hit rate&lt;/td&gt;
        &lt;td&gt;
          &lt;strong&gt;+54.03 points&lt;/strong&gt; (0.04% → 54.07%)
        &lt;/td&gt;
        &lt;td&gt;+47.28 points (0.02% → 47.30%)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Page views&lt;/td&gt;
        &lt;td&gt;
          &lt;strong&gt;+2.26%&lt;/strong&gt;
        &lt;/td&gt;
        &lt;td&gt;+0.65%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Ads revenue&lt;/td&gt;
        &lt;td&gt;
          &lt;strong&gt;+9.0%&lt;/strong&gt;
        &lt;/td&gt;
        &lt;td&gt;+0.6%&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;When back/forward navigations between pages become instantaneous with bfcache, users tend to stay on pages longer, thus increasing ad views, leading to an increase of ad revenue.&lt;/p&gt;
&lt;h2 id=&quot;bfcache-enhances-seamless-user-experience-on-the-website&quot;&gt;bfcache enhances seamless user experience on the website &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-news-bfcache/#bfcache-enhances-seamless-user-experience-on-the-website&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When pages load instantly, &lt;strong&gt;navigations feel more seamless.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Yahoo! JAPAN News, one of the major user journey is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to the article list&lt;/li&gt;
&lt;li&gt;Click on one article to read&lt;/li&gt;
&lt;li&gt;Go back to the article list&lt;/li&gt;
&lt;li&gt;Click on another article to read&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Before bfcache, when users finished reading an article (step 2), they had to wait for the article list page to load again. This could be a friction factor for users who just want to go back to the article list to pick out another article to read.&lt;/p&gt;
&lt;p&gt;Another source of friction during backward navigation was the scroll position. In practice, the browser tries to restore the scroll position when a backward navigation happens. However, because of dynamically-added ads or other layout changes, the scroll position often gets incorrectly restored, which could cause users to lose their bearings or even leave the page. This is never an issue when a backward navigation is powered by bfcache: the scroll position is immediately and correctly restored.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Two filmstrips of a backward navigation from an article to the article listing page. The top is a filmstrip of the process being handled with bfcache which takes 0.3 seconds, whereas the bottom is of the same process being handled without bfcache, which takes 3.3 seconds.&quot; decoding=&quot;async&quot; height=&quot;343&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WlJn1GZnDrSLpEPPHWAn.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Now with bfcache, the friction in the user journey is gone—users can instantly navigate back to the article list page and pick another article to read without having to wait for the article list page to load.&lt;/p&gt;
&lt;p&gt;The same thing happens when users browse from one article directly to another and back:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;An animated image showing the backward navigation flow from an article to the article listing page with and without bfcache. With bfcache, the backward navigation is not only faster, but the scroll position is accurately maintained. Without bfcache, these guarantees cannot be made.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pk7QmKzBA49ADdcJGE7q.gif?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In a nutshell, the benefits of using bfcache for Yahoo! JAPAN News includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increased pageviews: Users were more likely to navigate within the website when pages were cached with bfcache.&lt;/li&gt;
&lt;li&gt;Increased revenue: As a result of increased pageviews per session, ads impression increased, which resulted in a 9% increase in revenue on mobile compared with the test group without bfcache.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-news-bfcache/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In short, bfcache not only makes your website instant, but can also reduce friction in overall user experience and increase engagement within your website.&lt;/p&gt;
&lt;p&gt;The Chrome team is continually looking at bfcache blockers—especially the two reasons listed in this article as they are common reasons bfcache is not used. In the future, these may not prevent bfcache usage, but there&#39;s no need to wait until then. You can benefit from bfcache by looking at your bfcache blockers and avoiding these common, and other less common, patterns.&lt;/p&gt;
</content>
      <author>
          <name>Yuriko Hirota</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Three common types of test automation</title>
      <link href="https://web.dev/ta-types/"/>
      <updated>2023-07-12T00:00:00Z</updated>
      <id>https://web.dev/ta-types/</id>
      <content type="html" mode="escaped">&lt;p&gt;We&#39;ve all been there: what is a recurring coding meme that happens all too often in real life?
&lt;img alt=&quot;A cupboard with two drawers you cannot open at the same time.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/yl1OSGuWVIOsgLO6odFZ.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This meme sums it up quite nicely: each drawer works perfectly well individually, but in combination with the other drawer, they block each other and fail to function. You want both drawers to work well with each other and be operable at the same time.&lt;/p&gt;
&lt;img alt=&quot;The same cupboard but with two drawers you can open at the same time.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/2PY6rfmGkB26vX3qIbsj.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Apply this to web development: you wrote some tests, maybe even achieved 100% test coverage, but your application still needs to work once other parts fall into place. The units may work well on their own but not in relation to each other. Writing some tests is crucial but it&#39;s only one part of the ideal test setup for your project. As a very first step, you need to determine what parts of the application quality you need to ensure and how you can achieve that.&lt;/p&gt;
&lt;p&gt;Simply put, you need a plan before you start writing the actual test code. To approach the topic of how to test practically, let&#39;s start with a clean slate and answer two basic questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do you want to test?&lt;/li&gt;
&lt;li&gt;What do you want to test?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article focuses on the general things you need to know to answer the first question. To start from a common ground, let&#39;s first learn what testing modes exist and then focus on the common types of testing. In later articles, we will answer the second question, combine the answers, and find the testing strategy that works best for your project. Let&#39;s go! 🙌&lt;/p&gt;
&lt;h2 id=&quot;start-with-the-basics-general-testing-modes&quot;&gt;Start with the basics: General testing modes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#start-with-the-basics-general-testing-modes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When answering the question of how to test, the first point to clarify is very abstract. Should you test manually or let a computer take over? It&#39;s important, however, not to fall into binary thinking here.&lt;/p&gt;
&lt;h3 id=&quot;manual-testing-versus-automated-testing&quot;&gt;Manual testing versus automated testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#manual-testing-versus-automated-testing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you ask quality assurance engineers to define testing, they will probably break it down into two &amp;quot;modes&amp;quot; first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Manual testing&lt;/strong&gt;. This is a typical testing method conducted by actual people. A quality assurance engineer click through the application, check if it works and, at the same time, try to break it. The most common way is exploratory testing, where the engineer investigates the application using their knowledge of the application against a predefined path or checklist.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automated testing&lt;/strong&gt;. This is a type of testing conducted by a computer. Quality assurance engineers implement it to automate away repetitive and monotonous tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This series of guides will mostly focus on automated testing. However, you shouldn&#39;t focus on only one way of testing. Even if automation saves a lot of time and effort, humans and manual testing will always play a vital role. Rather, test automation should free up people to focus on exploratory testing and creative problem-solving. For example, ensuring the quality of user experiences or protecting the high-risk business logic. In other words, automation has your back. ❤️&lt;/p&gt;
&lt;h3 id=&quot;opaque-box-versus-clear-box&quot;&gt;Opaque box versus clear box &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#opaque-box-versus-clear-box&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So, you have defined the general modes of testing. However, that&#39;s not enough yet. To plan the testing strategy, there is one more question to answer: should you know how your application works under the hood or is it better to test without this knowledge? Depending on the answer, there are two procedures to choose from for deriving and selecting test cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Opaque box testing&lt;/strong&gt; (or black box testing). It is based on analyzing a component or system&#39;s functional or non-functional requirements (specifications) without considering its internal structure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clear box testing&lt;/strong&gt; (or white box testing) is a procedure that takes into account the internal structure of said box. In other words, how your application works under the hood.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both procedures can be applied to manual and automated testing. However, some aspects of general testing modes may focus more on one of the two—we will cover that later. For now, let&#39;s further break down test automation into types.&lt;/p&gt;
&lt;h2 id=&quot;test-automation-types-how-do-you-want-to-test&quot;&gt;Test automation types: How do you want to test? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#test-automation-types-how-do-you-want-to-test&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As you get closer to answering the &amp;quot;how&amp;quot; question, you have already decided to do some manual testing. However, choosing and applying test automation types is a bit more challenging. The types of automation testing are closely related to the metrics you want to create in your projects. So let&#39;s take a closer look at the most important ones.&lt;/p&gt;
&lt;p&gt;As illustrated in the meme mentioned earlier, you have already come across two types: unit testing and integration testing. End-to-end testing is the third important one to consider. But that isn&#39;t all of them still. Let&#39;s take a closer look.&lt;/p&gt;
&lt;h3 id=&quot;unit-testing&quot;&gt;Unit testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#unit-testing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unit testing is a testing type in which minor testable parts or units of an application are individually and independently tested for proper operation. These units can vary in scope from functions, classes, or interfaces, to services or complete components. Their primary attributes are execution speed, isolation, and comfortable maintainability. If you want to dive deeper into unit testing, head over to this &lt;a href=&quot;https://en.wikipedia.org/wiki/Unit_testing&quot; rel=&quot;noopener&quot;&gt;guide on unit testing&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;A simplified depiction of unit testing showing input and output.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/kVCbDIZN23OUGwOdpJmm.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Possible tools include but aren&#39;t limited to &lt;a href=&quot;https://vitest.dev/&quot;&gt;Vitest&lt;/a&gt; and &lt;a href=&quot;https://jestjs.io/&quot;&gt;Jest&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;integration-testing&quot;&gt;Integration testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#integration-testing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Integration testing focuses on interactions between components or systems. In other words, on how well they work together. Typical examples of integration tests are API or component tests.&lt;/p&gt;
&lt;img alt=&quot;A simplified depiction of integration testing showing how two unit working together.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/1dxHGzPGPDgkMqRMj46o.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The tools you may consider using are often the same as those mentioned in the &lt;a href=&quot;https://web.dev/ta-types/#unit-testing&quot;&gt;unit testing section&lt;/a&gt; and can also include frameworks providing component testing, for example, &lt;a href=&quot;https://webdriver.io/&quot;&gt;WebdriverIO&lt;/a&gt; and &lt;a href=&quot;https://www.cypress.io/&quot;&gt;Cypress&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;end-to-end-testing&quot;&gt;End-to-end testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#end-to-end-testing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These tests are often called UI tests and this name explains their function even better. These tests interact with your application&#39;s UI, including the complete application stack, and test your application from one end to the other.&lt;/p&gt;
&lt;img alt=&quot;A simplified depiction of end-to-end testing showing a computer as a robot, looking at a workflow.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/9ZWWlop306SoGFP9rbeH.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;They resemble a system test if you refer to the theory of quality assurance. These tests simulate a genuine user and their interactions. End-to-end tests take more runtime because they involve the whole system and more runtime requires more computing power. As a result, this additional effort results in higher maintenance costs.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The tools you might use for end-to-end testing include but aren&#39;t limited to &lt;a href=&quot;https://webdriver.io/&quot;&gt;WebdriverIO&lt;/a&gt;, &lt;a href=&quot;https://www.cypress.io/&quot;&gt;Cypress&lt;/a&gt;, &lt;a href=&quot;https://playwright.dev/&quot;&gt;Playwright&lt;/a&gt;, &lt;a href=&quot;https://www.selenium.dev/&quot;&gt;Selenium&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;visual-ui-testing&quot;&gt;Visual UI testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#visual-ui-testing&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;An interesting subcategory of UI tests is visual tests. These tests are extended end-to-end tests that provide a means to verify the visible output of an application. Such a test takes a screenshot after a change and another screenshot containing the “status quo” (or golden file), then provides those results to a human reviewer to inspect and check. In other words, it helps find “visual bugs” in the appearance of a page, beyond purely functional bugs and not explicitly written down into assertions.&lt;/p&gt;
&lt;h3 id=&quot;static-analysis&quot;&gt;Static analysis &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#static-analysis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&#39;s one more thing to introduce here: static analysis. It isn&#39;t a testing type in the textbook sense. However, it will be an essential aspect in quality assurance strategies later on. You can imagine it working like a spell check function: it scans your code for more significant defects and syntax errors without running the program, thus detecting code style issues. This simple measure can prevent many bugs. This is a good point to learn about Static Analysis if you want to get to know it in more detail.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The tools you might use for static analysis include but aren&#39;t limited to &lt;a href=&quot;https://eslint.org/&quot;&gt;Eslint&lt;/a&gt; and &lt;a href=&quot;https://stylelint.io/&quot;&gt;StyleLint&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;testing-in-all-shapes-how-does-this-all-work-together&quot;&gt;Testing in all shapes: How does this all work together? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/ta-types/#testing-in-all-shapes-how-does-this-all-work-together&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While searching for answers to all these questions, you might find a possible solution in some analogies. In the web and testing communities specifically, developers tend to use these analogies to give you an idea of how many tests you should use of which type.&lt;/p&gt;
&lt;img alt=&quot;A lot of shapes like pyramid, diamonds, ice cone, honeycombs and a trophy; representing test strategies.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/a96diycjrTQ2nVRpVgWH.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The following five strategies depicted in this image are the most common ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test Pyramid&lt;/li&gt;
&lt;li&gt;Test Diamond&lt;/li&gt;
&lt;li&gt;Test Ice Cone (also known as Test Pizza)&lt;/li&gt;
&lt;li&gt;Test Honeycomb&lt;/li&gt;
&lt;li&gt;Test Trophy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is truly a lot of information to process. How should you decide on a matching test strategy based on all this? Don&#39;t worry, we&#39;ve got you covered. In the next article, we will discuss these different strategies in more detail and explain how to choose the best fit for your project. Stay tuned! 🔥&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This blog post was written by Ramona, with input and review from &lt;a href=&quot;https://web.dev/authors/jecelynyeen/&quot;&gt;Jecelyn Yeen&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/jecfish&quot;&gt;Twitter&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/michael-hablich-2128646/&quot;&gt;Michael Hablich&lt;/a&gt; (&lt;a href=&quot;https://twitter.com/MHablich&quot;&gt;Twitter&lt;/a&gt;), and &lt;a href=&quot;https://www.linkedin.com/in/sofia-yemelianova/&quot;&gt;Sofia Emelianova&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
</content>
      <author>
          <name>Ramona Schwering</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>New to the web platform in June</title>
      <link href="https://web.dev/web-platform-06-2023/"/>
      <updated>2023-06-30T00:00:00Z</updated>
      <id>https://web.dev/web-platform-06-2023/</id>
      <content type="html" mode="escaped">&lt;h2 id=&quot;stable-browser-releases&quot;&gt;Stable browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-06-2023/#stable-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In June 2023 &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/114&quot; rel=&quot;noopener&quot;&gt;Firefox 114&lt;/a&gt; became stable, so it&#39;s a single browser issue this month. Check out the beta browser releases section for details of several features that are about to become interoperable once those betas become stable.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; We include browser compatibility data pulled from MDN in these posts which may not have been updated yet for very recent browser releases. The post will show the correct information as soon as it appears in the &lt;a href=&quot;https://github.com/mdn/browser-compat-data/releases&quot;&gt;browser-compat-data release&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;webtransport-api&quot;&gt;WebTransport API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-06-2023/#webtransport-api&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Firefox 114 includes the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebTransport_API&quot; rel=&quot;noopener&quot;&gt;WebTransport API&lt;/a&gt;, a modern update to WebSockets providing support for multiple streams, unidirectional streams, and out-of-order delivery.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 97, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      97
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 114, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      114
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 97, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      97
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/WebTransport#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;the-svg-crossorigin-attribute&quot;&gt;The SVG &lt;code&gt;crossorigin&lt;/code&gt; attribute &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-06-2023/#the-svg-crossorigin-attribute&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Firefox 114 also includes the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/SVG/Attribute/crossorigin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;crossorigin&lt;/code&gt; attribute&lt;/a&gt;, on the &lt;code&gt;&amp;lt;image&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;feImage&amp;gt;&lt;/code&gt; elements in SVG, provides support for configuration of the Cross-Origin Resource Sharing (CORS) requests for the element&#39;s fetched data. This works in the same way as the HTML &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/crossorigin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;crossorigin&lt;/code&gt;&lt;/a&gt; attribute.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox 114, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
114
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/SVGImageElement/crossorigin#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;beta-browser-releases&quot;&gt;Beta browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-06-2023/#beta-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beta browser versions give you a preview of things that will be in the next stable version of the browser. It&#39;s a great time to test new features, or removals, that could impact your site before the world gets that release. New betas are &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/115&quot; rel=&quot;noopener&quot;&gt;Firefox 115&lt;/a&gt;, and &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 17&lt;/a&gt; with &lt;a href=&quot;https://developer.chrome.com/blog/chrome-115-beta/&quot; rel=&quot;noopener&quot;&gt;Chrome 115&lt;/a&gt; and &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 16.6&lt;/a&gt; still ongoing. These releases bring many great features to the platform. Check out the release notes for all of the details, here are just a few highlights.&lt;/p&gt;
&lt;p&gt;Firefox 115 supports the CSS &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/animation-composition&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;animation-composition&lt;/code&gt;&lt;/a&gt; property. Once this version of Firefox becomes stable on July 4th, &lt;code&gt;animation-composition&lt;/code&gt; will be supported in all three major engines. Learn more in the article &lt;a href=&quot;https://developer.chrome.com/articles/css-animation-composition/&quot; rel=&quot;noopener&quot;&gt;Specify how multiple animation effects should composite with animation-composition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also reaching interoperability with Firefox 115 are a set of methods for &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;TypedArray&lt;/code&gt;.  &lt;code&gt;Array.toReversed()&lt;/code&gt;, &lt;code&gt;Array.toSorted()&lt;/code&gt;, &lt;code&gt;Array.toSpliced()&lt;/code&gt;, &lt;code&gt;Array.with()&lt;/code&gt;, &lt;code&gt;TypedArrays.toReversed()&lt;/code&gt;, &lt;code&gt;TypedArrays.toSorted()&lt;/code&gt;, and &lt;code&gt;TypedArrays.with()&lt;/code&gt; return a new array with elements that have been shallow copied.&lt;/p&gt;
&lt;p&gt;There is a whole stack of new features and fixes in the Safari 17 beta. Safari 17 adds &lt;a href=&quot;https://blog.tomayac.com/2023/06/07/web-apps-on-macos-sonoma-14-beta/&quot; rel=&quot;noopener&quot;&gt;Web Apps&lt;/a&gt; to macOS Sonoma. This means you can add a website to the Dock from the File menu or Share Sheet, and it will open in its own window.&lt;/p&gt;
&lt;p&gt;Safari 17 also brings some features to interoperable status—&lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-size&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;contain-intrinsic-size&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@counter-style&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;@counter-style&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@font-face/size-adjust&quot; rel=&quot;noopener&quot;&gt;@font-face size-adjust&lt;/a&gt;, and the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/overflow-block&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;overflow-block&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/overflow-inline&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;overflow-inline&lt;/code&gt;&lt;/a&gt; media features will be available in all major engines when Safari 17 ships.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rodrigospabreu&quot; rel=&quot;noopener&quot;&gt;Rodrigo Abreu&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>The origin private file system</title>
      <link href="https://web.dev/origin-private-file-system/"/>
      <updated>2023-06-08T00:00:00Z</updated>
      <id>https://web.dev/origin-private-file-system/</id>
      <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-good-bg color-state-good-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 128 128&quot; style=&quot;enable-background:new 0 0 128 128&quot; xml:space=&quot;preserve&quot;&gt;&lt;path d=&quot;M7.5 123.3c2.2 2.4 11.6-1.9 19-5.3C32 115.4 54 106.3 65 101.6c3-1.2 7.3-2.9 10.4-7 2.8-3.6 10-19-4.6-34.7-15-16-30.4-11.5-36.2-7.5A28.5 28.5 0 0 0 27.3 63c-5.2 11.6-12.7 32.9-15.7 41.3-2.3 6.1-6.4 16.5-4.1 19z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M18 86.8s.7 6.5 6.1 14.6c6.3 9.6 15 11.2 15 11.2l-5.8 2.4s-6.5-2-12.7-10.4c-3.8-5.3-5-11.6-5-11.6l2.3-6.2zm-5.6 15.4s1.5 5.6 4.7 9.7c3.8 5 8.6 6.5 8.6 6.5l-4.5 2s-3.3-.8-7-5.5c-2.9-3.5-3.7-7.6-3.7-7.6l1.9-5.1z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M10 116.4c-.2-.5-.2-1 0-1.4l25.4-53 4.2 16-26.8 38.7c-.7 1-2.3 1-2.8-.2z&quot; style=&quot;opacity:.44&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M41.6 83.2c12 14 25.5 12.2 30 8.6 4.5-3.5 8.1-15.6-3.7-29.3C55.3 48.2 41.3 52.2 38 55.3s-7.4 15.1 3.5 27.9z&quot; style=&quot;fill: var(--color-state-good-bg);&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M82.5 89c-4.3-3.7-6.6-3-9.7-1.8a26 26 0 0 1-18.9 0l2.6-6.2c5 1.7 8.7 1 12-1 4-2.4 9.6-5.6 18.3 1.6 3.6 3 7.3 5.1 10 4.2 2-.7 3-3.6 3.6-6l.2-1.3c.4-3.7 1.2-11.6 7.1-15.7 6.4-4.3 13-4.3 13-4.3l1.2 12c-3-.5-5.2.1-7 1-6.7 3.8-.8 18.2-11.3 23-10.1 4.8-18.4-3.3-21-5.6zM45.4 73.7l-4.3-3.9c8-8.9 5.8-15.4 4.3-20.2A26.4 26.4 0 0 1 44 38.8c-3-3.8-4.4-7.8-4.5-8-1.9-5.7-.5-11.2 2.8-16.4C48.7 4 60.5 4 60.5 4l4 10.5c-3-.1-12.8 0-15.8 4.8-3.8 6-1.3 9.6-1.2 10 .8-1 1.5-1.7 2.2-2.3 4.8-4.2 9-4.8 11.6-4.6a11 11 0 0 1 7.6 4.2c2 2.7 3 6.2 2.3 9.4a11 11 0 0 1-5.8 7.4 16 16 0 0 1-13 1.5v.3l.6 2c1.8 5.4 5 14.1-7.6 26.5zm7.4-37.5c.5.4 1.1.8 1.8 1 2 .8 4.4.6 7-.8 1.5-.9 1.7-1.7 1.7-2 .2-.9 0-2-.7-2.8a2.8 2.8 0 0 0-2-1.2c-1.6-.2-3.6.8-5.6 2.6-1 .9-1.7 2-2.3 3.2zm10 39.1-6.2-.1s3-16.7 12.5-19.5c1.8-.5 3.7-1 5.7-1.3l4-.8c.1-1.6-.5-3.6-1.3-5.9-.6-1.7-1.2-3.5-1.5-5.5-.6-3.9.4-7.3 3-9.6 3-2.9 7.9-3.8 13.4-2.5 3.2.7 5.5 2.2 7.6 3.6 2.9 2 4.6 3 8.2.5 4.3-2.9-1.4-14.3-4.4-21l11.3-4.6c1.5 3.3 8.8 20.3 4 30a11.5 11.5 0 0 1-8.1 6.2c-8 1.8-12.6-1.3-16-3.6-1.6-1-3-1.9-4.6-2.3-10.6-3 4.2 12.6-2.7 19.6-4.2 4.2-14.4 5.3-15 5.5-6.6 1.6-10 11.3-10 11.3z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M44 38.8c-.2 2.2-.3 3.5.3 6.4 2.7 2 8.7 2 8.7 2l-.6-2v-.3c-6.1-3-8.4-6.1-8.4-6.1zm-12.5 9.8-10.3-5 5.1-7.5 8.2 5.4zm-15.2-14A26 26 0 0 1 5 28.9l5.2-6c1.6 1.2 5 3.5 7.2 3.8l-1.1 7.9zM25.6 21.3 18 18.8a18 18 0 0 0 .7-8.3l7.9-1.3c.6 4 .3 8.2-1 12zM73 15.3l7.9-1.7L83 23.9l-7.8 1.7zM92.5 17.8 87 12c2.8-2.8 3.5-6.3 3.5-6.4L98.4 7c-.1.6-1.1 6.3-6 10.9zM95.5 48.6l7-2.2 2.3 7.7-7 2.1zM97.5 113l-7.9-1c.3-2.7-1.8-6.2-2.4-7l6.4-4.8c.5.6 4.7 6.4 4 12.8zM120.4 102.9c-3-.5-6-.6-9.1-.5l-.3-8c3.5-.2 7 0 10.6.6l-1.2 7.9zM109.6 113.9l5.6-5.7 7.8 7.6-5.6 5.7zM93.1 63.3 99 70l-6.6 5.8-5.8-6.6z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;strong&gt;Celebration&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; The origin private file system allows web apps to store and manipulate files in their very own origin-specific virtual filesystem, including low-level file manipulation, byte-by-byte access, and file streaming. The origin private file system is supported across all major browsers. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The origin private file system is supported by modern browsers and is standardized by the Web Hypertext Application Technology Working Group (&lt;a href=&quot;https://whatwg.org/&quot; rel=&quot;noopener&quot;&gt;WHATWG&lt;/a&gt;) in the &lt;a href=&quot;https://fs.spec.whatwg.org/&quot; rel=&quot;noopener&quot;&gt;File System Living Standard&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 86, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      86
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 86, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      86
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15.2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15.2
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/StorageManager/getDirectory#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#motivation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you think of files on your computer, you probably think about a file hierarchy: files organized in folders that you can explore with your operating system&#39;s file explorer. For example, on Windows, for a user called Tom, their To Do list might live in &lt;code&gt;C:\Users\Tom\Documents\ToDo.txt&lt;/code&gt;. In this example, &lt;code&gt;ToDo.txt&lt;/code&gt; is the file name, and &lt;code&gt;Users&lt;/code&gt;, &lt;code&gt;Tom&lt;/code&gt;, and &lt;code&gt;Documents&lt;/code&gt; are folder names. &lt;code&gt;C:\&lt;/code&gt; on Windows  represents the root directory of the drive.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In this article, I use the terms &lt;em&gt;folder&lt;/em&gt; and &lt;em&gt;directory&lt;/em&gt; interchangeably, disregarding the difference between the file system concept (directory) and the graphical user interface &lt;a href=&quot;https://en.wikipedia.org/wiki/Directory_%28computing%29#Folder_metaphor&quot;&gt;metaphor&lt;/a&gt; (folder). &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;traditional-way-of-working-with-files-on-the-web&quot;&gt;Traditional way of working with files on the web &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#traditional-way-of-working-with-files-on-the-web&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To edit the To Do list in a web application, this is the traditional flow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The user &lt;em&gt;uploads&lt;/em&gt; the file to a server or &lt;em&gt;opens&lt;/em&gt; it on the client with &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Element/input/file&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;file&amp;quot;&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The user makes their changes, and then &lt;em&gt;downloads&lt;/em&gt; the resulting file with an injected &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/HTMLAnchorElement/download&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;&amp;lt;a download=&amp;quot;ToDo.txt&amp;gt;&lt;/code&gt;&lt;/a&gt; that you programmatically &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/HTMLElement/click&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;click()&lt;/code&gt;&lt;/a&gt; via JavaScript.&lt;/li&gt;
&lt;li&gt;For opening folders, you use a special attribute in &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/HTMLInputElement/webkitdirectory&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;&amp;lt;input type=&amp;quot;file&amp;quot; webkitdirectory&amp;gt;&lt;/code&gt;&lt;/a&gt;, which, despite its proprietary name, has practically universal browser support.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;modern-way-of-working-with-files-on-the-web&quot;&gt;Modern way of working with files on the web &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#modern-way-of-working-with-files-on-the-web&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This flow is not representative of how users think of editing files, and means users end up with downloaded &lt;em&gt;copies&lt;/em&gt; of their input files. Therefore,  the File System Access API introduced three picker methods—&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/showOpenFilePicker&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;showOpenFilePicker()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/showSaveFilePicker&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;showSaveFilePicker()&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/showDirectoryPicker&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;showDirectoryPicker()&lt;/code&gt;&lt;/a&gt;—that do exactly what their name suggests. They enable a flow as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;ToDo.txt&lt;/code&gt; with &lt;code&gt;showOpenFilePicker()&lt;/code&gt;, and get a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileSystemFileHandle&lt;/code&gt;&lt;/a&gt; object.&lt;/li&gt;
&lt;li&gt;From the &lt;code&gt;FileSystemFileHandle&lt;/code&gt; object, get a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/File&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;File&lt;/code&gt;&lt;/a&gt; by calling the file handle&#39;s &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/getFile&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getFile()&lt;/code&gt;&lt;/a&gt; method.&lt;/li&gt;
&lt;li&gt;Modify the file, then call &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemHandle/requestPermission&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;requestPermission({mode: &#39;readwrite&#39;})&lt;/code&gt;&lt;/a&gt; on the handle.&lt;/li&gt;
&lt;li&gt;If the user accepts the permission request, save the changes back to the original file.&lt;/li&gt;
&lt;li&gt;Alternatively, call &lt;code&gt;showSaveFilePicker()&lt;/code&gt; and let the user pick a new file. (If the user picks a previously opened file, its contents will be overwritten.) For repeat saves, you can keep the file handle around, so you don&#39;t have to show the file save dialog again.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;restrictions-of-working-with-files-on-the-web&quot;&gt;Restrictions of working with files on the web &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#restrictions-of-working-with-files-on-the-web&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Files and folders that are accessible via these methods live in what can be called the &lt;em&gt;user-visible&lt;/em&gt; file system. Files saved from the web, and executable files specifically, are marked with the &lt;a href=&quot;https://textslashplain.com/2016/04/04/downloads-and-the-mark-of-the-web/&quot; rel=&quot;noopener&quot;&gt;mark of the web&lt;/a&gt;, so there&#39;s an additional warning the operating system can show before a potentially dangerous file gets executed. As an additional security feature, files obtained from the web are also protected by &lt;a href=&quot;https://safebrowsing.google.com/&quot; rel=&quot;noopener&quot;&gt;Safe Browsing&lt;/a&gt;, which, for the sake of simplicity and in the context of this article, you can think of as a cloud-based virus scan. When you write data to a file using the File System Access API, writes are  not in-place, but use a temporary file. The file itself is not modified unless it passes all these security checks. As you can imagine, this work makes file operations relatively slow, despite improvements applied where possible, for example, &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=1413443&quot; rel=&quot;noopener&quot;&gt;on macOS&lt;/a&gt;. Still every &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemWritableFileStream/write&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;write()&lt;/code&gt;&lt;/a&gt; call is self-contained, so under the hood it opens the file, seeks to the given offset, and finally writes data.&lt;/p&gt;
&lt;h3 id=&quot;files-as-the-foundation-of-processing&quot;&gt;Files as the foundation of processing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#files-as-the-foundation-of-processing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the same time, files are an excellent way to record data. For example, &lt;a href=&quot;https://www.sqlite.org/&quot; rel=&quot;noopener&quot;&gt;SQLite&lt;/a&gt; stores entire databases in a single file. Another example are &lt;a href=&quot;https://en.wikipedia.org/wiki/Mipmap&quot; rel=&quot;noopener&quot;&gt;mipmaps&lt;/a&gt; used in image processing. Mipmaps are pre-calculated, optimized sequences of images, each of which is a progressively lower resolution representation of the previous, which makes many operations like zooming faster. So how can web applications get the benefits of files, but without the performance costs of traditional web-based file processing? The answer is the &lt;em&gt;origin private file system&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-user-visible-versus-the-origin-private-file-system&quot;&gt;The user-visible versus the origin private file system &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#the-user-visible-versus-the-origin-private-file-system&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unlike the user-visible file system browsed via the operating system&#39;s file explorer, with files and folders you can read, write, move, and rename, the origin private file system is not meant to be seen by users. Files and folders in the origin private file system, as the name suggests, are private, and more concretely, private to the &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/Origin&quot; rel=&quot;noopener&quot;&gt;origin&lt;/a&gt; of a site. Discover the origin of a page by typing &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Location/origin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;location.origin&lt;/code&gt;&lt;/a&gt; in the DevTools Console. For example, the origin of the page &lt;code&gt;https://developer.chrome.com/articles/&lt;/code&gt; is &lt;code&gt;https://developer.chrome.com&lt;/code&gt; (that is, the part &lt;code&gt;/articles&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; part of the origin). You can read more about the theory of origins in &lt;a href=&quot;https://web.dev/same-site-same-origin/#origin&quot;&gt;Understanding &amp;quot;same-site&amp;quot; and &amp;quot;same-origin&amp;quot;&lt;/a&gt;. All pages that share the same origin can see the same origin private file system data, so &lt;code&gt;https://developer.chrome.com/docs/extensions/mv3/getstarted/extensions-101/&lt;/code&gt; can see the same details as the previous example. Each origin has its own independent origin private file system, which means the origin private file system of &lt;code&gt;https://developer.chrome.com&lt;/code&gt; is completely distinct from the one of, say, &lt;a href=&quot;https://web.dev/&quot;&gt;&lt;code&gt;https://web.dev&lt;/code&gt;&lt;/a&gt;. On Windows, the root directory of the user-visible file system is &lt;code&gt;C:\&lt;/code&gt;. The equivalent for the origin private file system is an initially empty root directory per origin accessed by calling the asynchronous method &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/StorageManager/getDirectory&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.storage.getDirectory()&lt;/code&gt;&lt;/a&gt;. For a comparison of the user-visible file system and the origin private file system, see the following diagram. The diagram shows that apart from the root directory, everything else is conceptually the same, with a hierarchy of files and folders to organize and arrange as needed for your data and storage needs.&lt;/p&gt;
&lt;img alt=&quot;Diagram of the user-visible file system and the origin private file system with two exemplary file hierarchies. The entry point for the user-visible file system is a symbolic harddisk, the entry point for the origin private file system is calling of the method &amp;#x27;navigator.storage.getDirectory&amp;#x27;.&quot; decoding=&quot;async&quot; height=&quot;722&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/xej6CL5VFJuGJgXPkeKJ.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;specifics-of-the-origin-private-file-system&quot;&gt;Specifics of the origin private file system &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#specifics-of-the-origin-private-file-system&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Just like other storage mechanisms in the browser (for example, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/localStorage&quot; rel=&quot;noopener&quot;&gt;localStorage&lt;/a&gt; or &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/IndexedDB_API/Using_IndexedDB&quot; rel=&quot;noopener&quot;&gt;IndexedDB&lt;/a&gt;), the origin private file system is subject to browser quota restrictions. When a user &lt;a href=&quot;https://support.google.com/chrome/answer/2392709&quot; rel=&quot;noopener&quot;&gt;clears all browsing data&lt;/a&gt; or &lt;a href=&quot;https://developer.chrome.com/docs/devtools/storage/cache/#deletecache&quot; rel=&quot;noopener&quot;&gt;all site data&lt;/a&gt;, the origin private file system will be deleted, too. Call &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/StorageManager/estimate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.storage.estimate()&lt;/code&gt;&lt;/a&gt; and in the resulting response object see the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/StorageManager/estimate#usage&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;usage&lt;/code&gt;&lt;/a&gt; entry to see how much storage your app already consumes, which is broken down by storage mechanism in the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/StorageManager/estimate#usagedetails&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;usageDetails&lt;/code&gt;&lt;/a&gt; object, where you want to look at the &lt;code&gt;fileSystem&lt;/code&gt; entry specifically. Since the origin private file system is not visible to the user, there are no permissions prompts and no Safe Browsing checks.&lt;/p&gt;
&lt;h2 id=&quot;getting-access-to-the-root-directory&quot;&gt;Getting access to the root directory &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#getting-access-to-the-root-directory&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To get access to the root directory, run the command below. You end up with an empty directory handle, more specifically, a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileSystemDirectoryHandle&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; opfsRoot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDirectory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// A FileSystemDirectoryHandle whose type is &quot;directory&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// and whose name is &quot;&quot;.&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opfsRoot&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;main-thread-or-web-worker&quot;&gt;Main thread or Web Worker &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#main-thread-or-web-worker&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are two ways of using the origin private file system: on the &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/Main_thread&quot; rel=&quot;noopener&quot;&gt;main thread&lt;/a&gt; or in a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Worker&quot; rel=&quot;noopener&quot;&gt;Web Worker&lt;/a&gt;. Web Workers cannot block the main thread, which means in this context APIs can be synchronous, a pattern generally disallowed on the main thread. Synchronous APIs can be faster as they avoid having to deal with promises, and file operations are typically synchronous in languages like C that can be compiled to WebAssembly.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// This is synchronous C code.&lt;/span&gt;&lt;br /&gt;FILE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;example.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fputs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Some text\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you need the fastest possible file operations and/or you deal with &lt;a href=&quot;https://developer.mozilla.org/es/docs/WebAssembly&quot; rel=&quot;noopener&quot;&gt;WebAssembly&lt;/a&gt;, skip down to &lt;a href=&quot;https://example.com/&quot; rel=&quot;noopener&quot;&gt;Using the origin private file system in a Web Worker&lt;/a&gt;. Else, you can read on.&lt;/p&gt;
&lt;h2 id=&quot;using-the-origin-private-file-system-on-the-main-thread&quot;&gt;Using the origin private file system on the main thread &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#using-the-origin-private-file-system-on-the-main-thread&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;creating-new-files-and-folders&quot;&gt;Creating new files and folders &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#creating-new-files-and-folders&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once you have a root folder, create files and folders using the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/getFileHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getFileHandle()&lt;/code&gt;&lt;/a&gt; and the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/getDirectoryHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getDirectoryHandle()&lt;/code&gt;&lt;/a&gt; methods respectively. By passing &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/getFileHandle#create&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;{create: true}&lt;/code&gt;&lt;/a&gt;, the file or folder will be created if it doesn&#39;t exist. Build up a hierarchy of files by calling these functions using a newly created directory as the starting point.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; directoryHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDirectoryHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first folder&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nestedFileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; directoryHandle&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first nested file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nestedDirectoryHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; directoryHandle&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDirectoryHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first nested folder&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img alt=&quot;The resulting file hierarchy from the earlier code sample.&quot; decoding=&quot;async&quot; height=&quot;196&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 438px) 438px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/VtWQ4T2a1gph0kFzhRwN.png?auto=format&amp;w=876 876w&quot; width=&quot;438&quot; /&gt;
&lt;h3 id=&quot;accessing-existing-files-and-folders&quot;&gt;Accessing existing files and folders &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#accessing-existing-files-and-folders&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you know their name, access previously created files and folders by calling the &lt;code&gt;getFileHandle()&lt;/code&gt; or the &lt;code&gt;getDirectoryHandle()&lt;/code&gt; methods, passing in the name of the file or folder.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingFileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingDirectoryHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDirectoryHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#39;my first folder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;getting-the-file-associated-with-a-file-handle-for-reading&quot;&gt;Getting the file associated with a file handle for reading &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#getting-the-file-associated-with-a-file-handle-for-reading&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;FileSystemFileHandle&lt;/code&gt; represents a file on the file system. To obtain the associated &lt;code&gt;File&lt;/code&gt;, use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/getFile&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getFile()&lt;/code&gt;&lt;/a&gt; method. A &lt;code&gt;File&lt;/code&gt; object is a specific kind of &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/Blob&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Blob&lt;/code&gt;&lt;/a&gt;, and can be used in any context that a &lt;code&gt;Blob&lt;/code&gt; can. In particular, &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/FileReader&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileReader&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/URL/createObjectURL&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;URL.createObjectURL()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/createImageBitmap&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;createImageBitmap()&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/send&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;XMLHttpRequest.send()&lt;/code&gt;&lt;/a&gt; accept both &lt;code&gt;Blobs&lt;/code&gt; and &lt;code&gt;Files&lt;/code&gt;. If you will, obtaining a &lt;code&gt;File&lt;/code&gt; from a &lt;code&gt;FileSystemFileHandle&lt;/code&gt; &amp;quot;frees&amp;quot; the data, so you can access it and make it available to the user-visible file system.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;writing-to-a-file-by-streaming&quot;&gt;Writing to a file by streaming &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#writing-to-a-file-by-streaming&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Stream data into a file by calling &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/createWritable&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;createWritable()&lt;/code&gt;&lt;/a&gt; which creates a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemWritableFileStream&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileSystemWritableFileStream&lt;/code&gt;&lt;/a&gt; to that you then &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemWritableFileStream/write&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;write()&lt;/code&gt;&lt;/a&gt; the contents. At the end, you need to &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WritableStream/close&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/a&gt; the stream.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contents &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Some text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Get a writable stream.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; writable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWritable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Write the contents of the file to the stream.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; writable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contents&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Close the stream, which persists the contents.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; writable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;deleting-files-and-folders&quot;&gt;Deleting files and folders &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#deleting-files-and-folders&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Delete files and folders by calling their file or directory handle&#39;s particular &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemHandle/remove&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;remove()&lt;/code&gt;&lt;/a&gt; method. To delete a folder including all subfolders, pass the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemHandle/remove#recursive&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;{recursive: true}&lt;/code&gt;&lt;/a&gt; option.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;recursive&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The &lt;code&gt;remove()&lt;/code&gt; method is currently only implemented in Chrome. You can feature-detect support via &lt;code&gt;&#39;remove&#39; in FileSystemFileHandle.prototype&lt;/code&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;As an alternative, if you know the name of the to-be-deleted file or folder in a directory, use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/removeEntry&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;removeEntry()&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeEntry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first nested file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; As a quick tip, &lt;code&gt;await (await navigator.storage.getDirectory()).remove({recursive: true})&lt;/code&gt; is the fastest way to clear the entire origin private file system. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;moving-and-renaming-files-and-folders&quot;&gt;Moving and renaming files and folders &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#moving-and-renaming-files-and-folders&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Rename and move files and folders using the &lt;a href=&quot;https://github.com/whatwg/fs/pull/10&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;move()&lt;/code&gt;&lt;/a&gt; method. Moving and renaming can happen together or in isolation.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Rename a file.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my first renamed file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Move a file to another directory.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nestedDirectoryHandle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Move a file to another directory and rename it.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nestedDirectoryHandle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;my first renamed and now nested file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Renaming and moving folders is not implemented yet in Chrome. You also can&#39;t move files from the origin private file system to the user-visible file system. You can &lt;a href=&quot;https://web.dev/origin-private-file-system/#copying-a-file-from-the-origin-private-file-system-to-the-user-visible-file-system&quot;&gt;copy&lt;/a&gt; them, though. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;resolving-the-path-of-a-file-or-folder&quot;&gt;Resolving the path of a file or folder &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#resolving-the-path-of-a-file-or-folder&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To learn where a given file or folder is located  in relation to a reference directory, use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/resolve&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;resolve()&lt;/code&gt;&lt;/a&gt; method, passing it a &lt;code&gt;FileSystemHandle&lt;/code&gt; as the argument. To obtain the full path of a file or folder in the origin private file system, use the root directory as the reference directory obtained via &lt;code&gt;navigator.storage.getDirectory()&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; relativePath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nestedDirectoryHandle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// `relativePath` is `[&#39;my first folder&#39;, &#39;my first nested folder&#39;]`.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;checking-if-two-file-or-folder-handles-point-to-the-same-file-or-folder&quot;&gt;Checking if two file or folder handles point to the same file or folder &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#checking-if-two-file-or-folder-handles-point-to-the-same-file-or-folder&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes you have two handles and don&#39;t know if they point at the same file or folder. To check whether this is the case, use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemHandle/isSameEntry&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;isSameEntry()&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSameEntry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nestedFileHandle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Returns `false`.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;listing-the-contents-of-a-folder&quot;&gt;Listing the contents of a folder &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#listing-the-contents-of-a-folder&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;FileSystemDirectoryHandle&lt;/code&gt; is an &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols&quot; rel=&quot;noopener&quot;&gt;asynchronous iterator&lt;/a&gt; that you iterate over with a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for-await...of&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;for await…of&lt;/code&gt;&lt;/a&gt; loop. As an asynchronous iterator, it also supports the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/entries&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;entries()&lt;/code&gt;&lt;/a&gt;, the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/values&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;values()&lt;/code&gt;&lt;/a&gt;, and the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemDirectoryHandle/keys&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;keys()&lt;/code&gt;&lt;/a&gt; methods, from which you can choose depending on what information you need:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; handle &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; name &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;recursively-listing-the-contents-of-a-folder-and-all-subfolders&quot;&gt;Recursively listing the contents of a folder and all subfolders &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#recursively-listing-the-contents-of-a-folder-and-all-subfolders&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Dealing with asynchronous loops and functions paired with recursion is easy to get wrong. The function below can serve as a starting point for listing the contents of a folder and all its subfolders, including all files and their sizes. You can simplify the function if you don&#39;t need the file sizes by, where it says &lt;code&gt;directoryEntryPromises.push&lt;/code&gt;, not pushing the &lt;code&gt;handle.getFile()&lt;/code&gt; promise, but the &lt;code&gt;handle&lt;/code&gt; directly.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getDirectoryEntriesRecursive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    relativePath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileHandles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; directoryHandles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; entries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Get an iterator of the files and folders in the directory.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; directoryIterator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; directoryHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; directoryEntryPromises &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handle &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; directoryIterator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nestedPath &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;relativePath&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        fileHandles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nestedPath &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        directoryEntryPromises&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;          handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kind&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;lastModified&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastModified&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;relativePath&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nestedPath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              handle&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;directory&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        directoryHandles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nestedPath &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        directoryEntryPromises&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kind&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;relativePath&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nestedPath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token literal-property property&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDirectoryEntriesRecursive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nestedPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;              handle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; directoryEntries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;directoryEntryPromises&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    directoryEntries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;directoryEntry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      entries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;directoryEntry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; directoryEntry&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; entries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;using-the-origin-private-file-system-in-a-web-worker&quot;&gt;Using the origin private file system in a Web Worker &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#using-the-origin-private-file-system-in-a-web-worker&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As outlined before, Web Workers can&#39;t block the main thread, which is why in this context synchronous methods are allowed.&lt;/p&gt;
&lt;h3 id=&quot;getting-a-synchronous-access-handle&quot;&gt;Getting a synchronous access handle &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#getting-a-synchronous-access-handle&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The entry point to the fastest possible file operations is a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileSystemSyncAccessHandle&lt;/code&gt;&lt;/a&gt;, obtained from a regular &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FileSystemFileHandle&lt;/code&gt;&lt;/a&gt; by calling &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;createSyncAccessHandle()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;my highspeed file.txt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; syncAccessHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createSyncAccessHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; It might seem confusing, but you actually get a &lt;em&gt;synchronous&lt;/em&gt; &lt;code&gt;FileSystemSyncAccessHandle&lt;/code&gt; from a regular &lt;code&gt;FileSystemFileHandle&lt;/code&gt;. Also note that the &lt;code&gt;createSyncAccessHandle()&lt;/code&gt; method is &lt;em&gt;asynchronous&lt;/em&gt;, despite the &lt;code&gt;Sync&lt;/code&gt; in its name. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;synchronous-in-place-file-methods&quot;&gt;Synchronous in-place file methods &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#synchronous-in-place-file-methods&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once you have a synchronous access handle, you get access to fast in-place file methods that are all synchronous.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/getSize&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getSize()&lt;/code&gt;&lt;/a&gt;: Returns the size of the file in bytes.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/write&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;write()&lt;/code&gt;&lt;/a&gt;: Writes the content of a buffer into the, optionally at a given offset, and returns the number of written bytes. Checking the returned number of written bytes allows callers to detect and handle errors and partial writes.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/read&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;read()&lt;/code&gt;&lt;/a&gt;: Reads the contents of the file into a buffer, optionally at a given offset.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/truncate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;truncate()&lt;/code&gt;&lt;/a&gt;: Resizes the file to the given size.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/flush&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;flush()&lt;/code&gt;&lt;/a&gt;: Ensures that the contents of the file contain all the modifications done through &lt;code&gt;write()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FileSystemSyncAccessHandle/close&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/a&gt;: Closes the access handle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is an example that uses all the methods mentioned above.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; opfsRoot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDirectory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;fast&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; accessHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createSyncAccessHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; textEncoder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TextEncoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; textDecoder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TextDecoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Initialize this variable for the size of the file.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// The current size of the file, initially `0`.&lt;/span&gt;&lt;br /&gt;size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Encode content to write to the file.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; textEncoder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Some text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Write the content at the beginning of the file.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Flush the changes.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// The current size of the file, now `9` (the length of &quot;Some text&quot;).&lt;/span&gt;&lt;br /&gt;size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Encode more content to write to the file.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; moreContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; textEncoder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;More content&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Write the content at the end of the file.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;moreContent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Flush the changes.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// The current size of the file, now `21` (the length of&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// &quot;Some textMore content&quot;).&lt;/span&gt;&lt;br /&gt;size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Prepare a data view of the length of the file.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dataView &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArrayBuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Read the entire file into the data view.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataView&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Logs `&quot;Some textMore content&quot;`.&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;textDecoder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataView&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Read starting at offset 9 into the data view.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataView&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Logs `&quot;More content&quot;`.&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;textDecoder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataView&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Truncate the file after 4 bytes.&lt;/span&gt;&lt;br /&gt;accessHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;truncate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Note that the first parameter for &lt;code&gt;read()&lt;/code&gt; and &lt;code&gt;write()&lt;/code&gt; is an &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer&quot;&gt;&lt;code&gt;ArrayBuffer&lt;/code&gt;&lt;/a&gt; or an &lt;code&gt;ArrayBufferView&lt;/code&gt; like a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/DataView&quot;&gt;&lt;code&gt;DataView&lt;/code&gt;&lt;/a&gt;. You cannot directly manipulate the contents of an &lt;code&gt;ArrayBuffer&lt;/code&gt;. Instead, you create one of the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypedArray&quot;&gt;typed array objects&lt;/a&gt; like an &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int8Array&quot;&gt;&lt;code&gt;Int8Array&lt;/code&gt;&lt;/a&gt; or a &lt;code&gt;DataView&lt;/code&gt; object which represents the buffer in a specific format, and use that to read and write the contents of the buffer. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;copying-a-file-from-the-origin-private-file-system-to-the-user-visible-file-system&quot;&gt;Copying a file from the origin private file system to the user-visible file system &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#copying-a-file-from-the-origin-private-file-system-to-the-user-visible-file-system&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned above, moving files from the origin private file system to the user-visible file system isn&#39;t possible, but you can copy files. Since &lt;code&gt;showSaveFilePicker()&lt;/code&gt; is only exposed on the main thread, but not in the Worker thread, be sure to run the code there.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// On the main thread, not in the Worker. This assumes&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// `fileHandle` is the `FileSystemFileHandle` you obtained&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// the `FileSystemSyncAccessHandle` from in the Worker&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// thread. Be sure to close the file in the Worker thread first.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; opfsRoot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFileHandle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;fast&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Obtain a file handle to a new file in the user-visible file system&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// with the same name as the file in the origin private file system.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; saveHandle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;showSaveFilePicker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;suggestedName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; writable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; saveHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWritable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; writable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; fileHandle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; writable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;debugging-the-origin-private-file-system&quot;&gt;Debugging the origin private file system &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#debugging-the-origin-private-file-system&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Until built-in DevTools support is added (see &lt;a href=&quot;https://crbug.com/1284595&quot; rel=&quot;noopener&quot;&gt;crbug/1284595&lt;/a&gt;), use the &lt;a href=&quot;https://chrome.google.com/webstore/detail/opfs-explorer/acndjpgkpaclldomagafnognkcgjignd&quot; rel=&quot;noopener&quot;&gt;OPFS Explorer&lt;/a&gt; Chrome extension to debug the origin private file system. The screenshot above from the section &lt;a href=&quot;https://web.dev/origin-private-file-system/#creating-new-files-and-folders&quot;&gt;Creating new files and folders&lt;/a&gt; is taken straight from the extension by the way.&lt;/p&gt;
&lt;img alt=&quot;The OPFS Explorer Chrome DevTools extension in the Chrome Web Store.&quot; decoding=&quot;async&quot; height=&quot;612&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/kmE7qbP61UlLcCxBkMMQ.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;After installing the extension, open the Chrome DevTools, select the &lt;strong&gt;OPFS Explorer&lt;/strong&gt; tab, and you&#39;re then ready to inspect the file hierarchy. Save files from the origin private file system to the user-visible file system by clicking the file name and delete files and folders by clicking the trash can icon.&lt;/p&gt;
&lt;h2 id=&quot;demo&quot;&gt;Demo &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#demo&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;See the origin private file system in action (if you install the OPFS Explorer extension) in a &lt;a href=&quot;https://sqlite-wasm-opfs.glitch.me/&quot; rel=&quot;noopener&quot;&gt;demo&lt;/a&gt; that uses it as a backend for a SQLite database compiled to WebAssembly. Be sure to check out the &lt;a href=&quot;https://glitch.com/edit/#!/sqlite-wasm-opfs&quot; rel=&quot;noopener&quot;&gt;source code on Glitch&lt;/a&gt;. Note how the embedded version below does not use the origin private file system backend (because the iframe is cross-origin), but when you open the demo in a separate tab, it does.&lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/sqlite-wasm-opfs?attributionHidden=true&amp;sidebarCollapsed=true&amp;previewSize=100&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;sqlite-wasm-opfs on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The origin private file system, as specified by the WHATWG, has shaped the way we use and interact with files on the web. It has enabled new use cases that were impossible to achieve with the user-visible file system. All major browser vendors—Apple, Mozilla, and Google—are on-board and share a joint vision. The development of the origin private file system is very much a collaborative effort, and feedback from developers and users is essential to its progress. As we continue to refine and improve the standard, feedback on the &lt;a href=&quot;https://github.com/whatwg/fs&quot; rel=&quot;noopener&quot;&gt;whatwg/fs repository&lt;/a&gt; in the form of Issues or Pull Requests is welcome.&lt;/p&gt;
&lt;h2 id=&quot;related-links&quot;&gt;Related links &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#related-links&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fs.spec.whatwg.org/&quot; rel=&quot;noopener&quot;&gt;File System Standard spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/whatwg/fs&quot; rel=&quot;noopener&quot;&gt;File System Standard repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webkit.org/blog/12257/the-file-system-access-api-with-origin-private-file-system/&quot; rel=&quot;noopener&quot;&gt;The File System API with Origin Private File System WebKit post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/opfs-explorer/acndjpgkpaclldomagafnognkcgjignd&quot; rel=&quot;noopener&quot;&gt;OPFS Explorer extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/origin-private-file-system/#acknowledgements&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article was reviewed by &lt;a href=&quot;https://github.com/a-sully&quot; rel=&quot;noopener&quot;&gt;Austin Sully&lt;/a&gt;, &lt;a href=&quot;https://ca.linkedin.com/in/enoel19&quot; rel=&quot;noopener&quot;&gt;Etienne Noël&lt;/a&gt;, and &lt;a href=&quot;https://rachelandrew.co.uk/&quot; rel=&quot;noopener&quot;&gt;Rachel Andrew&lt;/a&gt;. Hero image by &lt;a href=&quot;https://unsplash.com/@rumpf&quot; rel=&quot;noopener&quot;&gt;Christina Rumpf&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/XWDMmk-yW7Q&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
</content>
      <author>
          <name>Thomas Steiner</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>New CSS color spaces and functions in all major engines</title>
      <link href="https://web.dev/color-spaces-and-functions/"/>
      <updated>2023-06-02T00:00:00Z</updated>
      <id>https://web.dev/color-spaces-and-functions/</id>
      <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-good-bg color-state-good-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 128 128&quot; style=&quot;enable-background:new 0 0 128 128&quot; xml:space=&quot;preserve&quot;&gt;&lt;path d=&quot;M7.5 123.3c2.2 2.4 11.6-1.9 19-5.3C32 115.4 54 106.3 65 101.6c3-1.2 7.3-2.9 10.4-7 2.8-3.6 10-19-4.6-34.7-15-16-30.4-11.5-36.2-7.5A28.5 28.5 0 0 0 27.3 63c-5.2 11.6-12.7 32.9-15.7 41.3-2.3 6.1-6.4 16.5-4.1 19z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M18 86.8s.7 6.5 6.1 14.6c6.3 9.6 15 11.2 15 11.2l-5.8 2.4s-6.5-2-12.7-10.4c-3.8-5.3-5-11.6-5-11.6l2.3-6.2zm-5.6 15.4s1.5 5.6 4.7 9.7c3.8 5 8.6 6.5 8.6 6.5l-4.5 2s-3.3-.8-7-5.5c-2.9-3.5-3.7-7.6-3.7-7.6l1.9-5.1z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M10 116.4c-.2-.5-.2-1 0-1.4l25.4-53 4.2 16-26.8 38.7c-.7 1-2.3 1-2.8-.2z&quot; style=&quot;opacity:.44&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M41.6 83.2c12 14 25.5 12.2 30 8.6 4.5-3.5 8.1-15.6-3.7-29.3C55.3 48.2 41.3 52.2 38 55.3s-7.4 15.1 3.5 27.9z&quot; style=&quot;fill: var(--color-state-good-bg);&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M82.5 89c-4.3-3.7-6.6-3-9.7-1.8a26 26 0 0 1-18.9 0l2.6-6.2c5 1.7 8.7 1 12-1 4-2.4 9.6-5.6 18.3 1.6 3.6 3 7.3 5.1 10 4.2 2-.7 3-3.6 3.6-6l.2-1.3c.4-3.7 1.2-11.6 7.1-15.7 6.4-4.3 13-4.3 13-4.3l1.2 12c-3-.5-5.2.1-7 1-6.7 3.8-.8 18.2-11.3 23-10.1 4.8-18.4-3.3-21-5.6zM45.4 73.7l-4.3-3.9c8-8.9 5.8-15.4 4.3-20.2A26.4 26.4 0 0 1 44 38.8c-3-3.8-4.4-7.8-4.5-8-1.9-5.7-.5-11.2 2.8-16.4C48.7 4 60.5 4 60.5 4l4 10.5c-3-.1-12.8 0-15.8 4.8-3.8 6-1.3 9.6-1.2 10 .8-1 1.5-1.7 2.2-2.3 4.8-4.2 9-4.8 11.6-4.6a11 11 0 0 1 7.6 4.2c2 2.7 3 6.2 2.3 9.4a11 11 0 0 1-5.8 7.4 16 16 0 0 1-13 1.5v.3l.6 2c1.8 5.4 5 14.1-7.6 26.5zm7.4-37.5c.5.4 1.1.8 1.8 1 2 .8 4.4.6 7-.8 1.5-.9 1.7-1.7 1.7-2 .2-.9 0-2-.7-2.8a2.8 2.8 0 0 0-2-1.2c-1.6-.2-3.6.8-5.6 2.6-1 .9-1.7 2-2.3 3.2zm10 39.1-6.2-.1s3-16.7 12.5-19.5c1.8-.5 3.7-1 5.7-1.3l4-.8c.1-1.6-.5-3.6-1.3-5.9-.6-1.7-1.2-3.5-1.5-5.5-.6-3.9.4-7.3 3-9.6 3-2.9 7.9-3.8 13.4-2.5 3.2.7 5.5 2.2 7.6 3.6 2.9 2 4.6 3 8.2.5 4.3-2.9-1.4-14.3-4.4-21l11.3-4.6c1.5 3.3 8.8 20.3 4 30a11.5 11.5 0 0 1-8.1 6.2c-8 1.8-12.6-1.3-16-3.6-1.6-1-3-1.9-4.6-2.3-10.6-3 4.2 12.6-2.7 19.6-4.2 4.2-14.4 5.3-15 5.5-6.6 1.6-10 11.3-10 11.3z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M44 38.8c-.2 2.2-.3 3.5.3 6.4 2.7 2 8.7 2 8.7 2l-.6-2v-.3c-6.1-3-8.4-6.1-8.4-6.1zm-12.5 9.8-10.3-5 5.1-7.5 8.2 5.4zm-15.2-14A26 26 0 0 1 5 28.9l5.2-6c1.6 1.2 5 3.5 7.2 3.8l-1.1 7.9zM25.6 21.3 18 18.8a18 18 0 0 0 .7-8.3l7.9-1.3c.6 4 .3 8.2-1 12zM73 15.3l7.9-1.7L83 23.9l-7.8 1.7zM92.5 17.8 87 12c2.8-2.8 3.5-6.3 3.5-6.4L98.4 7c-.1.6-1.1 6.3-6 10.9zM95.5 48.6l7-2.2 2.3 7.7-7 2.1zM97.5 113l-7.9-1c.3-2.7-1.8-6.2-2.4-7l6.4-4.8c.5.6 4.7 6.4 4 12.8zM120.4 102.9c-3-.5-6-.6-9.1-.5l-.3-8c3.5-.2 7 0 10.6.6l-1.2 7.9zM109.6 113.9l5.6-5.7 7.8 7.6-5.6 5.7zM93.1 63.3 99 70l-6.6 5.8-5.8-6.6z&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;strong&gt;Celebration&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This web feature is now available in all three major browser engines! &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;CSS now supports color spaces that allow us to access colors outside of the sRGB &lt;a href=&quot;https://developer.chrome.com/articles/high-definition-css-color-guide/#what-is-a-color-gamut&quot; rel=&quot;noopener&quot;&gt;gamut&lt;/a&gt;. This means that you can support HD (high definition) displays, using colors from HD gamuts. This support comes with new functions to make better use of color on the web.&lt;/p&gt;
&lt;h2 id=&quot;accessing-color-spaces-from-css&quot;&gt;Accessing color spaces from CSS &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/color-spaces-and-functions/#accessing-color-spaces-from-css&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We already have a number of functions that allow us to access colors within the sRGB gamut—&lt;code&gt;rgb()&lt;/code&gt;, &lt;code&gt;hsl()&lt;/code&gt;, and &lt;code&gt;hwb()&lt;/code&gt;. Now supported in browsers is the &lt;code&gt;color()&lt;/code&gt; function, a normalized way to access colors within any RGB color space. This includes sRGB, Display P3, and Rec2020. You can see some examples in the following CSS:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.valid-css-color-function-colors&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--srgb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srgb 1 1 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--srgb-linear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srgb-linear 100% 100% 100% / 50%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--display-p3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;display-p3 1 1 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--rec2020&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rec2020 0 0 0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--a98-rgb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a98-rgb 1 1 1 / 25%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--prophoto&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prophoto-rgb 0% 0% 0%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--xyz&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xyz 1 1 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/color_value/color#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Also supported are several functions allowing access to color spaces other than sRGB using &lt;code&gt;lch()&lt;/code&gt;, &lt;code&gt;lab()&lt;/code&gt;, &lt;code&gt;oklch()&lt;/code&gt;, and &lt;code&gt;oklab()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/color_value/lch#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You can learn about all of these different color spaces in the &lt;a href=&quot;https://developer.chrome.com/articles/high-definition-css-color-guide/&quot; rel=&quot;noopener&quot;&gt;High definition CSS color guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-color-mix-function&quot;&gt;The &lt;code&gt;color-mix()&lt;/code&gt; function &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/color-spaces-and-functions/#the-color-mix-function&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As well as these new color spaces, all engines now support the &lt;code&gt;color-mix()&lt;/code&gt; function. This function enables mixing of one color into another, in any of the color spaces. In the following CSS, 25% of blue is mixed into white, in the srgb color space.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.example&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in srgb&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; blue 25%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 16.2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16.2
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/color_value/color-mix#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/blog/css-color-mix/&quot; rel=&quot;noopener&quot;&gt;Learn more about &lt;code&gt;color-mix()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These new functions and color spaces promise to bring vibrant HD color to the web. For inspiration, make a start by creating some beautiful gradients using the HD gradient generator at &lt;a href=&quot;https://gradient.style/&quot; rel=&quot;noopener&quot;&gt;gradient.style&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hero image by &lt;a href=&quot;https://unsplash.com/fr/@yogidan2012&quot; rel=&quot;noopener&quot;&gt;Daniele Levis Pelusi&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>New to the web platform in May</title>
      <link href="https://web.dev/web-platform-05-2023/"/>
      <updated>2023-05-31T00:00:00Z</updated>
      <id>https://web.dev/web-platform-05-2023/</id>
      <content type="html" mode="escaped">&lt;h2 id=&quot;stable-browser-releases&quot;&gt;Stable browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#stable-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In May 2023, &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/113&quot; rel=&quot;noopener&quot;&gt;Firefox 113&lt;/a&gt;, &lt;a href=&quot;https://developer.chrome.com/blog/new-in-chrome-113/&quot; rel=&quot;noopener&quot;&gt;Chrome 113&lt;/a&gt;, &lt;a href=&quot;https://developer.chrome.com/blog/new-in-chrome-114/&quot; rel=&quot;noopener&quot;&gt;Chrome 114&lt;/a&gt;, and &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_5-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 16.5&lt;/a&gt; became stable. Let&#39;s take a look at what this means for the web platform.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; We include browser compatibility data pulled from MDN in these posts which may not have been updated yet for very recent browser releases. The post will show the correct information as soon as it appears in the &lt;a href=&quot;https://github.com/mdn/browser-compat-data/releases&quot;&gt;browser-compat-data release&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;webgpu&quot;&gt;WebGPU &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#webgpu&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Chrome 113 includes &lt;a href=&quot;https://developer.chrome.com/blog/webgpu-release/&quot; rel=&quot;noopener&quot;&gt;WebGPU&lt;/a&gt;, the successor to the WebGL and WebGL 2 graphics APIs for the web. It provides modern features such as GPU compute, lower overhead access to GPU hardware, the ability to render to multiple canvases from a single graphics device, and better, more predictable performance.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox preview, Preview&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;preview&quot; title=&quot;Preview&quot; aria-label=&quot;Preview&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 113, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
113
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/GPU#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;first-party-sets&quot;&gt;First-Party Sets &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#first-party-sets&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/first-party-sets/&quot; rel=&quot;noopener&quot;&gt;First-Party Sets (FPS)&lt;/a&gt; is part of the &lt;a href=&quot;https://privacysandbox.com/&quot; rel=&quot;noopener&quot;&gt;Privacy Sandbox&lt;/a&gt;. It is a way for organizations to declare relationships among sites, so that browsers can decide when to allow limited third-party cookie access for sites within a set. FPS began a staged rollout in Chrome 113.&lt;/p&gt;
&lt;h3 id=&quot;css-media-features-and-more&quot;&gt;CSS media features and more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#css-media-features-and-more&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For CSS, Chrome 113 includes the &lt;code&gt;overflow-inline&lt;/code&gt; and &lt;code&gt;overflow-block&lt;/code&gt; media features.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 66, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      66
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/overflow-inline#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;And the &lt;code&gt;update&lt;/code&gt; media feature.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 102, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      102
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/update-frequency#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Also included is the &lt;code&gt;linear()&lt;/code&gt; easing function, which you can learn more about in the article &lt;a href=&quot;https://developer.chrome.com/articles/css-linear-easing-function/&quot; rel=&quot;noopener&quot;&gt;Create complex animation curves in CSS with the &lt;code&gt;linear()&lt;/code&gt; easing function&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 112, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      112
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;css-color-level-4-features&quot;&gt;CSS Color Level 4 features &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#css-color-level-4-features&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Firefox 113 includes the &lt;code&gt;color()&lt;/code&gt;, &lt;code&gt;lab()&lt;/code&gt;, &lt;code&gt;lch()&lt;/code&gt;, &lt;code&gt;oklab()&lt;/code&gt;, &lt;code&gt;oklch()&lt;/code&gt;, and &lt;code&gt;color-mix()&lt;/code&gt; functional notations, along with the forced-color-adjust property. This means that the new color spaces and functions are now supported across all three major engines. You can learn more about these color spaces and functions in the &lt;a href=&quot;https://web.dev/articles/high-definition-css-color-guide/&quot;&gt;High definition CSS color guide&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 16.2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16.2
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/color_value/color-mix#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;more-control-over-nth-child-selections&quot;&gt;More control over &lt;code&gt;:nth-child()&lt;/code&gt; selections &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#more-control-over-nth-child-selections&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Firefox 113 also adds the ability to pass a selector list into &lt;code&gt;:nth-child()&lt;/code&gt; and &lt;code&gt;nth-last-child()&lt;/code&gt;. Learn more about this, and see examples in the post &lt;a href=&quot;https://developer.chrome.com/articles/css-nth-child-of-s/&quot; rel=&quot;noopener&quot;&gt;More control over :nth-child() selections with the of S syntax&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 111, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      111
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 9, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      9
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;compressions-streams-api&quot;&gt;Compressions Streams API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#compressions-streams-api&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now supported in all three major engines due to inclusion in Firefox 113, the Compressions Streams API enables the compression and decompression of streams. This means that JavaScript applications no longer need to bundle a compression library.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 80, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      80
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 113, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      113
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 80, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      80
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 16.4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16.4
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/CompressionStream#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;css-nesting&quot;&gt;CSS nesting &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#css-nesting&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Safari 16.5 mostly resolved issues, but also adds support for &lt;a href=&quot;https://developer.chrome.com/articles/css-nesting/&quot; rel=&quot;noopener&quot;&gt;CSS Nesting&lt;/a&gt;, with the new nesting selector &lt;code&gt;&amp;gt;&lt;/code&gt;, used to nest related style rules, in a way that will be familiar to developers who have used pre-processors:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.nesting&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hotpink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&gt; .is&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; rebeccapurple&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;&gt; .awesome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; deeppink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 112, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      112
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 112, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
112
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 16.5, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
16.5
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/Nesting_selectors#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;balancing-headlines-with-text-wrap-balance&quot;&gt;Balancing headlines with &lt;code&gt;text-wrap: balance&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#balancing-headlines-with-text-wrap-balance&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From Chrome 114 you can use &lt;code&gt;text-wrap: balance&lt;/code&gt;. This allows you to balance headlines, avoiding the issue of having a single word on the final line, providing a more pleasing and readable result. You can find out more in &lt;a href=&quot;https://developer.chrome.com/blog/css-text-wrap-balance/&quot; rel=&quot;noopener&quot;&gt;CSS text-wrap: balance&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 114, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      114
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 114, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
114
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/text-wrap#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;chips-cookies-having-independent-partitioned-state&quot;&gt;CHIPS: Cookies Having Independent Partitioned State &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#chips-cookies-having-independent-partitioned-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As part of the work to &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/third-party-cookie-phase-out/&quot; rel=&quot;noopener&quot;&gt;phase out third-party cookies&lt;/a&gt;, &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/chips/&quot; rel=&quot;noopener&quot;&gt;CHIPS&lt;/a&gt; enables opting-in to third-party cookies being partitioned by top-level site using the new cookie attribute &lt;code&gt;Partitioned&lt;/code&gt;. CHIPS is available in Chrome 114.&lt;/p&gt;
&lt;h3 id=&quot;the-popover-api&quot;&gt;The Popover API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#the-popover-api&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also in Chrome 114 is the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Popover_API&quot; rel=&quot;noopener&quot;&gt;Popover API&lt;/a&gt; making it easier to build transient user interface (UI) elements that are displayed on top of all other web app UI.&lt;/p&gt;
&lt;p&gt;These include user-interactive elements like action menus, form element suggestions, content pickers, and teaching UI.&lt;/p&gt;
&lt;p&gt;The new popover attribute enables any element to be displayed in the &lt;a href=&quot;https://developer.chrome.com/blog/top-layer-devtools/&quot; rel=&quot;noopener&quot;&gt;top layer&lt;/a&gt; automatically. This means no more worrying about positioning, stacking elements, focus or keyboard interactions for the developer.&lt;/p&gt;
&lt;p&gt;Learn more in &lt;a href=&quot;https://developer.chrome.com/blog/introducing-popover-api/&quot; rel=&quot;noopener&quot;&gt;Introducing the popover API&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 114, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      114
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 114, Behind a flag&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 114, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
114
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 17, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
17
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/ToggleEvent#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;beta-browser-releases&quot;&gt;Beta browser releases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-platform-05-2023/#beta-browser-releases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beta browser versions give you a preview of things that will be in the next stable version of the browser. It&#39;s a great time to test new features, or removals, that could impact your site before the world gets that release. New betas are &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/114&quot; rel=&quot;noopener&quot;&gt;Firefox 114&lt;/a&gt;, &lt;a href=&quot;https://developer.chrome.com/blog/chrome-115-beta/&quot; rel=&quot;noopener&quot;&gt;Chrome 115&lt;/a&gt;, and &lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-16_6-release-notes&quot; rel=&quot;noopener&quot;&gt;Safari 16.6&lt;/a&gt;. These releases bring many great features to the platform. Check out the release notes for all of the details, here are just a few highlights.&lt;/p&gt;
&lt;p&gt;Chrome 115 includes multiple values for the CSS &lt;code&gt;display&lt;/code&gt; property. This means that &lt;code&gt;display: flex&lt;/code&gt; becomes &lt;code&gt;display: block flex&lt;/code&gt; and &lt;code&gt;display: block&lt;/code&gt; becomes &lt;code&gt;display: block flow&lt;/code&gt;. The single values are maintained as legacy keywords, and once in Chrome Stable this makes the multiple values available accross all engines.&lt;/p&gt;
&lt;p&gt;Also in Chrome 115 are the &lt;code&gt;ScrollTimeline&lt;/code&gt; and &lt;code&gt;ViewTimeline&lt;/code&gt; extensions to the Web Animations specification. These enable &lt;a href=&quot;https://developer.chrome.com/articles/scroll-driven-animations/&quot; rel=&quot;noopener&quot;&gt;scroll-driven animations&lt;/a&gt; via CSS and JavaScript.&lt;/p&gt;
&lt;p&gt;Firefox 114 includes the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebTransport_API&quot; rel=&quot;noopener&quot;&gt;WebTransport API&lt;/a&gt;, a modern update to WebSockets providing support for multiple streams, unidirectional streams, and out-of-order delivery.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@photozace&quot; rel=&quot;noopener&quot;&gt;Photoz ace&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Deploying AVIF for more responsive websites</title>
      <link href="https://web.dev/avif-updates-2023/"/>
      <updated>2023-05-24T00:00:00Z</updated>
      <id>https://web.dev/avif-updates-2023/</id>
      <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://aomedia.org/avif/&quot; rel=&quot;noopener&quot;&gt;AVIF&lt;/a&gt; is a new image format that is quickly gaining popularity on the web because of its high compression rates, efficient performance, and broad adoption. AVIF is an open, royalty-free image format that is based on the AV1 video codec standardized by the Alliance for Open Media. This blog post will provide an overview of how AVIF is adopted in the ecosystem, and what kind of performance and quality benefits developers can expect from AVIF for still images and animations.&lt;/p&gt;
&lt;h2 id=&quot;whats-new-with-the-avif-ecosystem&quot;&gt;What’s new with the AVIF ecosystem? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/avif-updates-2023/#whats-new-with-the-avif-ecosystem&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since the introduction of AVIF in Chrome, Firefox and Safari, usage of AVIF on the web has been growing steadily; &lt;a href=&quot;https://caniuse.com/avif&quot; rel=&quot;noopener&quot;&gt;almost all browsers&lt;/a&gt; support AVIF today.&lt;/p&gt;
&lt;p&gt;In Chrome alone, AVIF usage grew to approximately one percent in a little over a year after Chrome added AVIF support in stable.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A line graph of AVIF usage in Chrome from May 2021 to March 2023. Support has steadily grown from 0% to just beneath 1.4%.&quot; decoding=&quot;async&quot; height=&quot;367&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/QunCznNR5EJf8lp4rGNe.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;A number of image CDNs, such as &lt;a href=&quot;https://techdocs.akamai.com/ivm/changelog/apr-07-2021-new-policy-filters-and-avif-image-format&quot; rel=&quot;noopener&quot;&gt;Akamai&lt;/a&gt;, &lt;a href=&quot;https://blog.cloudflare.com/images-avif-blur-bundle/&quot; rel=&quot;noopener&quot;&gt;Cloudflare&lt;/a&gt;, &lt;a href=&quot;https://cloudinary.com/blog/how_to_adopt_avif_for_images_with_cloudinary&quot; rel=&quot;noopener&quot;&gt;Cloudinary&lt;/a&gt; and &lt;a href=&quot;https://blog.imgix.com/2021/10/27/avif-limited-availability&quot; rel=&quot;noopener&quot;&gt;Imgix&lt;/a&gt; are serving AVIF images today. In a &lt;a href=&quot;https://blog.imgix.com/2021/10/27/avif-limited-availability&quot; rel=&quot;noopener&quot;&gt;blog post&lt;/a&gt; announcing AVIF support, Imgix reported 60% file size savings compared to JPEG and 35% savings compared to WebP. These file size savings lead to significant storage savings, but also help pages load faster, yielding faster &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; times. LCP is one of the &lt;a href=&quot;https://web.dev/learn-core-web-vitals/&quot;&gt;Core Web Vitals&lt;/a&gt;, and represents how quickly the largest block of content on the page has loaded. Using modern codecs to compress images is one of the &lt;a href=&quot;https://web.dev/optimize-lcp/&quot;&gt;key techniques&lt;/a&gt; to reduce LCP. &lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/overview/&quot; rel=&quot;noopener&quot;&gt;Lighthouse&lt;/a&gt; is a great Chrome developer tool for testing your web site and to see &lt;a href=&quot;https://developer.chrome.com/en/docs/lighthouse/performance/uses-webp-images/&quot; rel=&quot;noopener&quot;&gt;how much savings AVIF would bring&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;WordPress is the &lt;a href=&quot;https://www.wpbeginner.com/beginners-guide/ultimate-list-of-wordpress-stats-facts-and-other-research/&quot; rel=&quot;noopener&quot;&gt;most popular&lt;/a&gt; website platform in the world, and there are number of plugins available for developers to convert their images to AVIF, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.org/plugins/autoptimize/&quot; rel=&quot;noopener&quot;&gt;AutoOptimize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.org/plugins/webp-converter-for-media/&quot; rel=&quot;noopener&quot;&gt;Converted for Media&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ewww.io/&quot; rel=&quot;noopener&quot;&gt;EWWW Image Optimizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://optimole.com/&quot; rel=&quot;noopener&quot;&gt;Optimole&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shortpixel.com/&quot; rel=&quot;noopener&quot;&gt;ShortPixel Image Optimizer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more hands-on developers, tools like &lt;a href=&quot;https://imagemagick.org/index.php&quot; rel=&quot;noopener&quot;&gt;ImageMagick&lt;/a&gt; and &lt;a href=&quot;https://ffmpeg.org/&quot; rel=&quot;noopener&quot;&gt;FFmpeg&lt;/a&gt; are a good starting point.&lt;/p&gt;
&lt;h2 id=&quot;avif-encode-speed&quot;&gt;AVIF encode speed &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/avif-updates-2023/#avif-encode-speed&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Fast encoding speed and high visual quality are critical for deploying image compression at scale. AVIF software encoding speed has improved significantly over the past two years. Compared to other modern still image formats, AVIF produces smaller files with similar visual quality (see the following graph, lower is better) but is also &lt;a href=&quot;https://storage.googleapis.com/avif-comparison/subset1.html&quot; rel=&quot;noopener&quot;&gt;faster to encode&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A bar chart comparing various image codec file sizes as a percentage of the output of TurboJPEG. AVIF is lowest, then JPEG XL, then WebP, and finally MozJPEG.&quot; decoding=&quot;async&quot; height=&quot;415&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bmoOLQMWjYTQzWK8hPE8.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The chart below (higher is better) illustrates how AVIF encoding speed compares to other image formats. Previous generation codecs like WebP benefit from the less complex (but also less efficient) compression algorithms. With a multi-threaded encoding scheme, AVIF achieves similar performance for common use cases while delivering significant compression gains.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A comparison of image codec encoding speed. The compared encoders are average AVIF, average JPEG XL, average WebP (one thread), and average MozJPEG (one thread). AVIF is generally one of the fastest image encoders in terms of best quality and default effort, but is the slowest of all encoders for on-the-fly performance.&quot; decoding=&quot;async&quot; height=&quot;433&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/FSzUG4d4ixJQytow1WNU.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;For developers interested in more detailed encoding speed and visual quality comparisons, the &lt;a href=&quot;https://storage.googleapis.com/avif-comparison/index.html&quot; rel=&quot;noopener&quot;&gt;Image Coding Comparisons&lt;/a&gt; site contains reproducible benchmark results.&lt;/p&gt;
&lt;p&gt;While software implementations for modern image codecs like AVIF and WebP are optimized for x86 and ARM processors architectures, compressing vast amounts of images at scale can be computationally expensive. One alternative to reduce compression costs is to explore hardware acceleration. &lt;a href=&quot;https://www.blue-dot.io/&quot; rel=&quot;noopener&quot;&gt;Bluedot&lt;/a&gt; has developed a hardware accelerated Pulsar-AVIF encoder running on programmable FPGAs, such as AMD&#39;s Alveo U250. Compared to software based avifenc, Pulsar-AVIF delivers a 7 to 23 times speed improvement with similar &lt;a href=&quot;https://www.blue-dot.io/avif-speed-quality-benchmark/&quot; rel=&quot;noopener&quot;&gt;compression efficiency&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Encoder&lt;/th&gt;
        &lt;th&gt;Encode time (ms)&lt;/th&gt;
        &lt;th&gt;Frames per second&lt;/th&gt;
        &lt;th&gt;CPU utilization&lt;/th&gt;
        &lt;th&gt;Hardware specification&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;
          Pulsar-AVIF&lt;br /&gt;
          (FPGA)
        &lt;/td&gt;
        &lt;td&gt;60&lt;/td&gt;
        &lt;td&gt;409.85&lt;/td&gt;
        &lt;td&gt;305%&lt;/td&gt;
        &lt;td&gt;
          AMD Alveo U250 1ea + Intel(R) Xeon(R)&lt;br /&gt;
          Platinum 8171 CPU at 2.6GHz, 10 cores
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          avifenc&lt;br /&gt;
          (libaom)
        &lt;/td&gt;
        &lt;td&gt;405&lt;/td&gt;
        &lt;td&gt;59.26&lt;/td&gt;
        &lt;td&gt;3200%&lt;/td&gt;
        &lt;td&gt;
          Intel(R) Xeon(R) Platinum 8370C CPU at&lt;br /&gt;
          2.8GHz, 32 cores
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          avifenc&lt;br /&gt;
          (SVT-AV1)
        &lt;/td&gt;
        &lt;td&gt;1325&lt;/td&gt;
        &lt;td&gt;18.11&lt;/td&gt;
        &lt;td&gt;3200%&lt;/td&gt;
        &lt;td&gt;
          Intel(R) Xeon(R) Platinum 8370C CPU at&lt;br /&gt;
          2.8GHz, 32 cores
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;caption&gt;
      AVIF encode speed comparison&lt;br /&gt;
      &lt;ul&gt;
        &lt;li&gt;Test set: Kodak (24 images of 768x512)&lt;/li&gt;
        &lt;li&gt;Encoding 24 images simultaneously (24 processes)&lt;/li&gt;
        &lt;li&gt;Each software encoding process is executed with 4 threads. (-j 4)&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/caption&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Developers can deploy Pulsar-AVIF encoder with cloud virtual machines, such as &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/virtual-machines/np-series&quot; rel=&quot;noopener&quot;&gt;Azure NP-Series&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;avif-features-for-responsive-web-pages&quot;&gt;AVIF features for responsive web pages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/avif-updates-2023/#avif-features-for-responsive-web-pages&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AVIF has a few interesting features that will help to deliver more responsive web pages. This time we’ll dive a bit into animated AVIFs, which are by far the most efficient way of delivering cool animations on the web.&lt;/p&gt;
&lt;h3 id=&quot;animated-avif&quot;&gt;Animated AVIF &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/avif-updates-2023/#animated-avif&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Animated &lt;a href=&quot;https://en.wikipedia.org/wiki/GIF&quot; rel=&quot;noopener&quot;&gt;GIF&lt;/a&gt; is still &lt;a href=&quot;https://almanac.httparchive.org/en/2022/media#gifs-animated-and-not&quot; rel=&quot;noopener&quot;&gt;a popular format&lt;/a&gt; for animated images, despite being 35 years old. Biggest drawbacks of animated GIFs are the support for 256 colors only and poor compression leading to very large file sizes while also limiting the resolution or frame rate for practical use cases. In contrast, animated AVIF coding is actually the same as AV1 video coding scheme which provides significant file size savings compared to animated GIF.&lt;/p&gt;
&lt;p&gt;We ran a simple benchmark where we encoded a set of animated GIFs to both AVIF and JPEG XL. Over the test set, median file size savings percentage was approximately 86% compared to original GIF files and about 73% compared to animated JPEG XL files*.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A comparison of animated image codec performance. AVIF outperforms GIF and JPEG XL in terms of both average and median file size.&quot; decoding=&quot;async&quot; height=&quot;371&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 600px) 600px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ltmx3lsTIyqiVcRAaYXL.png?auto=format&amp;w=1200 1200w&quot; width=&quot;600&quot; /&gt;
  &lt;figcaption&gt;
    * libavif and libjxl versions: libavif version 4cff6a3 (libaom version v3.5.0), libjxl version 176b1c03. Test set: 15 sample GIFs from &lt;a href=&quot;https://commons.wikimedia.org/wiki/Category:Animated_GIF_files.&quot; rel=&quot;noopener&quot;&gt;Wikipedia&lt;/a&gt;.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Chrome, Firefox and Safari all support animated AVIF playbacks.&lt;/p&gt;
&lt;p&gt;FFmpeg is one tool to use for creating animated AVIF files, here’s a basic example of converting a GIF to AVIF using FFmpeg:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ffmpeg -i &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$INPUT_GIF&lt;/span&gt;&quot;&lt;/span&gt; -crf &lt;span class=&quot;token variable&quot;&gt;$CRF&lt;/span&gt; -b:v &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$OUTPUT&lt;/span&gt;.avif&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;$CRF&lt;/code&gt; is the desired output quality on a scale of &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;63&lt;/code&gt;. Lower values mean better quality and greater file size. &lt;code&gt;0&lt;/code&gt; uses &lt;a href=&quot;https://en.wikipedia.org/wiki/Lossless_compression&quot; rel=&quot;noopener&quot;&gt;lossless compression&lt;/a&gt;. Start with a value of &lt;code&gt;23&lt;/code&gt; for small animated AVIF files.&lt;/p&gt;
&lt;p&gt;FFmpeg uses libaom by default for encoding AVIF images, but it can also use &lt;a href=&quot;https://github.com/xiph/rav1e&quot; rel=&quot;noopener&quot;&gt;rav1e&lt;/a&gt; or &lt;a href=&quot;https://gitlab.com/AOMediaCodec/SVT-AV1&quot; rel=&quot;noopener&quot;&gt;SVT-AV1&lt;/a&gt; when available. More information about encoder choices, tuning the encoding parameters for speed/quality trade-offs can be found in &lt;a href=&quot;https://trac.ffmpeg.org/wiki/Encode/AV1&quot; rel=&quot;noopener&quot;&gt;FFmpeg&#39;s AV1 encoding guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another use case is to repackage an AV1 video into AVIF without re-encoding the original file. This is significantly cheaper than decoding/encoding the original AV1 file and makes the AV1 video available for use with the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element. Passing &lt;code&gt;-c:v copy&lt;/code&gt; to FFmpeg can do this.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ffmpeg -i &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$INPUT_AV1_VIDEO&lt;/span&gt;&quot;&lt;/span&gt; -c:v copy -an &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$OUTPUT&lt;/span&gt;.avif&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/avif-updates-2023/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AVIF use on the web has been steadily increasing since launch and is widely supported by browsers, image CDNs, WordPress plugins and encoding tools. All in all, AVIF is a great choice for serving images on the web; AVIF is fast to encode and decode while providing the best quality or smallest file size, whichever you prefer for your website. AVIF is the most efficient way to deliver animations on the web. If you have questions, comments, or feature requests, please reach out on the &lt;a href=&quot;https://groups.google.com/a/aomedia.org/g/av1-discuss&quot; rel=&quot;noopener&quot;&gt;av1-discuss mailing list&lt;/a&gt;, &lt;a href=&quot;https://github.com/AOMediaCodec/community/wiki&quot; rel=&quot;noopener&quot;&gt;AOM Github community&lt;/a&gt;, and &lt;a href=&quot;https://github.com/AOMediaCodec/av1-avif/wiki&quot; rel=&quot;noopener&quot;&gt;AVIF wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hero image from &lt;a href=&quot;https://unsplash.com/photos/oXlXu2qukGE&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;, by &lt;a href=&quot;https://unsplash.com/@amal_z7z&quot; rel=&quot;noopener&quot;&gt;Amal S
&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Jani Huoponen</name>
        </author><author>
          <name>Vignesh Venkatasubramanian</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>How redBus improved their website&#39;s Interaction to Next Paint (INP) and increased sales by 7%</title>
      <link href="https://web.dev/redbus-inp/"/>
      <updated>2023-05-10T00:00:00Z</updated>
      <id>https://web.dev/redbus-inp/</id>
      <content type="html" mode="escaped">&lt;p&gt;The web and its capabilities are evolving at a fast pace. You can now build rich and full-featured experiences on the web that can achieve much of what native applications can in terms of capabilities.&lt;/p&gt;
&lt;p&gt;JavaScript is a primary driver for interactivity across the web, but if it&#39;s not used with care, interactions can feel sluggish, and lead users to perceive your website to be non-responsive or altogether broken. Thankfully, the &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; metric was created to address this specific user experience problem.&lt;/p&gt;
&lt;p&gt;INP measures all interactions made with a page during its lifecycle, and reports a single value that is representative of a website&#39;s speed in responding to user inputs. Simply put, if a page&#39;s INP is at or below the &lt;a href=&quot;https://web.dev/inp/#what-is-a-good-inp-score&quot;&gt;good threshold&lt;/a&gt;, all interactions made with a page can be said to be reliably fast.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.redbus.in/&quot; rel=&quot;noopener&quot;&gt;redBus&lt;/a&gt;, a bus booking and ticketing website based in India, undertook a substantial effort to improve their website&#39;s INP, even during the time when it was still considered an experimental metric. As a result of their efforts, they were able to increase sales by 7%, illustrating once again the relationship between web performance and business health. Here&#39;s what redBus did to improve their website&#39;s INP.&lt;/p&gt;
&lt;h2 id=&quot;top-goals&quot;&gt;Top goals &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#top-goals&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When redBus set out to optimize their website&#39;s INP, they had three goals in mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide a better user experience for users by focusing on interaction latency regardless of network speed and device capabilities.&lt;/li&gt;
&lt;li&gt;Optimize their website to keep interactions as fast as possible.&lt;/li&gt;
&lt;li&gt;Ensure that responses from their API were as light as possible to ensure fast data transfer to the front end.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-journey&quot;&gt;The journey &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#the-journey&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;redBus categorized interaction latency in two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Interaction latency caused by blocking JavaScript on the client. When interactions use excessive JavaScript that blocks the main thread, rendering is delayed, and this affects a page&#39;s INP.&lt;/li&gt;
&lt;li&gt;Network latency caused by API calls. While network activity is not something that INP measures, an interaction reliant on a call to a remote API can feel sluggish on slower networks, or if requests result in large responses.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;redBus was initially quite confident that the INP for their website would be good, but the &lt;a href=&quot;https://en.wikipedia.org/wiki/Real_user_monitoring&quot; rel=&quot;noopener&quot;&gt;Real User Monitoring (RUM)&lt;/a&gt; data for this metric at the 95th percentile told a different story.&lt;/p&gt;
&lt;h2 id=&quot;how-redbus-measured-inp&quot;&gt;How redBus measured INP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#how-redbus-measured-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;redBus relied on the &lt;a href=&quot;https://github.com/GoogleChrome/web-vitals&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;web-vitals&lt;/code&gt; JavaScript library&lt;/a&gt; built by Google to track not just INP, but all important user experience metrics for all pages across their website. In addition to the &lt;code&gt;web-vitals&lt;/code&gt; JavaScript library, redBus used &lt;a href=&quot;https://www.elastic.co/what-is/elk-stack&quot; rel=&quot;noopener&quot;&gt;ELK&lt;/a&gt; to analyze INP data that was collected on the front end.&lt;/p&gt;
&lt;p&gt;However, how you track your website&#39;s INP in &lt;a href=&quot;https://web.dev/lab-and-field-data-differences/#field-data&quot;&gt;the field&lt;/a&gt; may be quite different from how redBus approached the problem. We highly recommend that you read about &lt;a href=&quot;https://web.dev/find-slow-interactions-in-the-field/&quot;&gt;how to find slow interactions in the field&lt;/a&gt; to learn how to best to track INP for your websites, and subsequently &lt;a href=&quot;https://web.dev/diagnose-slow-interactions-in-the-lab/&quot;&gt;how to reproduce them in the lab&lt;/a&gt; before you begin &lt;a href=&quot;https://web.dev/optimize-inp/&quot;&gt;optimizing interactions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once redBus had a system in place for tracking INP, they were able to analyze the data in order to gain a better understanding of where slow interactivity was present.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the ELK logging system reporting INP values for analysis.&quot; decoding=&quot;async&quot; height=&quot;287&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A screenshot of the logging system used by redBus to analyze INP values collected from the field. (&lt;a href=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/s4JxEJgRhQAYZRSi7X3m.png&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Click for a higher resolution version of this image&lt;/a&gt;.)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When users search for fares on the redBus website, they can change the date on the search page to filter selected fares for the desired destination. The interaction to change the date on this page was slow, and was a cause of poor INP.&lt;/p&gt;
&lt;p&gt;Additionally, when a user scrolls through fares, additional fares are lazy-loaded from the API. &lt;a href=&quot;https://web.dev/inp/#whats-in-an-interaction&quot;&gt;Though scrolling itself isn&#39;t factored in how INP is measured&lt;/a&gt;, the &lt;code&gt;scroll&lt;/code&gt; event listener itself schedules a lot of work that must run on the main thread. This work was causing contention on the main thread that increased interaction latency, leading to poor INP on the search page.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;
    &lt;source src=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/xcxqqKz4JaUO9yQlS3Ex.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    The lazy-loading behavior used to load additional fares from the API on scroll. (&lt;a href=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/xcxqqKz4JaUO9yQlS3Ex.webm&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Click for a higher resolution version of this video&lt;/a&gt;.)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;how-redbus-optimized-inp-for-the-search-page&quot;&gt;How redBus optimized INP for the search page &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#how-redbus-optimized-inp-for-the-search-page&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To improve the search page&#39;s INP, redBus made several optimizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Element/scroll_event&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;scroll&lt;/code&gt;&lt;/a&gt; event handler was &lt;a href=&quot;https://web.dev/debounce-your-input-handlers/&quot;&gt;debounced&lt;/a&gt; in order to reduce the amount of times the event callback would fire in a given period. By lowering the frequency in which &lt;code&gt;scroll&lt;/code&gt; event callback ran, the main thread was able to respond more quickly to user interactions on the search page.&lt;/li&gt;
&lt;li&gt;The resulting rendering work was prioritized by using a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/a&gt; callback. &lt;code&gt;requestAnimationFrame&lt;/code&gt; tells the browser that the work in the callback must be done before the next frame.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the performance panel in Chrome DevTools showing the redBus website firing scroll event callbacks which are not debounced. The result is that the main thread becomes blocked.&quot; decoding=&quot;async&quot; height=&quot;500&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/seddeACyZ710UvE5s5L7.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Before: scroll handlers firing without debouncing applied to the event callback. A considerable number of blocking tasks on the main thread are present, which will delay interactions.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the performance panel in Chrome DevTools showing the redBus website firing scroll event callbacks which are debounced. The result is that the main thread is less blocked because the scroll event handlers fire far less frequently.&quot; decoding=&quot;async&quot; height=&quot;500&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/op1p5FGFPsSi8cNU21WS.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    After: scroll handlers firing with debouncing applied. The scroll event callbacks fire less frequently, giving the main thread more opportunities to respond to user interactions.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Additionally, the following further optimizations were made to the search results page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New batches of results were fetched on the second to last card on the search results page in order to improve the user experience and visual performance by triggering lazy loading earlier.&lt;/li&gt;
&lt;li&gt;Fewer results were fetched on each network call during lazy loading. By reducing fetches from 30 to 10 results, a reduction in INP ranges at 870 to 900 down to 350 to 370 were observed.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;
    &lt;source src=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ZjeONw0InjN2H5FEU0PM.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    The lazy-loading behavior used to load additional fares from the API on scroll. (&lt;a href=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ZjeONw0InjN2H5FEU0PM.webm&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Click for a higher resolution version of this video&lt;/a&gt;.)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;While these changes significantly improved the INP of the search page, there was still the problem where the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/HTMLElement/change_event&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;change&lt;/code&gt;&lt;/a&gt; event on the search page&#39;s input fields would call an expensive reducer function to update the user interface. This resulted in unnecessary rerendering of the user interface, which affected the page&#39;s INP.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;
    &lt;source src=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/9A46NHqYLxgWLkFsKGmF.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    INP values reported in the console while the user types in an input field. The resulting INP value of 344 observed in a lab setting falls within the &quot;need improvement&quot; thresholds. (&lt;a href=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/9A46NHqYLxgWLkFsKGmF.webm&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Click for a higher resolution version of this video&lt;/a&gt;.)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To optimize this interaction, redBus managed the state of input components locally and synced it with the &lt;a href=&quot;https://react-redux.js.org/&quot; rel=&quot;noopener&quot;&gt;Redux&lt;/a&gt; store only when an input&#39;s &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Element/blur_event&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;blur&lt;/code&gt;&lt;/a&gt; event was fired. This change reduced the number of rerenders and eliminated unwanted rerendering of the user interface by calling the reducer less frequently.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;
    &lt;source src=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/gD8RNByfNP8IsjytGbXZ.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Improved INP as a result of calling the reducer less frequently on an input field change. (&lt;a href=&quot;https://web-dev.imgix.net/video/jL3OLOhcWUQDnR4XjewLBx4e3PC3/gD8RNByfNP8IsjytGbXZ.webm&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Click for a higher resolution version of this video&lt;/a&gt;.)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;With this change, the page&#39;s INP improved by 72%, resulting in a faster and smoother user experience that users are more likely to engage with.&lt;/p&gt;
&lt;h2 id=&quot;business-impact&quot;&gt;Business impact &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/redbus-inp/#business-impact&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The relationship between business health and page performance is well-known. Though INP is a relatively new metric compared to other Core Web Vitals, redBus observed better business outcomes by focusing on improving this important user-centric performance metric. &lt;strong&gt;The result was a 7% overall increase in sales.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In short, INP helped to paint a picture of runtime performance issues on the redBus website. With the knowledge that there were improvements to be made, redBus was able to observe the problem, reproduce it, and use that crucial information to make optimizations that were beneficial to redBus and its business.&lt;/p&gt;
</content>
      <author>
          <name>Amit Kumar</name>
        </author><author>
          <name>Saurabh Rajpal</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Introducing Baseline</title>
      <link href="https://web.dev/introducing-baseline/"/>
      <updated>2023-05-10T00:00:00Z</updated>
      <id>https://web.dev/introducing-baseline/</id>
      <content type="html" mode="escaped">&lt;p&gt;Baseline helps you to see, at a glance, whether a feature or API is safe to use in your site or web applications. In this post, learn about the ideas that led to this concept, and how we hope it will help you.&lt;/p&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;eZa3BgGaAeA&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;h2 id=&quot;keeping-up-with-changes-to-the-web-platform&quot;&gt;Keeping up with changes to the web platform &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/introducing-baseline/#keeping-up-with-changes-to-the-web-platform&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The web of today changes rapidly. Our browsers are &lt;em&gt;evergreen&lt;/em&gt;, with new features landing in stable browsers each month. This is exciting, however it also poses problems. How do web developers keep up with all of this change? How do you know when it&#39;s safe to use a feature? When is it the right time to start to learn, and to invest in new features?&lt;/p&gt;
&lt;p&gt;In the past, we often explained browser support to stakeholders by tying it to a certain browser release (for example, Internet Explorer 11) because the line in the sand a non-evergreen browser created was clear to everyone. Today, the landscape can often seem less clear, with so many features landing it&#39;s a lot of work to check support for everything we use.&lt;/p&gt;
&lt;p&gt;We know how much of a problem this is to developers, because you have consistently &lt;a href=&quot;https://web.dev/deep-dive-into-developer-pain-points/&quot;&gt;told us that it&#39;s a problem&lt;/a&gt;. Over two years ago we decided it was a problem we wanted to try to address.&lt;/p&gt;
&lt;h2 id=&quot;getting-our-own-house-in-order&quot;&gt;Getting our own house in order &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/introducing-baseline/#getting-our-own-house-in-order&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We recognized that we were adding to confusion about the status of features, mixing experimental things in with stable content on our sites. So, we&#39;ve improved the clarity of our own communication channels. We now use web.dev to publish content about the stable web, those things that we can now describe as part of Baseline, and those that are very close to that status. We also highlight the work of other browsers, as we all work together to improve the interoperability of the platform.&lt;/p&gt;
&lt;p&gt;On web.dev you&#39;ll find content such as the &lt;a href=&quot;https://web.dev/tags/newly-interoperable/&quot;&gt;newly interoperable&lt;/a&gt; series, celebrating features that are now supported in all three major engines. We also have our monthly series, covering &lt;a href=&quot;https://web.dev/tags/new-to-the-web/&quot;&gt;what&#39;s new to the web platform&lt;/a&gt; sharing the work of all browsers, and updates about Interop 2023. This site is also home to our best practices guidance in subjects such as performance, accessibility, and fundamental web development skills.&lt;/p&gt;
&lt;p&gt;On &lt;a href=&quot;https://developer.chrome.com/&quot; rel=&quot;noopener&quot;&gt;developer.chrome.com&lt;/a&gt; you can learn about the new things that Chrome is bringing to the web platform. Some of these things are experimental, or only in Chrome right now. Many of the things we post about on developer.chrome.com are coming to other browsers, and we hope to celebrate their interoperable moments very soon, but we want you to have clarity about their status and browser support.&lt;/p&gt;
&lt;p&gt;We have also been adding clear browser support information to everything that we publish, and when our team talks about features at conferences.&lt;/p&gt;
&lt;p&gt;Documentation is really important for adoption of new features, and this year we&#39;ve made sure that the new features we are landing in Chrome have documentation over on MDN. For example, take a look at the documentation for &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/View_Transitions_API&quot; rel=&quot;noopener&quot;&gt;View Transitions&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebGPU_API&quot; rel=&quot;noopener&quot;&gt;WebGPU&lt;/a&gt;. We also help support &lt;a href=&quot;https://openwebdocs.org/&quot; rel=&quot;noopener&quot;&gt;Open Web Docs&lt;/a&gt; who contribute documentation for the entire web platform to MDN.&lt;/p&gt;
&lt;h2 id=&quot;working-with-others&quot;&gt;Working with others &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/introducing-baseline/#working-with-others&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Improving what we do was important, however to address the bigger issue we needed to work with others. We&#39;ve been successfully working with our partners at other browser vendors and related companies through &lt;a href=&quot;https://web.dev/interop-2022-wrapup/&quot;&gt;Interop 2022&lt;/a&gt; and &lt;a href=&quot;https://web.dev/interop-2023/&quot;&gt;2023&lt;/a&gt;. Forming the &lt;a href=&quot;https://www.w3.org/community/webdx/&quot; rel=&quot;noopener&quot;&gt;WebDX Community Group&lt;/a&gt; brought everyone together to think about this issue of clarity across the platform as a whole.&lt;/p&gt;
&lt;p&gt;The group is working together on a &lt;a href=&quot;https://github.com/web-platform-dx/feature-set&quot; rel=&quot;noopener&quot;&gt;feature set&lt;/a&gt;, a way to group web platform features to show their support status, and this feature-set is key to the concept of Baseline.&lt;/p&gt;
&lt;h2 id=&quot;creating-platform-wide-clarity-with-baseline&quot;&gt;Creating platform-wide clarity with Baseline &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/introducing-baseline/#creating-platform-wide-clarity-with-baseline&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/baseline&quot;&gt;Baseline&lt;/a&gt; is the line in the sand that is hard to identify in a world of evergreen browsers. Everything that is fully supported in the most recent two versions of major browsers will be part of Baseline. Therefore if your library states that all features used are part of Baseline, developers know what you mean. When creating a proposal for a new application, you can explain to stakeholders that browser support will be tied to Baseline, thus creating clarity for everyone as to levels of support.&lt;/p&gt;
&lt;p&gt;From today you will start to see Baseline appearing on pages &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/grid&quot; rel=&quot;noopener&quot;&gt;on MDN&lt;/a&gt;, and on &lt;a href=&quot;https://web.dev/baseline-features/&quot;&gt;web.dev&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As Baseline will be a continuously moving line, with new features becoming part of that set each month, every year we will publish a cut of features that are part of Baseline at one moment in time. For extra clarity, you can tie support to Baseline 24, for example.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; We&#39;re also quite excited by the ability to compare year-on-year what Baseline looks like. What will have changed between Baseline 24 and Baseline 25? That will be interesting to see. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What&#39;s next? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/introducing-baseline/#whats-next&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ll be continuing the rollout of Baseline across web.dev. When reading an article or tutorial, you&#39;ll be able to see when the features described are part of Baseline. You won&#39;t get part of the way through something and realize it uses something that doesn&#39;t have good browser support.&lt;/p&gt;
&lt;p&gt;We&#39;ll be providing widgets that you can use on your own articles or libraries, indicating support for the Baseline feature set.&lt;/p&gt;
&lt;p&gt;We&#39;ll also be working to ensure that new features we are landing in Chrome become part of Baseline as quickly as possible. Watch out for future posts where we&#39;ll talk more about that work.&lt;/p&gt;
&lt;p&gt;And we&#39;ll be gathering feedback from developers to find out how this idea is working in practice, and what more you would like to see. Keep an eye on the &lt;a href=&quot;https://web.dev/baseline/&quot;&gt;Baseline page&lt;/a&gt;, or offer feedback right now via the &lt;a href=&quot;https://www.w3.org/community/webdx/&quot; rel=&quot;noopener&quot;&gt;WebDX Community Group&lt;/a&gt;.&lt;/p&gt;
</content>
      <author>
          <name>Rachel Andrew</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Advancing Interaction to Next Paint</title>
      <link href="https://web.dev/inp-cwv/"/>
      <updated>2023-05-10T00:00:00Z</updated>
      <id>https://web.dev/inp-cwv/</id>
      <content type="html" mode="escaped">&lt;p&gt;Chrome&#39;s mission with the &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;Web Vitals program&lt;/a&gt; is to help developers focus on the metrics that are essential to great user experiences—the Core Web Vitals. One important aspect of the user experience that we&#39;ve been focusing on is responsiveness, which is the ability of a web page to react quickly to user interactions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/fid/&quot;&gt;First Input Delay (FID)&lt;/a&gt; is the Core Web Vital metric that measures responsiveness, but as we&#39;ve written in the past, there are &lt;a href=&quot;https://web.dev/better-responsiveness-metric/&quot;&gt;known limitations of FID&lt;/a&gt;. This led us to explore and seek feedback on a (then) &lt;a href=&quot;https://web.dev/responsiveness/&quot;&gt;experimental metric&lt;/a&gt; that addresses these limitations more effectively. In 2022, we announced &lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; as  that new metric, made it widely available in our tools, and started working with the community to test its efficacy.&lt;/p&gt;
&lt;p&gt;After another year of testing and gathering feedback from the community, we&#39;re ready to take the training wheels off and announce that INP is no longer experimental. Furthermore, effective March 2024, we&#39;re also committed to promoting INP as the new Core Web Vital metric for responsiveness, replacing FID.&lt;/p&gt;
&lt;p&gt;In this post, we&#39;ll cover more about the motivation behind the decision, exactly what&#39;s changing, and how to get started. For more on how this affects Google Search, refer to &lt;a href=&quot;https://developers.google.com/search/blog/2023/05/introducing-inp&quot; rel=&quot;noopener&quot;&gt;their blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-better-responsiveness-metric&quot;&gt;A better responsiveness metric &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/inp-cwv/#a-better-responsiveness-metric&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;FID was a huge step forward when we &lt;a href=&quot;https://blog.chromium.org/2020/05/introducing-web-vitals-essential-metrics.html&quot; rel=&quot;noopener&quot;&gt;introduced&lt;/a&gt; it as a Core Web Vital in 2020. It offered developers a new way to measure responsiveness &lt;em&gt;as real users experience it&lt;/em&gt;, which has always been an important part of the Web Vitals program. Unlike similar metrics that only approximate page interactivity—like &lt;a href=&quot;https://web.dev/tbt/&quot;&gt;Total Blocking Time (TBT)&lt;/a&gt; and &lt;a href=&quot;https://web.dev/tti/&quot;&gt;Time To Interactive (TTI)&lt;/a&gt;—FID directly measures the user experience. Crucially, a page could have slow TBT or TTI and still be perceived as responsive, because of the way real users interact with the page.&lt;/p&gt;
&lt;p&gt;While it did improve the way we measure responsiveness, FID wasn&#39;t without limitations. The name itself actually gives away two such limitations: &amp;quot;first input&amp;quot; and &amp;quot;delay&amp;quot;.  FID only reports the responsiveness of the &lt;em&gt;first&lt;/em&gt; time a user interacts with the page. Even though first impressions are important, the first interaction is not necessarily representative of &lt;em&gt;all&lt;/em&gt; interactions throughout the life of a page. Further, FID only measures the &lt;em&gt;input delay&lt;/em&gt; portion of the first interaction, which is the amount of time the browser had to wait (due to main thread busyness) before even beginning to handle the interaction.&lt;/p&gt;
&lt;p&gt;Enter INP. Rather than only measuring the first interaction, INP takes &lt;a href=&quot;https://web.dev/inp/#whats-in-an-interaction&quot;&gt;&lt;em&gt;all&lt;/em&gt; interactions&lt;/a&gt; into account, reporting one of the slowest over the entire lifetime of the page. And, rather than only measuring the delay portion, INP measures the full duration from the start of the interaction, through the event handler, and until the browser is able to paint the next frame. Hence, Interaction to &lt;em&gt;Next Paint&lt;/em&gt;. These implementation details make INP a much more comprehensive measure of user-perceived responsiveness than FID.&lt;/p&gt;
&lt;h2 id=&quot;evolving-inp&quot;&gt;Evolving INP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/inp-cwv/#evolving-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Starting today, INP is no longer experimental and will instead be considered a &lt;a href=&quot;https://web.dev/vitals/#pending&quot;&gt;&lt;em&gt;pending&lt;/em&gt; Core Web Vital metric&lt;/a&gt;. This is a new designation to indicate that INP has proven its readiness to replace FID—but we&#39;re not making the change just yet. To give the ecosystem time to adjust, INP will officially become a stable Core Web Vital metric in March 2024.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Graphic showing the timeline of INP phases, starting from when Chrome announced experimental support for INP in May 2022, to today in May 2023 when Chrome is announcing that INP is now a non-experimental, pending Core Web Vital metric, and finally to March 2024 when INP becomes a stable Core Web Vital metric, replacing FID.&quot; decoding=&quot;async&quot; height=&quot;270&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/so4oTRZP5vEEB6m8xo5L.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Graphic showing the timeline of INP phases.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Across our tools, you&#39;ll start to see INP without the &lt;code&gt;experimental&lt;/code&gt; prefix or icon. If you programmatically consume INP data from any of the following APIs, you&#39;ll need to update your code to switch over to the non-experimental INP field.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Tool&lt;/th&gt;
        &lt;th&gt;Deprecated field&lt;/th&gt;
        &lt;th&gt;New field&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;CrUX API&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;experimental_interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;CrUX History API&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;experimental_interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;CrUX BigQuery&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;experimental.interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;PageSpeed Insights API&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;experimental_interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;interaction_to_next_paint&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Lighthouse report*&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;experimental-interaction-to-next-paint&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;interaction-to-next-paint&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;caption style=&quot;max-width: 60ch;&quot;&gt;
      Map of APIs to their old and new INP field name.&lt;br /&gt;
      * Lighthouse will stop using the experimental INP field in version 11.
    &lt;/caption&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;To ease the transition and avoid breaking any downstream applications, these APIs will continue to serve the experimental INP field for another 90 days. API support for the experimental INP field will end on August 8, 2023.&lt;/p&gt;
&lt;p&gt;Meanwhile, FID will remain a Core Web Vital until March 2024. At that time, INP will join &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; and &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt; as the three stable Core Web Vitals. In a future update, we&#39;ll share more information about the precise timing of the change and the plan for FID after it&#39;s replaced as a Core Web Vital.&lt;/p&gt;
&lt;h2 id=&quot;getting-started-with-inp&quot;&gt;Getting started with INP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/inp-cwv/#getting-started-with-inp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;style&gt;
  .inp-mobile {
    display: inline;
  }

  .inp-desktop {
    display: none;
  }

  @media screen and (min-width: 640px) {
    .inp-mobile {
      display: none;
    }

    .inp-desktop {
      display: inline;
    }
  }
&lt;/style&gt;
&lt;figure&gt;
  &lt;svg title=&quot;A diagram of the INP thresholds. An INP at or below 200 milliseconds is considered good. Between 200 and 500 milliseconds suggests a page&#39;s responsiveness needs improvement. Anything over 500 milliseconds means that a page&#39;s responsiveness is poor.&quot; class=&quot;inp-mobile&quot; version=&quot;1.1&quot; id=&quot;Layer_1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; x=&quot;0&quot; y=&quot;0&quot; viewBox=&quot;0 0 296.6 220.2&quot; style=&quot;enable-background:new 0 0 296.6 220.2&quot; xml:space=&quot;preserve&quot;&gt;&lt;style&gt;.st0{fill:#2979FF} .st1{fill-rule:evenodd;clip-rule:evenodd;fill:#0CCE6B} .st2{fill:#191919} .st3{fill-rule:evenodd;clip-rule:evenodd;fill:#FFA400} .st4{fill-rule:evenodd;clip-rule:evenodd;fill:#FF4E42} @media screen and (prefers-color-scheme: light){.st2{fill:#191919}} [data-user-theme=light] .st2 {fill:#191919} @media screen and (prefers-color-scheme: dark){.st2{fill:#fff}} [data-user-theme=dark] .st2{fill:#fff}&lt;/style&gt;&lt;path class=&quot;st0&quot; d=&quot;M83.3 63V0h11.9v63H83.3zm26.3 0V0h13.8l25.3 42.2h.7l-.7-12.1V0h11.8v63H148l-26.8-44.6h-.7l.7 12.1V63h-11.6zm65.4 0V0h22.2c4.1 0 7.7.8 10.9 2.5s5.8 4 7.7 7 2.9 6.4 2.9 10.4c0 3.9-1 7.4-2.9 10.4s-4.5 5.4-7.7 7c-3.2 1.7-6.9 2.5-10.9 2.5h-15.6V28.6h15.9c2.1 0 3.8-.4 5.2-1.2s2.5-1.9 3.2-3.2c.7-1.3 1.1-2.8 1.1-4.3s-.4-2.9-1.1-4.2c-.7-1.3-1.8-2.3-3.2-3.2s-3.1-1.2-5.2-1.2h-10.7V63H175z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st1&quot; d=&quot;M0 137.1h96v38.4H0v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M34 161c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-.9-.4-.4-.7-.9-1-1.4-.2-.6-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.6.6-1 1-1.4.4-.4.9-.7 1.4-.9.5-.2 1.1-.3 1.8-.3s1.3.1 1.8.3c.6.2 1 .6 1.4 1l-.9.9c-.2-.2-.4-.4-.6-.5-.2-.1-.5-.3-.8-.3-.3-.1-.6-.1-.9-.1-.4 0-.8.1-1.2.2-.4.1-.7.4-1 .6-.3.3-.5.6-.7 1-.2.4-.2.8-.2 1.3s.1.9.2 1.3c.2.4.4.7.7 1 .3.3.6.5 1 .7.4.1.8.2 1.2.2.4 0 .8-.1 1.1-.2.3-.1.6-.3.9-.5.3-.2.5-.5.6-.8.2-.3.3-.6.3-1H34v-1.2h4.2v.7c0 .6-.1 1.2-.3 1.7-.2.5-.5.9-.9 1.3s-.8.6-1.3.8c-.5.3-1.1.4-1.7.4zm9.5 0c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8 0 .6-.1 1.2-.3 1.8-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.5.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm9.9 1.2c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8 0 .6-.1 1.2-.3 1.8-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.2.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm6 1.1v-8.6h2.8c.9 0 1.7.2 2.3.5.7.4 1.2.9 1.5 1.5.4.6.5 1.4.5 2.2 0 .8-.2 1.6-.5 2.2-.4.6-.9 1.2-1.5 1.5-.6.4-1.4.5-2.3.5h-2.8zm1.3-1.3h1.4c.6 0 1.2-.1 1.7-.4.5-.3.8-.6 1.1-1 .2-.5.4-1 .4-1.6 0-.6-.1-1.2-.4-1.6-.2-.5-.6-.8-1.1-1-.5-.3-1-.4-1.7-.4h-1.4v6z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st3&quot; d=&quot;M96 137.1h105.6v38.4H96v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M130.8 153.9v-8.6h1.6l3.9 6.3h.1l-.1-1.7v-4.7h1.3v8.6h-1.4l-4.1-6.6h-.1l.1 1.7v5h-1.3zm8.7 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V149h4.1v1.2h-4.1zm6.2 3.7v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V149h4.1v1.2h-4.1zm6.1 3.7v-8.6h2.8c.9 0 1.7.2 2.3.5.7.4 1.2.9 1.5 1.5.4.6.5 1.4.5 2.2s-.2 1.6-.5 2.2c-.4.6-.9 1.2-1.5 1.5-.6.4-1.4.5-2.3.5h-2.8zm1.3-1.3h1.4c.6 0 1.2-.1 1.7-.4.5-.2.8-.6 1.1-1 .2-.5.4-1 .4-1.6 0-.6-.1-1.2-.4-1.6-.2-.5-.6-.8-1.1-1-.5-.2-1-.4-1.7-.4h-1.4v6zm9.9 1.4c-.5 0-.9-.1-1.3-.3-.4-.2-.8-.4-1.1-.8-.3-.4-.5-.8-.7-1.3l1.2-.5c.1.5.3.9.7 1.2.3.3.7.5 1.2.5.3 0 .5 0 .8-.1.2-.1.4-.2.6-.4s.2-.4.2-.7c0-.3-.1-.5-.2-.7-.1-.2-.3-.3-.6-.5s-.6-.3-1-.5l-.5-.2c-.2-.1-.5-.2-.7-.3-.2-.1-.5-.3-.7-.5-.2-.2-.4-.4-.5-.7-.1-.3-.2-.6-.2-.9 0-.4.1-.8.3-1.2.2-.4.5-.6.9-.8.4-.2.9-.3 1.4-.3.6 0 1 .1 1.4.3.4.2.7.4.9.7.2.3.4.5.4.8l-1.2.5c0-.2-.1-.3-.2-.5s-.3-.3-.5-.4c-.2-.1-.4-.2-.8-.2-.2 0-.5.1-.7.2-.2.1-.4.2-.5.4-.1.2-.2.3-.2.6s.1.6.4.8c.3.2.6.4 1.1.5l.6.2c.3.1.6.2.8.3.3.1.5.3.7.5.2.2.4.4.5.7.1.3.2.6.2 1s-.1.8-.3 1.2c-.2.3-.4.6-.7.8-.3.2-.6.3-.9.4s-.5.2-.8.2zM107 167.9v-8.6h1.3v8.6H107zm3.2 0v-8.6h1.8l2.5 6.5h.1l2.5-6.5h1.8v8.6h-1.3V163l.1-1.5h-.1l-2.5 6.4h-1l-2.5-6.4h-.1l.1 1.5v4.9h-1.4zm10.6 0v-8.6h3c.5 0 1 .1 1.4.3.4.2.8.5 1 .9.3.4.4.9.4 1.4 0 .5-.1 1-.4 1.4-.2.4-.6.7-1 .9-.4.2-.9.3-1.4.3h-2.2v-1.2h2.3c.3 0 .6-.1.8-.2.2-.1.4-.3.5-.5.1-.2.2-.4.2-.7 0-.2-.1-.4-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.3h-1.4zm7.2 0v-8.6h3c.5 0 1 .1 1.4.3.4.2.7.5 1 .9.2.4.4.8.4 1.4 0 .3-.1.7-.2 1s-.3.6-.6.8c-.3.2-.6.4-1 .6-.4.1-.8.2-1.2.2h-2.1v-1.2h2.3c.3 0 .5-.1.7-.2.2-.1.4-.3.5-.5.1-.2.2-.5.2-.7 0-.2-.1-.5-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.4H128zm2-4h1.5l2.7 3.9v.1h-1.5l-2.7-4zm9.3 4.1c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.2.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm7.9 1.1-3-8.6h1.4l1.9 5.7.3 1h.1l.3-1 2-5.7h1.4l-3.1 8.6h-1.3zm5.6 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V163h4.1v1.2h-4.1zm6.2 3.7v-8.6h1.8l2.5 6.5h.1l2.5-6.5h1.8v8.6H167V163l.1-1.5h-.1l-2.5 6.4h-1l-2.5-6.4h-.1l.1 1.5v4.9h-1.3zm10.6 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V163h4.1v1.2H171zm6.1 3.7v-8.6h1.6l3.9 6.3h.1l-.1-1.7v-4.7h1.3v8.6h-1.4l-4.1-6.6h-.1l.1 1.7v5h-1.3zm10.5 0V160h1.3v7.9h-1.3zm-2.4-7.4v-1.2h6.1v1.2h-6.1z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st4&quot; d=&quot;M200.6 137.1h96v38.4h-96v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M232.5 160.9v-8.6h3c.5 0 1 .1 1.4.3.4.2.8.5 1 .9.3.4.4.9.4 1.4 0 .5-.1 1-.4 1.4-.2.4-.6.7-1 .9-.4.2-.9.3-1.4.3h-2.2v-1.2h2.3c.3 0 .6-.1.8-.2.2-.1.4-.3.5-.5.1-.2.2-.4.2-.7 0-.2-.1-.4-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.3h-1.4zm11 .1c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.5.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.6.3 1.1.4 1.6.4zm9.9 1.2c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm6 1.1v-8.6h3c.5 0 1 .1 1.4.3.4.2.7.5 1 .9.2.4.4.8.4 1.4 0 .3-.1.7-.2 1s-.3.6-.6.8c-.3.2-.6.4-1 .6-.4.1-.8.2-1.2.2h-2.1v-1.2h2.3c.3 0 .5-.1.7-.2.2-.1.4-.3.5-.5.1-.2.2-.5.2-.7 0-.2-.1-.5-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.4h-1.2zm2-4h1.5l2.7 3.9v.1H264l-2.6-4zM178.1 219.9c-.5 0-1-.1-1.5-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-1-.8-1.7l1.5-.6c.1.6.4 1 .8 1.4.4.4.9.5 1.4.5.6 0 1.1-.2 1.5-.6.4-.4.6-.9.6-1.5s-.2-1.1-.6-1.5c-.4-.4-.9-.6-1.5-.6-.4 0-.7.1-1 .2-.3.1-.5.4-.7.6l-1.7-.8.7-5.5h5.9v1.6h-4.5l-.4 2.9h.1c.2-.2.5-.3.8-.5.3-.1.7-.2 1.2-.2.6 0 1.2.2 1.7.5s1 .7 1.3 1.3c.3.5.5 1.2.5 1.9s-.2 1.3-.5 1.9c-.3.6-.8 1-1.3 1.3-.7.5-1.4.7-2.1.7zm9.9 0c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.2-1.2.4-1.9.4zm.1-1.7c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10.5 1.7c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.2-1.2.4-1.9.4zm0-1.7c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10 1.4v-8.2h1.6v1.1h.1c.2-.3.4-.5.6-.7.3-.2.6-.4.9-.5.3-.1.7-.2 1-.2.6 0 1.1.1 1.5.4.4.3.7.7.9 1.1.3-.4.6-.8 1.1-1.1.5-.3 1-.5 1.7-.5 1 0 1.7.3 2.1.9.5.6.7 1.4.7 2.3v5.2h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.8zm17.2.3c-.6 0-1.2-.1-1.7-.3-.5-.2-.9-.5-1.2-.8-.3-.3-.5-.7-.7-1.1l1.5-.7c.2.4.5.8.8 1 .4.2.8.3 1.2.3.4 0 .8-.1 1.1-.2.3-.2.5-.4.5-.8 0-.2-.1-.4-.2-.6-.1-.1-.3-.3-.6-.4-.2-.1-.5-.2-.8-.2l-1-.2c-.4-.1-.8-.3-1.1-.5-.3-.2-.6-.5-.8-.8-.2-.3-.3-.7-.3-1.1 0-.5.1-.9.4-1.3.3-.4.7-.6 1.1-.8.5-.2 1-.3 1.6-.3.5 0 1 .1 1.4.2.4.1.8.3 1.1.6.3.3.6.6.8 1l-1.5.7c-.2-.4-.4-.6-.7-.8-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.2-.4.4-.4.6 0 .3.1.5.4.7.2.2.5.3.9.4l1.2.3c.8.2 1.4.5 1.8.9.4.4.6.9.6 1.5 0 .5-.2 1-.5 1.4-.3.4-.7.7-1.2.9-.6.2-1.1.4-1.7.4zM69 220v-1.6s.2-.1.4-.4c.2-.2.5-.5.8-.9l1.1-1.1 1-1c.3-.3.5-.6.7-.8.3-.3.5-.6.7-.8.2-.2.3-.5.4-.7.1-.2.1-.5.1-.8 0-.3-.1-.5-.2-.8-.1-.3-.3-.4-.6-.6-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.1-.5.3-.6.6-.1.2-.3.4-.3.7l-1.5-.6c.1-.3.2-.5.4-.8.2-.3.4-.5.7-.8.3-.3.6-.5 1-.6.4-.2.9-.3 1.4-.2.7 0 1.3.2 1.9.5.5.3.9.7 1.2 1.2.3.5.4 1 .4 1.6 0 .5-.1.9-.2 1.3-.2.4-.4.8-.7 1.2-.3.4-.5.7-.8 1l-.5.5c-.2.2-.4.5-.7.7l-.7.7-.6.6-.4.4h4.8v1.6H69zm13.2.2c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.3-1.2.4-1.9.4zm0-1.6c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10.5 1.6c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.3-1.2.4-1.9.4zm0-1.6c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.5.3 1 .5 1.5.5zm10 1.4v-8.2h1.6v1.1h.1c.2-.3.4-.5.6-.7.3-.2.6-.4.9-.5.3-.1.7-.2 1-.2.6 0 1.1.1 1.5.4.4.3.7.7.9 1.1.3-.4.6-.8 1.1-1.1.5-.3 1-.5 1.7-.5 1 0 1.7.3 2.1.9.5.6.7 1.4.7 2.3v5.2h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4H108v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.8zm17.2.2c-.6 0-1.2-.1-1.7-.3-.5-.2-.9-.5-1.2-.8-.3-.3-.5-.7-.7-1.1l1.5-.7c.2.4.5.8.8 1 .4.2.8.3 1.2.3.4 0 .8-.1 1.1-.2.3-.2.5-.4.5-.8 0-.2-.1-.4-.2-.6-.1-.1-.3-.3-.6-.4-.2-.1-.5-.2-.8-.2l-1-.2c-.4-.1-.8-.3-1.1-.5-.3-.2-.6-.5-.8-.8-.2-.3-.3-.7-.3-1.1 0-.5.1-.9.4-1.3.3-.4.7-.6 1.1-.8.5-.2 1-.3 1.6-.3.5 0 1 .1 1.4.2.4.1.8.3 1.1.6.3.3.6.6.8 1l-1.5.7c-.2-.4-.4-.6-.7-.8-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.2-.4.4-.4.6 0 .3.1.5.4.7.2.2.5.3.9.4l1.2.3c.8.2 1.4.5 1.8.9.4.4.6.9.6 1.5 0 .5-.2 1-.5 1.4-.3.4-.7.7-1.2.9-.5.3-1.1.4-1.7.4zM42.4 96.3V82h1.7v14.3h-1.7zm4.6 0V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H47zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.5-.6-.7-1.3-.7-2.2zm10.3 3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7s1-1.5 1.7-2 1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5H65V90h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-.9.6-1.8.8-2.9.8zm6.7-.3V86.1h1.6v1.6h.1c.1-.4.4-.7.7-1 .3-.3.7-.5 1.1-.7s.8-.2 1.2-.2h.7c.2 0 .3.1.5.2v1.8c-.2-.1-.5-.2-.7-.2-.2-.1-.5-.1-.7-.1-.5 0-1 .1-1.4.4-.4.3-.7.7-1 1.1-.2.5-.4 1-.4 1.5v5.7h-1.7zm10.4.3c-.8 0-1.4-.1-2-.4s-1-.7-1.3-1.2c-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1s.7.2 1 .3c.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8s-.7.5-1.1.7c-.5.2-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5s-1-.2-1.5-.2c-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4 1 .4 1.6.4zm11.8 1.5c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-2 .7-2.8.4-.8 1.1-1.5 1.8-1.9.8-.5 1.7-.7 2.7-.7 1.1 0 2.1.3 2.8.8.7.5 1.3 1.2 1.6 2l-1.5.6c-.2-.6-.6-1.1-1.1-1.4-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.7.5s-.9.8-1.2 1.4c-.3.6-.5 1.3-.5 2 0 .8.2 1.4.5 2 .3.6.7 1 1.2 1.4.5.3 1.1.5 1.7.5.7 0 1.3-.2 1.9-.5s.9-.8 1.2-1.4l1.5.6c-.3.8-.9 1.5-1.6 2s-1.9.8-3 .8zm5.5-10.5h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8s-.7-1.3-.7-2.2zm6.5 2.7V86.1h1.7v10.2h-1.7zm.9-12c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.9c0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.2-.6.4-.9.4zm8.1 12.3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2s.7 1.7.7 2.7c0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.6-1.7.8-2.7.8zm0-1.5c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1-.8-1-1.3-1.3c-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3-.5 1.3-.5 2.1.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm7 1.2V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zM143 86.1h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.6-.7-1.3-.7-2.2zm10.5 3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.6-1.7.8-2.7.8zm0-1.5c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm12.2 1.2V82h2.1l7.2 11.4h.1l-.1-2.8V82h1.7v14.3h-1.8l-7.5-11.9h-.1l.1 2.8v9.2h-1.7zm18.2.3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V90h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .6-1.9.8-3 .8zm5.5-.3 4.1-5.9h.2l2.9-4.3h2l-4 5.6h-.1l-3.1 4.6h-2zm.1-10.2h1.9l3.2 4.5h.1l4 5.7h-2l-3-4.5h-.1l-4.1-5.7zm9.9 0h6v1.5h-6v-1.5zm1.8 7.5V83.3h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.6-.7-1.3-.7-2.2zm11.2 2.7V82h4.8c.8 0 1.5.2 2.2.5.7.4 1.2.8 1.6 1.5.4.6.6 1.4.6 2.2 0 .8-.2 1.6-.6 2.2-.4.6-.9 1.1-1.6 1.5-.7.4-1.4.5-2.2.5H215v-1.6h4c.6 0 1-.1 1.4-.4.4-.3.7-.6.9-1 .2-.4.3-.8.3-1.2s-.1-.8-.3-1.2c-.2-.4-.5-.7-.9-1-.4-.3-.9-.4-1.4-.4h-3.2v12.7h-1.7zm14.1.3c-.8 0-1.4-.1-2-.4s-1-.7-1.3-1.2-.5-1.1-.5-1.8c0-.8.2-1.4.6-1.9s.9-.9 1.5-1.2c.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1s.7.2 1 .3c.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7s1.1-.2 1.6-.2c1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8s-.7.5-1.1.7c-.6.2-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5s-1-.2-1.5-.2c-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4 1 .4 1.6.4zm7.4 1.2V86.1h1.7v10.2h-1.7zm.8-12c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.9c0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.2.2-.5.4-.9.4zm3.5 12V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H240zm10.1-10.2h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8s-.7-1.3-.7-2.2zM96 172.8c-2.4 0-4.3 1.9-4.3 4.3 0 2 1.4 3.7 3.3 4.2v20.1h2v-20.1c1.9-.5 3.3-2.1 3.3-4.2 0-2.3-1.9-4.3-4.3-4.3zM201.6 172.6c-2.4 0-4.3 1.9-4.3 4.3 0 2 1.4 3.7 3.3 4.2v19.8h2v-19.8c1.9-.5 3.3-2.1 3.3-4.2 0-2.4-1.9-4.3-4.3-4.3z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
  &lt;svg title=&quot;A diagram of the INP thresholds. An INP at or below 200 milliseconds is considered good. Between 200 and 500 milliseconds suggests a page&#39;s responsiveness needs improvement. Anything over 500 milliseconds means that a page&#39;s responsiveness is poor.&quot; class=&quot;inp-desktop&quot; version=&quot;1.1&quot; id=&quot;Layer_1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; x=&quot;0&quot; y=&quot;0&quot; viewBox=&quot;0 0 658.4 113.6&quot; style=&quot;enable-background:new 0 0 658.4 113.6&quot; xml:space=&quot;preserve&quot;&gt;&lt;style&gt;.st0{fill: #2979FF} v.st1{fill-rule: evenodd;clip-rule: evenodd;fill: #0CCE6B} .st2 {fill: #191919} .st3{fill-rule: evenodd;clip-rule: evenodd;fill: #FFA400} .st4{fill-rule: evenodd;clip-rule: evenodd;fill: #FF4E42} @media screen and (prefers-color-scheme: light){.st2{fill: #191919}} @media screen and (prefers-color-scheme: dark){.st2{fill: #fff}} [data-user-theme=dark] .st2{fill: #fff}&lt;/style&gt;&lt;path class=&quot;st0&quot; d=&quot;M30.2 68.7V0h13v68.7h-13zm28.7 0V0H74l27.7 46.1h.8l-.8-13.2V0h12.9v68.7H101L71.7 20.1h-.8l.8 13.2v35.4H58.9zm71.3 0V0h24.2c4.4 0 8.4.9 11.9 2.7 3.5 1.8 6.3 4.4 8.4 7.6 2.1 3.3 3.1 7 3.1 11.3 0 4.3-1 8.1-3.1 11.4-2.1 3.3-4.9 5.8-8.4 7.7-3.5 1.8-7.5 2.7-11.9 2.7h-17V31.2h17.4c2.2 0 4.1-.4 5.7-1.3 1.5-.9 2.7-2.1 3.5-3.5.8-1.4 1.2-3 1.2-4.7 0-1.7-.4-3.2-1.2-4.6-.8-1.4-1.9-2.6-3.5-3.5-1.5-.9-3.4-1.3-5.7-1.3h-11.6v56.5h-13z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st1&quot; d=&quot;M303.2 14.9h115.2v43.2H303.2V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M345.3 41.5c-.7 0-1.3-.1-1.9-.4-.6-.2-1.1-.6-1.6-1s-.8-1-1.1-1.6c-.3-.6-.4-1.3-.4-2s.1-1.4.4-2c.3-.6.6-1.1 1.1-1.6.5-.5 1-.8 1.6-1 .6-.2 1.2-.4 1.9-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1l-1 1c-.2-.2-.4-.4-.7-.6-.3-.2-.5-.3-.9-.4-.3-.1-.6-.1-1-.1-.5 0-.9.1-1.3.3-.4.2-.8.4-1.1.7-.3.3-.6.7-.8 1.1-.2.4-.3.9-.3 1.5s.1 1 .3 1.5c.2.4.5.8.8 1.1.3.3.7.6 1.1.7.4.2.9.2 1.3.2s.8-.1 1.2-.2c.4-.1.7-.3 1-.5.3-.2.5-.5.7-.8.2-.3.3-.7.3-1.1h-3.3v-1.3h4.6v.8c0 .7-.1 1.3-.4 1.9-.2.6-.6 1-1 1.5-.4.4-.9.7-1.5.9-.3.2-.9.3-1.6.3zm10.5 0c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1-1.2.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3s.5-1.2.5-1.9-.2-1.3-.5-1.9-.7-1-1.2-1.3c-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3s-.5 1.2-.5 1.9.2 1.3.5 1.9.7 1 1.2 1.3c.6.4 1.2.5 1.8.5zm11 1.4c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3s.5-1.2.5-1.9-.2-1.3-.5-1.9-.7-1-1.2-1.3c-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3s-.5 1.2-.5 1.9.2 1.3.5 1.9.7 1 1.2 1.3c.6.4 1.2.5 1.8.5zm6.6 1.2v-9.5h3c1 0 1.9.2 2.6.6.7.4 1.3 1 1.7 1.7s.6 1.5.6 2.5c0 .9-.2 1.8-.6 2.5s-1 1.3-1.7 1.7c-.7.4-1.6.6-2.6.6h-3zm1.5-1.4h1.5c.7 0 1.3-.1 1.8-.4.5-.3.9-.7 1.2-1.2.3-.5.4-1.1.4-1.8s-.1-1.3-.4-1.8c-.3-.5-.7-.9-1.2-1.2-.5-.3-1.1-.4-1.8-.4h-1.5v6.8z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st3&quot; d=&quot;M418.4 14.9h124.8v43.2H418.4V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M460.8 33.3v-9.5h1.7l4.3 7h.1l-.1-1.8v-5.2h1.5v9.5h-1.5l-4.5-7.4h-.1l.1 1.8v5.5h-1.5zm9.7 0v-9.5h5.8v1.4H472V32h4.3v1.4h-5.8zm.7-4.1v-1.4h4.6v1.4h-4.6zm6.9 4.1v-9.5h5.8v1.4h-4.3V32h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4h-4.6zm6.8 4.1v-9.5h3c1 0 1.9.2 2.6.6.7.4 1.3 1 1.7 1.7s.6 1.5.6 2.5c0 .9-.2 1.8-.6 2.5s-1 1.3-1.7 1.7c-.7.4-1.6.6-2.6.6h-3zm1.5-1.4h1.5c.7 0 1.3-.1 1.8-.4.5-.3.9-.7 1.2-1.2.3-.5.4-1.1.4-1.8s-.1-1.3-.4-1.8c-.3-.5-.7-.9-1.2-1.2-.5-.3-1.1-.4-1.8-.4h-1.5v6.8zm10.9 1.6c-.5 0-1-.1-1.5-.3-.5-.2-.9-.5-1.2-.9-.3-.4-.6-.9-.8-1.5l1.4-.6c.1.5.4.9.8 1.3.4.3.8.5 1.3.5.3 0 .6-.1.8-.2.3-.1.5-.3.6-.5.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.6-.5-.3-.2-.7-.3-1.1-.5l-.6-.2c-.3-.1-.5-.2-.8-.4-.3-.1-.5-.3-.7-.5-.2-.2-.4-.5-.5-.7-.1-.3-.2-.6-.2-1 0-.5.1-.9.4-1.3.2-.4.6-.7 1-.9.4-.2 1-.4 1.6-.4.6 0 1.1.1 1.5.3.4.2.7.5 1 .8.2.3.4.6.5.9l-1.3.6c-.1-.2-.2-.4-.3-.5-.1-.2-.3-.3-.5-.4-.2-.1-.5-.2-.8-.2-.3 0-.5.1-.8.2-.2.1-.4.2-.6.4-.1.2-.2.4-.2.6 0 .3.1.6.4.8s.7.4 1.2.6l.6.2c.3.1.6.2.9.4.3.1.6.3.8.6.2.2.4.5.6.8.1.3.2.7.2 1.2s-.1.9-.3 1.3c-.2.4-.4.6-.8.9-.3.2-.7.4-1 .5-.3 0-.7.1-1 .1zM434.4 49.3v-9.5h1.5v9.5h-1.5zm3.6 0v-9.5h2l2.8 7.3h.1l2.8-7.3h2v9.5h-1.4v-5.4l.1-1.7h-.1l-2.8 7.1h-1.2l-2.8-7.1h-.1l.1 1.7v5.4H438zm11.7 0v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.9.6 1.1 1 .3.4.4.9.4 1.5s-.1 1.1-.4 1.5c-.3.4-.7.8-1.1 1-.5.2-1 .4-1.6.4h-2.5v-1.4h2.5c.4 0 .7-.1.9-.2.2-.1.4-.3.5-.6.1-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.2-.5-.2-.9-.2h-1.8v8.2h-1.5zm8 0v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.8.6 1.1 1s.4.9.4 1.5c0 .4-.1.8-.2 1.1s-.4.7-.7.9c-.3.3-.6.5-1 .6-.4.1-.9.2-1.4.2h-2.3v-1.3h2.5c.3 0 .6-.1.8-.2.2-.1.4-.3.6-.6.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.1-.5-.2-.9-.2h-1.9v8.2h-1.4zm2.2-4.4h1.7l3 4.3v.1h-1.7l-3-4.4zm10.3 4.6c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.6.3-1.2.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5s-1.2.2-1.8.5c-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.2.5 1.8.5zm8.8 1.2-3.4-9.5h1.6l2.2 6.3.3 1.1h.1l.4-1.1 2.2-6.3h1.6l-3.5 9.5H479zm6.2 0v-9.5h5.8v1.4h-4.3V48h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4H486zm6.8 4.1v-9.5h2l2.8 7.3h.1l2.8-7.3h2v9.5H501v-5.4l.1-1.7h-.1l-2.8 7.1H497l-2.8-7.1h-.1l.1 1.7v5.4h-1.4zm11.8 0v-9.5h5.8v1.4h-4.3V48h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4h-4.6zm6.8 4.1v-9.5h1.7l4.3 7h.1l-.1-1.8v-5.2h1.5v9.5h-1.5l-4.5-7.4h-.1l.1 1.8v5.5h-1.5zm11.7 0v-8.8h1.5v8.8h-1.5zm-2.7-8.2v-1.4h6.8v1.4h-6.8z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st4&quot; d=&quot;M543.2 14.9h115.2v43.2H543.2V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M582.9 41.3v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.9.6 1.1 1 .3.4.4.9.4 1.5s-.1 1.1-.4 1.5c-.3.4-.7.8-1.1 1-.5.2-1 .4-1.6.4h-2.5v-1.4h2.5c.4 0 .7-.1.9-.2.2-.1.4-.3.5-.6.1-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.2-.5-.2-.9-.2h-1.8v8.2h-1.5zm12.3.2c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.7.3-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.1.5 1.8.5zm10.9 1.4c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.6.3-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5s-1.2.2-1.8.5c-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.2.5 1.8.5zm6.7 1.2v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.8.6 1.1 1s.4.9.4 1.5c0 .4-.1.8-.2 1.1s-.4.7-.7.9c-.3.3-.6.5-1 .6-.4.1-.9.2-1.4.2h-2.3v-1.3h2.5c.3 0 .6-.1.8-.2.2-.1.4-.3.6-.6.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.1-.5-.2-.9-.2h-1.9v8.2h-1.4zm2.2-4.4h1.7l3 4.3v.1H618l-3-4.4zM517.7 102.9c-.6 0-1.1-.1-1.7-.3-.6-.2-1-.6-1.5-1-.4-.5-.7-1.1-.9-1.8l1.7-.7c.2.6.4 1.1.8 1.5.4.4.9.6 1.6.6.7 0 1.2-.2 1.6-.6.4-.4.7-1 .7-1.6 0-.7-.2-1.2-.6-1.6-.4-.4-1-.7-1.6-.7-.4 0-.8.1-1.1.2-.3.2-.6.4-.8.7l-1.8-.8.7-6h6.4v1.7h-4.9l-.4 3.2h.1c.3-.2.6-.4.9-.5.4-.1.8-.2 1.3-.2.7 0 1.3.2 1.9.5.6.3 1 .8 1.4 1.4.4.6.5 1.3.5 2 0 .8-.2 1.5-.5 2.1-.4.6-.8 1.1-1.5 1.4-.7.3-1.5.5-2.3.5zm10.8 0c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.6.3-1.2.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.5.4 1 .6 1.6.6zm11.4 1.8c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.5.3-1.2.5-2 .5zm.1-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.4.4.9.6 1.6.6zm10.8 1.5v-8.8h1.8V95h.1c.2-.3.4-.5.7-.8s.6-.4.9-.5c.4-.1.7-.2 1.1-.2.7 0 1.2.2 1.7.5s.8.7 1 1.2c.3-.5.7-.8 1.2-1.2.5-.3 1.1-.5 1.8-.5 1 0 1.8.3 2.3 1 .5.6.8 1.5.8 2.5v5.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.7-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.8 1s-.3.9-.3 1.3v4.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.8-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.7 1s-.3.9-.3 1.3v4.7h-1.7zm18.6.3c-.7 0-1.3-.1-1.8-.3-.5-.2-.9-.5-1.3-.9-.3-.4-.6-.8-.7-1.2l1.7-.7c.2.5.5.8.9 1.1.4.2.8.4 1.3.4s.9-.1 1.2-.2c.3-.2.5-.4.5-.8 0-.2-.1-.5-.2-.6s-.4-.3-.6-.4l-.9-.3-1.1-.2c-.4-.1-.8-.3-1.2-.5-.4-.2-.7-.5-.9-.9-.2-.4-.3-.8-.3-1.2 0-.5.2-1 .5-1.4.3-.4.7-.7 1.2-.9.5-.2 1.1-.3 1.7-.3.6 0 1.1.1 1.5.2.5.1.9.3 1.2.6.3.3.6.6.8 1l-1.6.7c-.2-.4-.5-.7-.8-.8-.3-.2-.7-.2-1.1-.2-.4 0-.8.1-1.1.3-.3.2-.4.4-.4.7 0 .3.1.5.4.7.3.2.6.3 1 .4l1.3.3c.9.2 1.5.6 2 1 .4.4.7 1 .7 1.6 0 .6-.2 1.1-.5 1.5-.3.4-.8.7-1.3 1-.8.2-1.5.3-2.1.3zM389.2 102.6v-1.8l.4-.4.9-.9c.4-.4.7-.8 1.1-1.2l1.1-1.1.8-.8c.3-.3.6-.6.8-.9.2-.3.3-.5.4-.8.1-.2.1-.5.1-.8 0-.3-.1-.6-.2-.8-.1-.3-.4-.5-.7-.6-.3-.2-.6-.2-1.1-.2-.4 0-.7.1-1 .2-.3.2-.5.4-.7.6-.2.2-.3.5-.3.7l-1.7-.7c.1-.3.2-.6.4-.9.2-.3.4-.6.8-.9.3-.3.7-.5 1.1-.7.4-.2.9-.3 1.5-.3.8 0 1.4.2 2 .5.6.3 1 .7 1.3 1.2.3.5.5 1.1.5 1.7 0 .5-.1 1-.3 1.5-.2.5-.4.9-.7 1.3-.3.4-.6.7-.9 1-.2.1-.4.3-.6.6-.2.2-.5.5-.7.8l-.8.8-.7.7-.4.4h5.2v1.7h-7.6zm14.2.3c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.5.3-1.2.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.5.4 1 .6 1.6.6zm11.5 1.8c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.6.3-1.3.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.4.4.9.6 1.6.6zm10.8 1.5v-8.8h1.8V95h.1c.2-.3.4-.5.7-.8s.6-.4.9-.5c.4-.1.7-.2 1.1-.2.7 0 1.2.2 1.7.5s.8.7 1 1.2c.3-.5.7-.8 1.2-1.2.5-.3 1.1-.5 1.8-.5 1 0 1.8.3 2.3 1 .5.6.8 1.5.8 2.5v5.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.7-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.8 1s-.3.9-.3 1.3v4.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.8-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.7 1s-.3.9-.3 1.3v4.7h-1.7zm18.6.3c-.7 0-1.3-.1-1.8-.3-.5-.2-.9-.5-1.3-.9-.3-.4-.6-.8-.7-1.2l1.7-.7c.2.5.5.8.9 1.1.4.2.8.4 1.3.4s.9-.1 1.2-.2c.3-.2.5-.4.5-.8 0-.2-.1-.5-.2-.6-.2-.2-.4-.3-.6-.4l-.9-.3-1.1-.2c-.4-.1-.8-.3-1.2-.5-.4-.2-.7-.5-.9-.9-.2-.4-.3-.8-.3-1.2 0-.5.2-1 .5-1.4.3-.4.7-.7 1.2-.9.5-.2 1.1-.3 1.7-.3.6 0 1.1.1 1.5.2.5.1.9.3 1.2.6.3.3.6.6.8 1l-1.6.7c-.2-.4-.5-.7-.8-.8-.3-.2-.7-.2-1.1-.2-.4 0-.8.1-1.1.3-.3.2-.4.4-.4.7 0 .3.1.5.4.7.3.2.6.3 1 .4l1.3.3c.9.2 1.5.6 2 1 .4.4.7 1 .7 1.6 0 .6-.2 1.1-.5 1.5-.3.4-.8.7-1.3 1-.8.2-1.4.3-2.1.3zM0 113.3V99h1.7v14.3H0zm4.6 0v-10.2h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H4.6zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.5-.5-.7-1.2-.7-2.1zm10.3 3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V107h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .5-1.9.8-3 .8zm6.7-.3v-10.2H35v1.6h.1c.1-.4.4-.7.7-1 .3-.3.7-.5 1.1-.7.4-.2.8-.2 1.2-.2h.7c.2 0 .3.1.5.2v1.8c-.2-.1-.5-.2-.7-.2-.2-.1-.5-.1-.7-.1-.5 0-1 .1-1.4.4-.4.3-.7.7-1 1.1-.2.5-.4 1-.4 1.5v5.7h-1.7zm10.4.3c-.8 0-1.4-.1-2-.4-.6-.3-1-.7-1.3-1.2-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1.4.1.7.2 1 .3.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8-.3.3-.7.5-1.1.7-.5.1-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5-.5-.1-1-.2-1.5-.2-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4c.4.2 1 .4 1.6.4zm11.7 1.5c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-2 .7-2.8.4-.8 1.1-1.5 1.8-1.9.8-.5 1.7-.7 2.7-.7 1.1 0 2.1.3 2.8.8.7.5 1.3 1.2 1.6 2l-1.5.6c-.2-.6-.6-1.1-1.1-1.4-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.7.5s-.9.8-1.2 1.4c-.3.6-.5 1.3-.5 2 0 .8.2 1.4.5 2 .3.6.7 1 1.2 1.4.5.3 1.1.5 1.7.5.7 0 1.3-.2 1.9-.5.5-.3.9-.8 1.2-1.4l1.5.6c-.3.8-.9 1.5-1.6 2-.9.5-1.8.8-3 .8zm5.5-10.5h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm6.5 2.7v-10.2h1.7v10.2h-1.7zm.9-12.1c-.3 0-.6-.1-.9-.4-.2-.2-.4-.5-.4-.9 0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.3-.6.4-.9.4zm8.1 12.4c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.5-1.7.8-2.7.8zm0-1.6c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm7 1.3v-10.2H87v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zm15.1-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm10.5 3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.5-1.7.8-2.7.8zm0-1.6c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm12.2 1.3V99h2.1l7.2 11.4h.1l-.1-2.8V99h1.7v14.3h-1.8l-7.5-11.9h-.1l.1 2.8v9.2H125zm18.2.3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V107h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .5-1.9.8-3 .8zm5.5-.3 4.1-5.9h.2l2.9-4.3h2l-4 5.6h-.1l-3.1 4.6h-2zm.1-10.2h1.9l3.2 4.5h.1l4 5.7h-2l-3-4.5h-.1l-4.1-5.7zm9.9 0h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm11.2 2.7V99h4.8c.8 0 1.5.2 2.2.5.7.4 1.2.8 1.6 1.5.4.6.6 1.4.6 2.2 0 .8-.2 1.6-.6 2.2-.4.6-.9 1.1-1.6 1.5-.7.4-1.4.5-2.2.5h-3.9v-1.6h4c.6 0 1-.1 1.4-.4.4-.3.7-.6.9-1 .2-.4.3-.8.3-1.2 0-.4-.1-.8-.3-1.2-.2-.4-.5-.7-.9-1-.4-.3-.9-.4-1.4-.4h-3.2v12.7h-1.7zm14 .3c-.8 0-1.4-.1-2-.4-.6-.3-1-.7-1.3-1.2-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1.4.1.7.2 1 .3.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8-.3.3-.7.5-1.1.7-.5.1-.9.2-1.5.2zm.2-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5-.5-.1-1-.2-1.5-.2-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4c.4.2 1 .4 1.6.4zm7.4 1.2v-10.2h1.7v10.2h-1.7zm.8-12.1c-.3 0-.6-.1-.9-.4-.2-.2-.4-.5-.4-.9 0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.3-.5.4-.9.4zm3.5 12.1v-10.2h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zM418.1 55.2c-1.8 0-3.3 1.5-3.3 3.3 0 1.5 1 2.7 2.3 3.1V83h2V61.6c1.3-.4 2.3-1.7 2.3-3.1 0-1.8-1.5-3.3-3.3-3.3zM546.5 58.6c0-1.8-1.5-3.3-3.3-3.3s-3.3 1.5-3.3 3.3c0 1.5 1 2.7 2.3 3.1v21.2h2V61.7c1.3-.4 2.3-1.6 2.3-3.1z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
  &lt;figcaption&gt;
    Graphic showing the thresholds for good and poor INP.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Don&#39;t wait for INP to become a Core Web Vital in 2024 to start improving it. Your website may very well be in the &lt;a href=&quot;https://httparchive.org/reports/chrome-ux-report#cruxFastFid&quot; rel=&quot;noopener&quot;&gt;93%&lt;/a&gt; of sites that have good FID performance on mobile devices; however, you might be surprised to learn that only &lt;a href=&quot;https://httparchive.org/reports/chrome-ux-report#cruxFastInp&quot; rel=&quot;noopener&quot;&gt;65%&lt;/a&gt; of sites have good INP on mobile devices. INP paints a much more accurate picture of responsiveness, so these numbers help us to more clearly see the room for improvement ahead of us.&lt;/p&gt;
&lt;p&gt;To find out whether your site has INP issues, how to address them, and all things INP, the best place to start is the &lt;a href=&quot;https://web.dev/optimize-inp/&quot;&gt;INP optimization guide&lt;/a&gt;. Whether you&#39;re learning about responsiveness for the first time or you&#39;re a performance expert, we&#39;ve added a lot of new guidance to make it as easy as possible for everyone to learn how to measure and optimize INP.&lt;/p&gt;
&lt;p&gt;INP might take some time to learn, and that&#39;s just fine. To help you focus on the optimizations with the biggest ROI, earlier this year we published &lt;a href=&quot;https://web.dev/top-cwv-2023/&quot;&gt;a blog post&lt;/a&gt; to distill our guidance down to the most effective recommendations to improve Core Web Vitals. Specifically, we wrote about three must-know techniques that apply equally to optimizing FID and INP: avoid or break up long tasks, avoid unnecessary JavaScript, and avoid large rendering updates. You can learn more about these and many other INP optimization techniques in &lt;a href=&quot;https://web.dev/optimize-inp/&quot;&gt;our documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-road-ahead&quot;&gt;The road ahead &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/inp-cwv/#the-road-ahead&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A new bar for responsiveness has been set, and we&#39;re excited to see the community rise to the challenge for a better user experience. The early &lt;a href=&quot;https://groups.google.com/g/web-vitals-feedback&quot; rel=&quot;noopener&quot;&gt;feedback&lt;/a&gt; and &lt;a href=&quot;https://web.dev/tags/case-study/&quot;&gt;case studies&lt;/a&gt; have been promising, but we know that for many, it may be a long and unfamiliar road ahead. We strive to make that journey as easy as possible with improved &lt;a href=&quot;https://github.com/w3c/longtasks/blob/main/loaf-explainer.md&quot; rel=&quot;noopener&quot;&gt;diagnostics&lt;/a&gt;, &lt;a href=&quot;https://web.dev/vitals-tools/&quot;&gt;tools&lt;/a&gt;, and &lt;a href=&quot;https://web.dev/optimize-inp/&quot;&gt;documentation&lt;/a&gt; to help developers along the way.&lt;/p&gt;
&lt;p&gt;Stay tuned for updates on INP&#39;s exact graduation date in March 2024. And even though the metric is not experimental anymore, we&#39;re always open to feedback at &lt;a href=&quot;mailto:web-vitals-feedback@googlegroups.com&quot; rel=&quot;noopener&quot;&gt;web-vitals-feedback@googlegroups.com&lt;/a&gt; to help us improve INP and the Web Vitals program as a whole.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hero image from &lt;a href=&quot;https://unsplash.com/&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;, by &lt;a href=&quot;https://unsplash.com/@agebarros&quot; rel=&quot;noopener&quot;&gt;Agê Barros&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
      <author>
          <name>Rick Viscomi</name>
        </author><author>
          <name>Annie Sullivan</name>
        </author>
    </entry>
    
    
    
    <entry>
      <title>Economic Times quest for fixing INP</title>
      <link href="https://web.dev/economic-times-inp/"/>
      <updated>2023-05-10T00:00:00Z</updated>
      <id>https://web.dev/economic-times-inp/</id>
      <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://web.dev/inp/&quot;&gt;Interaction to Next Paint (INP)&lt;/a&gt; is a metric that assesses a website&#39;s responsiveness to user input. Good responsiveness means that a page is quick to respond to user interactions. The lower a page&#39;s INP is, the better it is able to respond to user interactions.&lt;/p&gt;
&lt;style&gt;
  .inp-mobile {
    display: inline;
  }

  .inp-desktop {
    display: none;
  }

  @media screen and (min-width: 640px) {
    .inp-mobile {
      display: none;
    }

    .inp-desktop {
      display: inline;
    }
  }
&lt;/style&gt;
&lt;figure&gt;
  &lt;svg title=&quot;A diagram of the INP thresholds. An INP at or below 200 milliseconds is considered good. Between 200 and 500 milliseconds suggests a page&#39;s responsiveness needs improvement. Anything over 500 milliseconds means that a page&#39;s responsiveness is poor.&quot; class=&quot;inp-mobile&quot; version=&quot;1.1&quot; id=&quot;Layer_1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; x=&quot;0&quot; y=&quot;0&quot; viewBox=&quot;0 0 296.6 220.2&quot; style=&quot;enable-background:new 0 0 296.6 220.2&quot; xml:space=&quot;preserve&quot;&gt;&lt;style&gt;.st0{fill:#2979FF} .st1{fill-rule:evenodd;clip-rule:evenodd;fill:#0CCE6B} .st2{fill:#191919} .st3{fill-rule:evenodd;clip-rule:evenodd;fill:#FFA400} .st4{fill-rule:evenodd;clip-rule:evenodd;fill:#FF4E42} @media screen and (prefers-color-scheme: light){.st2{fill:#191919}} [data-user-theme=light] .st2 {fill:#191919} @media screen and (prefers-color-scheme: dark){.st2{fill:#fff}} [data-user-theme=dark] .st2{fill:#fff}&lt;/style&gt;&lt;path class=&quot;st0&quot; d=&quot;M83.3 63V0h11.9v63H83.3zm26.3 0V0h13.8l25.3 42.2h.7l-.7-12.1V0h11.8v63H148l-26.8-44.6h-.7l.7 12.1V63h-11.6zm65.4 0V0h22.2c4.1 0 7.7.8 10.9 2.5s5.8 4 7.7 7 2.9 6.4 2.9 10.4c0 3.9-1 7.4-2.9 10.4s-4.5 5.4-7.7 7c-3.2 1.7-6.9 2.5-10.9 2.5h-15.6V28.6h15.9c2.1 0 3.8-.4 5.2-1.2s2.5-1.9 3.2-3.2c.7-1.3 1.1-2.8 1.1-4.3s-.4-2.9-1.1-4.2c-.7-1.3-1.8-2.3-3.2-3.2s-3.1-1.2-5.2-1.2h-10.7V63H175z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st1&quot; d=&quot;M0 137.1h96v38.4H0v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M34 161c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-.9-.4-.4-.7-.9-1-1.4-.2-.6-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.6.6-1 1-1.4.4-.4.9-.7 1.4-.9.5-.2 1.1-.3 1.8-.3s1.3.1 1.8.3c.6.2 1 .6 1.4 1l-.9.9c-.2-.2-.4-.4-.6-.5-.2-.1-.5-.3-.8-.3-.3-.1-.6-.1-.9-.1-.4 0-.8.1-1.2.2-.4.1-.7.4-1 .6-.3.3-.5.6-.7 1-.2.4-.2.8-.2 1.3s.1.9.2 1.3c.2.4.4.7.7 1 .3.3.6.5 1 .7.4.1.8.2 1.2.2.4 0 .8-.1 1.1-.2.3-.1.6-.3.9-.5.3-.2.5-.5.6-.8.2-.3.3-.6.3-1H34v-1.2h4.2v.7c0 .6-.1 1.2-.3 1.7-.2.5-.5.9-.9 1.3s-.8.6-1.3.8c-.5.3-1.1.4-1.7.4zm9.5 0c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8 0 .6-.1 1.2-.3 1.8-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.5.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm9.9 1.2c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8 0-.6.1-1.2.3-1.8.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8 0 .6-.1 1.2-.3 1.8-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.2.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm6 1.1v-8.6h2.8c.9 0 1.7.2 2.3.5.7.4 1.2.9 1.5 1.5.4.6.5 1.4.5 2.2 0 .8-.2 1.6-.5 2.2-.4.6-.9 1.2-1.5 1.5-.6.4-1.4.5-2.3.5h-2.8zm1.3-1.3h1.4c.6 0 1.2-.1 1.7-.4.5-.3.8-.6 1.1-1 .2-.5.4-1 .4-1.6 0-.6-.1-1.2-.4-1.6-.2-.5-.6-.8-1.1-1-.5-.3-1-.4-1.7-.4h-1.4v6z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st3&quot; d=&quot;M96 137.1h105.6v38.4H96v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M130.8 153.9v-8.6h1.6l3.9 6.3h.1l-.1-1.7v-4.7h1.3v8.6h-1.4l-4.1-6.6h-.1l.1 1.7v5h-1.3zm8.7 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V149h4.1v1.2h-4.1zm6.2 3.7v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V149h4.1v1.2h-4.1zm6.1 3.7v-8.6h2.8c.9 0 1.7.2 2.3.5.7.4 1.2.9 1.5 1.5.4.6.5 1.4.5 2.2s-.2 1.6-.5 2.2c-.4.6-.9 1.2-1.5 1.5-.6.4-1.4.5-2.3.5h-2.8zm1.3-1.3h1.4c.6 0 1.2-.1 1.7-.4.5-.2.8-.6 1.1-1 .2-.5.4-1 .4-1.6 0-.6-.1-1.2-.4-1.6-.2-.5-.6-.8-1.1-1-.5-.2-1-.4-1.7-.4h-1.4v6zm9.9 1.4c-.5 0-.9-.1-1.3-.3-.4-.2-.8-.4-1.1-.8-.3-.4-.5-.8-.7-1.3l1.2-.5c.1.5.3.9.7 1.2.3.3.7.5 1.2.5.3 0 .5 0 .8-.1.2-.1.4-.2.6-.4s.2-.4.2-.7c0-.3-.1-.5-.2-.7-.1-.2-.3-.3-.6-.5s-.6-.3-1-.5l-.5-.2c-.2-.1-.5-.2-.7-.3-.2-.1-.5-.3-.7-.5-.2-.2-.4-.4-.5-.7-.1-.3-.2-.6-.2-.9 0-.4.1-.8.3-1.2.2-.4.5-.6.9-.8.4-.2.9-.3 1.4-.3.6 0 1 .1 1.4.3.4.2.7.4.9.7.2.3.4.5.4.8l-1.2.5c0-.2-.1-.3-.2-.5s-.3-.3-.5-.4c-.2-.1-.4-.2-.8-.2-.2 0-.5.1-.7.2-.2.1-.4.2-.5.4-.1.2-.2.3-.2.6s.1.6.4.8c.3.2.6.4 1.1.5l.6.2c.3.1.6.2.8.3.3.1.5.3.7.5.2.2.4.4.5.7.1.3.2.6.2 1s-.1.8-.3 1.2c-.2.3-.4.6-.7.8-.3.2-.6.3-.9.4s-.5.2-.8.2zM107 167.9v-8.6h1.3v8.6H107zm3.2 0v-8.6h1.8l2.5 6.5h.1l2.5-6.5h1.8v8.6h-1.3V163l.1-1.5h-.1l-2.5 6.4h-1l-2.5-6.4h-.1l.1 1.5v4.9h-1.4zm10.6 0v-8.6h3c.5 0 1 .1 1.4.3.4.2.8.5 1 .9.3.4.4.9.4 1.4 0 .5-.1 1-.4 1.4-.2.4-.6.7-1 .9-.4.2-.9.3-1.4.3h-2.2v-1.2h2.3c.3 0 .6-.1.8-.2.2-.1.4-.3.5-.5.1-.2.2-.4.2-.7 0-.2-.1-.4-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.3h-1.4zm7.2 0v-8.6h3c.5 0 1 .1 1.4.3.4.2.7.5 1 .9.2.4.4.8.4 1.4 0 .3-.1.7-.2 1s-.3.6-.6.8c-.3.2-.6.4-1 .6-.4.1-.8.2-1.2.2h-2.1v-1.2h2.3c.3 0 .5-.1.7-.2.2-.1.4-.3.5-.5.1-.2.2-.5.2-.7 0-.2-.1-.5-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.4H128zm2-4h1.5l2.7 3.9v.1h-1.5l-2.7-4zm9.3 4.1c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.2.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm7.9 1.1-3-8.6h1.4l1.9 5.7.3 1h.1l.3-1 2-5.7h1.4l-3.1 8.6h-1.3zm5.6 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V163h4.1v1.2h-4.1zm6.2 3.7v-8.6h1.8l2.5 6.5h.1l2.5-6.5h1.8v8.6H167V163l.1-1.5h-.1l-2.5 6.4h-1l-2.5-6.4h-.1l.1 1.5v4.9h-1.3zm10.6 0v-8.6h5.2v1.2h-3.9v6.1h3.9v1.2h-5.2zm.7-3.7V163h4.1v1.2H171zm6.1 3.7v-8.6h1.6l3.9 6.3h.1l-.1-1.7v-4.7h1.3v8.6h-1.4l-4.1-6.6h-.1l.1 1.7v5h-1.3zm10.5 0V160h1.3v7.9h-1.3zm-2.4-7.4v-1.2h6.1v1.2h-6.1z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st4&quot; d=&quot;M200.6 137.1h96v38.4h-96v-38.4z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M232.5 160.9v-8.6h3c.5 0 1 .1 1.4.3.4.2.8.5 1 .9.3.4.4.9.4 1.4 0 .5-.1 1-.4 1.4-.2.4-.6.7-1 .9-.4.2-.9.3-1.4.3h-2.2v-1.2h2.3c.3 0 .6-.1.8-.2.2-.1.4-.3.5-.5.1-.2.2-.4.2-.7 0-.2-.1-.4-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.3h-1.4zm11 .1c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.5.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.6.3 1.1.4 1.6.4zm9.9 1.2c-.6 0-1.2-.1-1.8-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-.9-.9-1.4-.2-.5-.3-1.1-.3-1.8s.1-1.2.3-1.8c.2-.5.5-1 .9-1.4.4-.4.9-.7 1.4-1 .5-.2 1.1-.3 1.8-.3.6 0 1.2.1 1.8.3.5.2 1 .6 1.4 1 .4.4.7.9.9 1.4.2.5.3 1.1.3 1.8s-.1 1.2-.3 1.8c-.2.5-.5 1-.9 1.4-.4.4-.9.7-1.4 1-.6.2-1.1.3-1.8.3zm0-1.2c.6 0 1.1-.1 1.6-.4.5-.3.8-.7 1.1-1.1.3-.5.4-1.1.4-1.7 0-.6-.1-1.2-.4-1.7-.3-.5-.7-.9-1.1-1.1-.5-.3-1-.4-1.6-.4-.6 0-1.1.1-1.6.4-.5.3-.8.7-1.1 1.1-.3.5-.4 1-.4 1.7 0 .6.1 1.2.4 1.7.3.5.7.9 1.1 1.1.5.3 1 .4 1.6.4zm6 1.1v-8.6h3c.5 0 1 .1 1.4.3.4.2.7.5 1 .9.2.4.4.8.4 1.4 0 .3-.1.7-.2 1s-.3.6-.6.8c-.3.2-.6.4-1 .6-.4.1-.8.2-1.2.2h-2.1v-1.2h2.3c.3 0 .5-.1.7-.2.2-.1.4-.3.5-.5.1-.2.2-.5.2-.7 0-.2-.1-.5-.2-.7-.1-.2-.3-.4-.5-.5-.2-.1-.5-.2-.8-.2h-1.7v7.4h-1.2zm2-4h1.5l2.7 3.9v.1H264l-2.6-4zM178.1 219.9c-.5 0-1-.1-1.5-.3-.5-.2-1-.5-1.4-1-.4-.4-.7-1-.8-1.7l1.5-.6c.1.6.4 1 .8 1.4.4.4.9.5 1.4.5.6 0 1.1-.2 1.5-.6.4-.4.6-.9.6-1.5s-.2-1.1-.6-1.5c-.4-.4-.9-.6-1.5-.6-.4 0-.7.1-1 .2-.3.1-.5.4-.7.6l-1.7-.8.7-5.5h5.9v1.6h-4.5l-.4 2.9h.1c.2-.2.5-.3.8-.5.3-.1.7-.2 1.2-.2.6 0 1.2.2 1.7.5s1 .7 1.3 1.3c.3.5.5 1.2.5 1.9s-.2 1.3-.5 1.9c-.3.6-.8 1-1.3 1.3-.7.5-1.4.7-2.1.7zm9.9 0c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.2-1.2.4-1.9.4zm.1-1.7c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10.5 1.7c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.2-1.2.4-1.9.4zm0-1.7c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10 1.4v-8.2h1.6v1.1h.1c.2-.3.4-.5.6-.7.3-.2.6-.4.9-.5.3-.1.7-.2 1-.2.6 0 1.1.1 1.5.4.4.3.7.7.9 1.1.3-.4.6-.8 1.1-1.1.5-.3 1-.5 1.7-.5 1 0 1.7.3 2.1.9.5.6.7 1.4.7 2.3v5.2h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.8zm17.2.3c-.6 0-1.2-.1-1.7-.3-.5-.2-.9-.5-1.2-.8-.3-.3-.5-.7-.7-1.1l1.5-.7c.2.4.5.8.8 1 .4.2.8.3 1.2.3.4 0 .8-.1 1.1-.2.3-.2.5-.4.5-.8 0-.2-.1-.4-.2-.6-.1-.1-.3-.3-.6-.4-.2-.1-.5-.2-.8-.2l-1-.2c-.4-.1-.8-.3-1.1-.5-.3-.2-.6-.5-.8-.8-.2-.3-.3-.7-.3-1.1 0-.5.1-.9.4-1.3.3-.4.7-.6 1.1-.8.5-.2 1-.3 1.6-.3.5 0 1 .1 1.4.2.4.1.8.3 1.1.6.3.3.6.6.8 1l-1.5.7c-.2-.4-.4-.6-.7-.8-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.2-.4.4-.4.6 0 .3.1.5.4.7.2.2.5.3.9.4l1.2.3c.8.2 1.4.5 1.8.9.4.4.6.9.6 1.5 0 .5-.2 1-.5 1.4-.3.4-.7.7-1.2.9-.6.2-1.1.4-1.7.4zM69 220v-1.6s.2-.1.4-.4c.2-.2.5-.5.8-.9l1.1-1.1 1-1c.3-.3.5-.6.7-.8.3-.3.5-.6.7-.8.2-.2.3-.5.4-.7.1-.2.1-.5.1-.8 0-.3-.1-.5-.2-.8-.1-.3-.3-.4-.6-.6-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.1-.5.3-.6.6-.1.2-.3.4-.3.7l-1.5-.6c.1-.3.2-.5.4-.8.2-.3.4-.5.7-.8.3-.3.6-.5 1-.6.4-.2.9-.3 1.4-.2.7 0 1.3.2 1.9.5.5.3.9.7 1.2 1.2.3.5.4 1 .4 1.6 0 .5-.1.9-.2 1.3-.2.4-.4.8-.7 1.2-.3.4-.5.7-.8 1l-.5.5c-.2.2-.4.5-.7.7l-.7.7-.6.6-.4.4h4.8v1.6H69zm13.2.2c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.3-1.2.4-1.9.4zm0-1.6c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.4.3.9.5 1.5.5zm10.5 1.6c-.7 0-1.3-.1-1.9-.4-.5-.3-1-.7-1.4-1.2-.4-.5-.7-1.1-.9-1.8-.2-.7-.3-1.4-.3-2.2 0-.8.1-1.6.3-2.2.2-.7.5-1.3.9-1.8s.9-.9 1.4-1.2c.6-.3 1.2-.5 1.9-.5s1.3.2 1.9.5c.6.3 1 .7 1.4 1.2.4.5.7 1.1.9 1.8.2.7.3 1.4.3 2.2 0 .8-.1 1.6-.3 2.2-.2.7-.5 1.3-.9 1.8s-.9.9-1.4 1.2c-.6.3-1.2.4-1.9.4zm0-1.6c.6 0 1-.2 1.5-.5.4-.4.7-.9 1-1.5.2-.6.3-1.3.3-2.1s-.1-1.5-.3-2.1c-.2-.6-.5-1.1-1-1.5-.4-.4-.9-.5-1.5-.5s-1.1.2-1.5.5c-.4.4-.7.8-.9 1.5-.2.6-.3 1.3-.3 2.1s.1 1.5.3 2.1c.2.6.5 1.1.9 1.5.5.3 1 .5 1.5.5zm10 1.4v-8.2h1.6v1.1h.1c.2-.3.4-.5.6-.7.3-.2.6-.4.9-.5.3-.1.7-.2 1-.2.6 0 1.1.1 1.5.4.4.3.7.7.9 1.1.3-.4.6-.8 1.1-1.1.5-.3 1-.5 1.7-.5 1 0 1.7.3 2.1.9.5.6.7 1.4.7 2.3v5.2h-1.7v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4H108v-4.9c0-.7-.1-1.1-.4-1.4-.3-.3-.7-.5-1.2-.5-.4 0-.7.1-1 .3-.3.2-.5.5-.7.9-.2.4-.2.8-.2 1.2v4.4h-1.8zm17.2.2c-.6 0-1.2-.1-1.7-.3-.5-.2-.9-.5-1.2-.8-.3-.3-.5-.7-.7-1.1l1.5-.7c.2.4.5.8.8 1 .4.2.8.3 1.2.3.4 0 .8-.1 1.1-.2.3-.2.5-.4.5-.8 0-.2-.1-.4-.2-.6-.1-.1-.3-.3-.6-.4-.2-.1-.5-.2-.8-.2l-1-.2c-.4-.1-.8-.3-1.1-.5-.3-.2-.6-.5-.8-.8-.2-.3-.3-.7-.3-1.1 0-.5.1-.9.4-1.3.3-.4.7-.6 1.1-.8.5-.2 1-.3 1.6-.3.5 0 1 .1 1.4.2.4.1.8.3 1.1.6.3.3.6.6.8 1l-1.5.7c-.2-.4-.4-.6-.7-.8-.3-.1-.6-.2-1-.2s-.7.1-1 .2c-.3.2-.4.4-.4.6 0 .3.1.5.4.7.2.2.5.3.9.4l1.2.3c.8.2 1.4.5 1.8.9.4.4.6.9.6 1.5 0 .5-.2 1-.5 1.4-.3.4-.7.7-1.2.9-.5.3-1.1.4-1.7.4zM42.4 96.3V82h1.7v14.3h-1.7zm4.6 0V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H47zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.5-.6-.7-1.3-.7-2.2zm10.3 3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7s1-1.5 1.7-2 1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5H65V90h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-.9.6-1.8.8-2.9.8zm6.7-.3V86.1h1.6v1.6h.1c.1-.4.4-.7.7-1 .3-.3.7-.5 1.1-.7s.8-.2 1.2-.2h.7c.2 0 .3.1.5.2v1.8c-.2-.1-.5-.2-.7-.2-.2-.1-.5-.1-.7-.1-.5 0-1 .1-1.4.4-.4.3-.7.7-1 1.1-.2.5-.4 1-.4 1.5v5.7h-1.7zm10.4.3c-.8 0-1.4-.1-2-.4s-1-.7-1.3-1.2c-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1s.7.2 1 .3c.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8s-.7.5-1.1.7c-.5.2-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5s-1-.2-1.5-.2c-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4 1 .4 1.6.4zm11.8 1.5c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-2 .7-2.8.4-.8 1.1-1.5 1.8-1.9.8-.5 1.7-.7 2.7-.7 1.1 0 2.1.3 2.8.8.7.5 1.3 1.2 1.6 2l-1.5.6c-.2-.6-.6-1.1-1.1-1.4-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.7.5s-.9.8-1.2 1.4c-.3.6-.5 1.3-.5 2 0 .8.2 1.4.5 2 .3.6.7 1 1.2 1.4.5.3 1.1.5 1.7.5.7 0 1.3-.2 1.9-.5s.9-.8 1.2-1.4l1.5.6c-.3.8-.9 1.5-1.6 2s-1.9.8-3 .8zm5.5-10.5h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8s-.7-1.3-.7-2.2zm6.5 2.7V86.1h1.7v10.2h-1.7zm.9-12c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.9c0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.2-.6.4-.9.4zm8.1 12.3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2s.7 1.7.7 2.7c0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.6-1.7.8-2.7.8zm0-1.5c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1-.8-1-1.3-1.3c-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3-.5 1.3-.5 2.1.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm7 1.2V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zM143 86.1h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.6-.7-1.3-.7-2.2zm10.5 3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.6-1.7.8-2.7.8zm0-1.5c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm12.2 1.2V82h2.1l7.2 11.4h.1l-.1-2.8V82h1.7v14.3h-1.8l-7.5-11.9h-.1l.1 2.8v9.2h-1.7zm18.2.3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V90h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .6-1.9.8-3 .8zm5.5-.3 4.1-5.9h.2l2.9-4.3h2l-4 5.6h-.1l-3.1 4.6h-2zm.1-10.2h1.9l3.2 4.5h.1l4 5.7h-2l-3-4.5h-.1l-4.1-5.7zm9.9 0h6v1.5h-6v-1.5zm1.8 7.5V83.3h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.6-.7-1.3-.7-2.2zm11.2 2.7V82h4.8c.8 0 1.5.2 2.2.5.7.4 1.2.8 1.6 1.5.4.6.6 1.4.6 2.2 0 .8-.2 1.6-.6 2.2-.4.6-.9 1.1-1.6 1.5-.7.4-1.4.5-2.2.5H215v-1.6h4c.6 0 1-.1 1.4-.4.4-.3.7-.6.9-1 .2-.4.3-.8.3-1.2s-.1-.8-.3-1.2c-.2-.4-.5-.7-.9-1-.4-.3-.9-.4-1.4-.4h-3.2v12.7h-1.7zm14.1.3c-.8 0-1.4-.1-2-.4s-1-.7-1.3-1.2-.5-1.1-.5-1.8c0-.8.2-1.4.6-1.9s.9-.9 1.5-1.2c.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1s.7.2 1 .3c.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7s1.1-.2 1.6-.2c1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8s-.7.5-1.1.7c-.6.2-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5s-1-.2-1.5-.2c-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4 1 .4 1.6.4zm7.4 1.2V86.1h1.7v10.2h-1.7zm.8-12c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.9c0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.2.2-.5.4-.9.4zm3.5 12V86.1h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V90c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H240zm10.1-10.2h6v1.5h-6v-1.5zm1.7 7.5V83.3h1.7v10c0 .5.1.9.3 1.2s.6.4 1.1.4c.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8s-.7-1.3-.7-2.2zM96 172.8c-2.4 0-4.3 1.9-4.3 4.3 0 2 1.4 3.7 3.3 4.2v20.1h2v-20.1c1.9-.5 3.3-2.1 3.3-4.2 0-2.3-1.9-4.3-4.3-4.3zM201.6 172.6c-2.4 0-4.3 1.9-4.3 4.3 0 2 1.4 3.7 3.3 4.2v19.8h2v-19.8c1.9-.5 3.3-2.1 3.3-4.2 0-2.4-1.9-4.3-4.3-4.3z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
  &lt;svg title=&quot;A diagram of the INP thresholds. An INP at or below 200 milliseconds is considered good. Between 200 and 500 milliseconds suggests a page&#39;s responsiveness needs improvement. Anything over 500 milliseconds means that a page&#39;s responsiveness is poor.&quot; class=&quot;inp-desktop&quot; version=&quot;1.1&quot; id=&quot;Layer_1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; x=&quot;0&quot; y=&quot;0&quot; viewBox=&quot;0 0 658.4 113.6&quot; style=&quot;enable-background:new 0 0 658.4 113.6&quot; xml:space=&quot;preserve&quot;&gt;&lt;style&gt;.st0{fill: #2979FF} v.st1{fill-rule: evenodd;clip-rule: evenodd;fill: #0CCE6B} .st2 {fill: #191919} .st3{fill-rule: evenodd;clip-rule: evenodd;fill: #FFA400} .st4{fill-rule: evenodd;clip-rule: evenodd;fill: #FF4E42} @media screen and (prefers-color-scheme: light){.st2{fill: #191919}} @media screen and (prefers-color-scheme: dark){.st2{fill: #fff}} [data-user-theme=dark] .st2{fill: #fff}&lt;/style&gt;&lt;path class=&quot;st0&quot; d=&quot;M30.2 68.7V0h13v68.7h-13zm28.7 0V0H74l27.7 46.1h.8l-.8-13.2V0h12.9v68.7H101L71.7 20.1h-.8l.8 13.2v35.4H58.9zm71.3 0V0h24.2c4.4 0 8.4.9 11.9 2.7 3.5 1.8 6.3 4.4 8.4 7.6 2.1 3.3 3.1 7 3.1 11.3 0 4.3-1 8.1-3.1 11.4-2.1 3.3-4.9 5.8-8.4 7.7-3.5 1.8-7.5 2.7-11.9 2.7h-17V31.2h17.4c2.2 0 4.1-.4 5.7-1.3 1.5-.9 2.7-2.1 3.5-3.5.8-1.4 1.2-3 1.2-4.7 0-1.7-.4-3.2-1.2-4.6-.8-1.4-1.9-2.6-3.5-3.5-1.5-.9-3.4-1.3-5.7-1.3h-11.6v56.5h-13z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st1&quot; d=&quot;M303.2 14.9h115.2v43.2H303.2V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M345.3 41.5c-.7 0-1.3-.1-1.9-.4-.6-.2-1.1-.6-1.6-1s-.8-1-1.1-1.6c-.3-.6-.4-1.3-.4-2s.1-1.4.4-2c.3-.6.6-1.1 1.1-1.6.5-.5 1-.8 1.6-1 .6-.2 1.2-.4 1.9-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1l-1 1c-.2-.2-.4-.4-.7-.6-.3-.2-.5-.3-.9-.4-.3-.1-.6-.1-1-.1-.5 0-.9.1-1.3.3-.4.2-.8.4-1.1.7-.3.3-.6.7-.8 1.1-.2.4-.3.9-.3 1.5s.1 1 .3 1.5c.2.4.5.8.8 1.1.3.3.7.6 1.1.7.4.2.9.2 1.3.2s.8-.1 1.2-.2c.4-.1.7-.3 1-.5.3-.2.5-.5.7-.8.2-.3.3-.7.3-1.1h-3.3v-1.3h4.6v.8c0 .7-.1 1.3-.4 1.9-.2.6-.6 1-1 1.5-.4.4-.9.7-1.5.9-.3.2-.9.3-1.6.3zm10.5 0c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1-1.2.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3s.5-1.2.5-1.9-.2-1.3-.5-1.9-.7-1-1.2-1.3c-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3s-.5 1.2-.5 1.9.2 1.3.5 1.9.7 1 1.2 1.3c.6.4 1.2.5 1.8.5zm11 1.4c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3s.5-1.2.5-1.9-.2-1.3-.5-1.9-.7-1-1.2-1.3c-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3s-.5 1.2-.5 1.9.2 1.3.5 1.9.7 1 1.2 1.3c.6.4 1.2.5 1.8.5zm6.6 1.2v-9.5h3c1 0 1.9.2 2.6.6.7.4 1.3 1 1.7 1.7s.6 1.5.6 2.5c0 .9-.2 1.8-.6 2.5s-1 1.3-1.7 1.7c-.7.4-1.6.6-2.6.6h-3zm1.5-1.4h1.5c.7 0 1.3-.1 1.8-.4.5-.3.9-.7 1.2-1.2.3-.5.4-1.1.4-1.8s-.1-1.3-.4-1.8c-.3-.5-.7-.9-1.2-1.2-.5-.3-1.1-.4-1.8-.4h-1.5v6.8z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st3&quot; d=&quot;M418.4 14.9h124.8v43.2H418.4V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M460.8 33.3v-9.5h1.7l4.3 7h.1l-.1-1.8v-5.2h1.5v9.5h-1.5l-4.5-7.4h-.1l.1 1.8v5.5h-1.5zm9.7 0v-9.5h5.8v1.4H472V32h4.3v1.4h-5.8zm.7-4.1v-1.4h4.6v1.4h-4.6zm6.9 4.1v-9.5h5.8v1.4h-4.3V32h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4h-4.6zm6.8 4.1v-9.5h3c1 0 1.9.2 2.6.6.7.4 1.3 1 1.7 1.7s.6 1.5.6 2.5c0 .9-.2 1.8-.6 2.5s-1 1.3-1.7 1.7c-.7.4-1.6.6-2.6.6h-3zm1.5-1.4h1.5c.7 0 1.3-.1 1.8-.4.5-.3.9-.7 1.2-1.2.3-.5.4-1.1.4-1.8s-.1-1.3-.4-1.8c-.3-.5-.7-.9-1.2-1.2-.5-.3-1.1-.4-1.8-.4h-1.5v6.8zm10.9 1.6c-.5 0-1-.1-1.5-.3-.5-.2-.9-.5-1.2-.9-.3-.4-.6-.9-.8-1.5l1.4-.6c.1.5.4.9.8 1.3.4.3.8.5 1.3.5.3 0 .6-.1.8-.2.3-.1.5-.3.6-.5.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.6-.5-.3-.2-.7-.3-1.1-.5l-.6-.2c-.3-.1-.5-.2-.8-.4-.3-.1-.5-.3-.7-.5-.2-.2-.4-.5-.5-.7-.1-.3-.2-.6-.2-1 0-.5.1-.9.4-1.3.2-.4.6-.7 1-.9.4-.2 1-.4 1.6-.4.6 0 1.1.1 1.5.3.4.2.7.5 1 .8.2.3.4.6.5.9l-1.3.6c-.1-.2-.2-.4-.3-.5-.1-.2-.3-.3-.5-.4-.2-.1-.5-.2-.8-.2-.3 0-.5.1-.8.2-.2.1-.4.2-.6.4-.1.2-.2.4-.2.6 0 .3.1.6.4.8s.7.4 1.2.6l.6.2c.3.1.6.2.9.4.3.1.6.3.8.6.2.2.4.5.6.8.1.3.2.7.2 1.2s-.1.9-.3 1.3c-.2.4-.4.6-.8.9-.3.2-.7.4-1 .5-.3 0-.7.1-1 .1zM434.4 49.3v-9.5h1.5v9.5h-1.5zm3.6 0v-9.5h2l2.8 7.3h.1l2.8-7.3h2v9.5h-1.4v-5.4l.1-1.7h-.1l-2.8 7.1h-1.2l-2.8-7.1h-.1l.1 1.7v5.4H438zm11.7 0v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.9.6 1.1 1 .3.4.4.9.4 1.5s-.1 1.1-.4 1.5c-.3.4-.7.8-1.1 1-.5.2-1 .4-1.6.4h-2.5v-1.4h2.5c.4 0 .7-.1.9-.2.2-.1.4-.3.5-.6.1-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.2-.5-.2-.9-.2h-1.8v8.2h-1.5zm8 0v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.8.6 1.1 1s.4.9.4 1.5c0 .4-.1.8-.2 1.1s-.4.7-.7.9c-.3.3-.6.5-1 .6-.4.1-.9.2-1.4.2h-2.3v-1.3h2.5c.3 0 .6-.1.8-.2.2-.1.4-.3.6-.6.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.1-.5-.2-.9-.2h-1.9v8.2h-1.4zm2.2-4.4h1.7l3 4.3v.1h-1.7l-3-4.4zm10.3 4.6c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.6.3-1.2.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5s-1.2.2-1.8.5c-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.2.5 1.8.5zm8.8 1.2-3.4-9.5h1.6l2.2 6.3.3 1.1h.1l.4-1.1 2.2-6.3h1.6l-3.5 9.5H479zm6.2 0v-9.5h5.8v1.4h-4.3V48h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4H486zm6.8 4.1v-9.5h2l2.8 7.3h.1l2.8-7.3h2v9.5H501v-5.4l.1-1.7h-.1l-2.8 7.1H497l-2.8-7.1h-.1l.1 1.7v5.4h-1.4zm11.8 0v-9.5h5.8v1.4h-4.3V48h4.3v1.4h-5.8zm.8-4.1v-1.4h4.6v1.4h-4.6zm6.8 4.1v-9.5h1.7l4.3 7h.1l-.1-1.8v-5.2h1.5v9.5h-1.5l-4.5-7.4h-.1l.1 1.8v5.5h-1.5zm11.7 0v-8.8h1.5v8.8h-1.5zm-2.7-8.2v-1.4h6.8v1.4h-6.8z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st4&quot; d=&quot;M543.2 14.9h115.2v43.2H543.2V14.9z&quot;&gt;&lt;/path&gt;&lt;path class=&quot;st2&quot; d=&quot;M582.9 41.3v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.9.6 1.1 1 .3.4.4.9.4 1.5s-.1 1.1-.4 1.5c-.3.4-.7.8-1.1 1-.5.2-1 .4-1.6.4h-2.5v-1.4h2.5c.4 0 .7-.1.9-.2.2-.1.4-.3.5-.6.1-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.2-.5-.2-.9-.2h-1.8v8.2h-1.5zm12.3.2c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.7.3-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.8.5-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.1.5 1.8.5zm10.9 1.4c-.7 0-1.4-.1-2-.4-.6-.3-1.1-.6-1.6-1.1-.4-.5-.8-1-1-1.6-.2-.6-.4-1.2-.4-1.9s.1-1.3.4-1.9c.2-.6.6-1.1 1-1.6s1-.8 1.6-1.1c.6-.3 1.3-.4 2-.4s1.4.1 2 .4c.6.2 1.1.6 1.6 1.1.5.5.8 1 1 1.6.2.6.4 1.2.4 1.9s-.1 1.3-.4 1.9c-.2.6-.6 1.1-1 1.6s-1 .8-1.6 1.1c-.6.3-1.3.4-2 .4zm0-1.4c.6 0 1.2-.2 1.8-.5.5-.3.9-.7 1.2-1.3.3-.5.5-1.2.5-1.9s-.2-1.3-.5-1.9c-.3-.5-.7-1-1.2-1.3-.5-.3-1.1-.5-1.8-.5s-1.2.2-1.8.5c-.5.3-.9.7-1.2 1.3-.3.5-.5 1.2-.5 1.9s.2 1.3.5 1.9c.3.5.7 1 1.2 1.3.6.4 1.2.5 1.8.5zm6.7 1.2v-9.5h3.3c.6 0 1.1.1 1.6.4.5.2.8.6 1.1 1s.4.9.4 1.5c0 .4-.1.8-.2 1.1s-.4.7-.7.9c-.3.3-.6.5-1 .6-.4.1-.9.2-1.4.2h-2.3v-1.3h2.5c.3 0 .6-.1.8-.2.2-.1.4-.3.6-.6.2-.2.2-.5.2-.8 0-.3-.1-.5-.2-.7-.1-.2-.3-.4-.5-.6-.2-.1-.5-.2-.9-.2h-1.9v8.2h-1.4zm2.2-4.4h1.7l3 4.3v.1H618l-3-4.4zM517.7 102.9c-.6 0-1.1-.1-1.7-.3-.6-.2-1-.6-1.5-1-.4-.5-.7-1.1-.9-1.8l1.7-.7c.2.6.4 1.1.8 1.5.4.4.9.6 1.6.6.7 0 1.2-.2 1.6-.6.4-.4.7-1 .7-1.6 0-.7-.2-1.2-.6-1.6-.4-.4-1-.7-1.6-.7-.4 0-.8.1-1.1.2-.3.2-.6.4-.8.7l-1.8-.8.7-6h6.4v1.7h-4.9l-.4 3.2h.1c.3-.2.6-.4.9-.5.4-.1.8-.2 1.3-.2.7 0 1.3.2 1.9.5.6.3 1 .8 1.4 1.4.4.6.5 1.3.5 2 0 .8-.2 1.5-.5 2.1-.4.6-.8 1.1-1.5 1.4-.7.3-1.5.5-2.3.5zm10.8 0c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.6.3-1.2.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.5.4 1 .6 1.6.6zm11.4 1.8c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.5.3-1.2.5-2 .5zm.1-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.4.4.9.6 1.6.6zm10.8 1.5v-8.8h1.8V95h.1c.2-.3.4-.5.7-.8s.6-.4.9-.5c.4-.1.7-.2 1.1-.2.7 0 1.2.2 1.7.5s.8.7 1 1.2c.3-.5.7-.8 1.2-1.2.5-.3 1.1-.5 1.8-.5 1 0 1.8.3 2.3 1 .5.6.8 1.5.8 2.5v5.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.7-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.8 1s-.3.9-.3 1.3v4.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.8-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.7 1s-.3.9-.3 1.3v4.7h-1.7zm18.6.3c-.7 0-1.3-.1-1.8-.3-.5-.2-.9-.5-1.3-.9-.3-.4-.6-.8-.7-1.2l1.7-.7c.2.5.5.8.9 1.1.4.2.8.4 1.3.4s.9-.1 1.2-.2c.3-.2.5-.4.5-.8 0-.2-.1-.5-.2-.6s-.4-.3-.6-.4l-.9-.3-1.1-.2c-.4-.1-.8-.3-1.2-.5-.4-.2-.7-.5-.9-.9-.2-.4-.3-.8-.3-1.2 0-.5.2-1 .5-1.4.3-.4.7-.7 1.2-.9.5-.2 1.1-.3 1.7-.3.6 0 1.1.1 1.5.2.5.1.9.3 1.2.6.3.3.6.6.8 1l-1.6.7c-.2-.4-.5-.7-.8-.8-.3-.2-.7-.2-1.1-.2-.4 0-.8.1-1.1.3-.3.2-.4.4-.4.7 0 .3.1.5.4.7.3.2.6.3 1 .4l1.3.3c.9.2 1.5.6 2 1 .4.4.7 1 .7 1.6 0 .6-.2 1.1-.5 1.5-.3.4-.8.7-1.3 1-.8.2-1.5.3-2.1.3zM389.2 102.6v-1.8l.4-.4.9-.9c.4-.4.7-.8 1.1-1.2l1.1-1.1.8-.8c.3-.3.6-.6.8-.9.2-.3.3-.5.4-.8.1-.2.1-.5.1-.8 0-.3-.1-.6-.2-.8-.1-.3-.4-.5-.7-.6-.3-.2-.6-.2-1.1-.2-.4 0-.7.1-1 .2-.3.2-.5.4-.7.6-.2.2-.3.5-.3.7l-1.7-.7c.1-.3.2-.6.4-.9.2-.3.4-.6.8-.9.3-.3.7-.5 1.1-.7.4-.2.9-.3 1.5-.3.8 0 1.4.2 2 .5.6.3 1 .7 1.3 1.2.3.5.5 1.1.5 1.7 0 .5-.1 1-.3 1.5-.2.5-.4.9-.7 1.3-.3.4-.6.7-.9 1-.2.1-.4.3-.6.6-.2.2-.5.5-.7.8l-.8.8-.7.7-.4.4h5.2v1.7h-7.6zm14.2.3c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.5.3-1.2.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.5.4 1 .6 1.6.6zm11.5 1.8c-.7 0-1.4-.2-2-.5-.6-.3-1.1-.8-1.5-1.3-.4-.6-.8-1.2-1-2-.2-.8-.3-1.6-.3-2.4 0-.9.1-1.7.3-2.5.2-.8.6-1.4 1-2 .4-.6.9-1 1.5-1.3.6-.3 1.3-.5 2-.5.8 0 1.4.2 2 .5.6.3 1.1.8 1.5 1.3.4.6.8 1.2 1 2 .2.8.3 1.6.3 2.5 0 .9-.1 1.7-.3 2.4-.2.8-.5 1.4-1 2-.4.6-.9 1-1.5 1.3-.6.3-1.3.5-2 .5zm0-1.8c.6 0 1.1-.2 1.6-.6.4-.4.8-.9 1-1.6.2-.7.4-1.4.4-2.2 0-.8-.1-1.6-.4-2.3-.2-.7-.6-1.2-1-1.6-.4-.4-1-.6-1.6-.6-.6 0-1.2.2-1.6.6-.4.4-.8.9-1 1.6-.2.7-.4 1.4-.4 2.3 0 .8.1 1.6.4 2.2.2.7.6 1.2 1 1.6.4.4.9.6 1.6.6zm10.8 1.5v-8.8h1.8V95h.1c.2-.3.4-.5.7-.8s.6-.4.9-.5c.4-.1.7-.2 1.1-.2.7 0 1.2.2 1.7.5s.8.7 1 1.2c.3-.5.7-.8 1.2-1.2.5-.3 1.1-.5 1.8-.5 1 0 1.8.3 2.3 1 .5.6.8 1.5.8 2.5v5.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.7-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.8 1s-.3.9-.3 1.3v4.7h-1.9v-5.4c0-.7-.2-1.2-.5-1.5-.3-.3-.8-.5-1.3-.5-.4 0-.8.1-1.1.4-.3.2-.6.6-.7 1s-.3.9-.3 1.3v4.7h-1.7zm18.6.3c-.7 0-1.3-.1-1.8-.3-.5-.2-.9-.5-1.3-.9-.3-.4-.6-.8-.7-1.2l1.7-.7c.2.5.5.8.9 1.1.4.2.8.4 1.3.4s.9-.1 1.2-.2c.3-.2.5-.4.5-.8 0-.2-.1-.5-.2-.6-.2-.2-.4-.3-.6-.4l-.9-.3-1.1-.2c-.4-.1-.8-.3-1.2-.5-.4-.2-.7-.5-.9-.9-.2-.4-.3-.8-.3-1.2 0-.5.2-1 .5-1.4.3-.4.7-.7 1.2-.9.5-.2 1.1-.3 1.7-.3.6 0 1.1.1 1.5.2.5.1.9.3 1.2.6.3.3.6.6.8 1l-1.6.7c-.2-.4-.5-.7-.8-.8-.3-.2-.7-.2-1.1-.2-.4 0-.8.1-1.1.3-.3.2-.4.4-.4.7 0 .3.1.5.4.7.3.2.6.3 1 .4l1.3.3c.9.2 1.5.6 2 1 .4.4.7 1 .7 1.6 0 .6-.2 1.1-.5 1.5-.3.4-.8.7-1.3 1-.8.2-1.4.3-2.1.3zM0 113.3V99h1.7v14.3H0zm4.6 0v-10.2h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7H4.6zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.5-.5-.7-1.2-.7-2.1zm10.3 3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V107h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .5-1.9.8-3 .8zm6.7-.3v-10.2H35v1.6h.1c.1-.4.4-.7.7-1 .3-.3.7-.5 1.1-.7.4-.2.8-.2 1.2-.2h.7c.2 0 .3.1.5.2v1.8c-.2-.1-.5-.2-.7-.2-.2-.1-.5-.1-.7-.1-.5 0-1 .1-1.4.4-.4.3-.7.7-1 1.1-.2.5-.4 1-.4 1.5v5.7h-1.7zm10.4.3c-.8 0-1.4-.1-2-.4-.6-.3-1-.7-1.3-1.2-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1.4.1.7.2 1 .3.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8-.3.3-.7.5-1.1.7-.5.1-1 .2-1.5.2zm.1-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5-.5-.1-1-.2-1.5-.2-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4c.4.2 1 .4 1.6.4zm11.7 1.5c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-2 .7-2.8.4-.8 1.1-1.5 1.8-1.9.8-.5 1.7-.7 2.7-.7 1.1 0 2.1.3 2.8.8.7.5 1.3 1.2 1.6 2l-1.5.6c-.2-.6-.6-1.1-1.1-1.4-.5-.3-1.1-.5-1.8-.5-.6 0-1.2.2-1.7.5s-.9.8-1.2 1.4c-.3.6-.5 1.3-.5 2 0 .8.2 1.4.5 2 .3.6.7 1 1.2 1.4.5.3 1.1.5 1.7.5.7 0 1.3-.2 1.9-.5.5-.3.9-.8 1.2-1.4l1.5.6c-.3.8-.9 1.5-1.6 2-.9.5-1.8.8-3 .8zm5.5-10.5h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm6.5 2.7v-10.2h1.7v10.2h-1.7zm.9-12.1c-.3 0-.6-.1-.9-.4-.2-.2-.4-.5-.4-.9 0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.3-.6.4-.9.4zm8.1 12.4c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.5-1.7.8-2.7.8zm0-1.6c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm7 1.3v-10.2H87v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zm15.1-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm10.5 3c-1 0-1.9-.2-2.7-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.7-1.7-.7-2.8 0-1 .2-1.9.7-2.8.4-.8 1.1-1.5 1.8-2 .8-.5 1.7-.7 2.7-.7 1 0 1.9.2 2.7.7.8.5 1.4 1.1 1.9 2 .4.8.7 1.7.7 2.7 0 1-.2 1.9-.7 2.8-.4.8-1.1 1.5-1.9 1.9-.8.5-1.7.8-2.7.8zm0-1.6c.6 0 1.2-.2 1.7-.5s1-.8 1.3-1.3c.3-.6.5-1.3.5-2.1s-.2-1.5-.5-2.1c-.3-.6-.8-1-1.3-1.3-.5-.3-1.1-.5-1.7-.5-.6 0-1.2.2-1.7.5s-1 .7-1.3 1.3c-.3.6-.5 1.3-.5 2.1s.2 1.5.5 2.1c.3.6.8 1 1.3 1.3.5.4 1.1.5 1.7.5zm12.2 1.3V99h2.1l7.2 11.4h.1l-.1-2.8V99h1.7v14.3h-1.8l-7.5-11.9h-.1l.1 2.8v9.2H125zm18.2.3c-1 0-1.9-.2-2.6-.7-.8-.5-1.4-1.1-1.8-1.9-.4-.8-.6-1.7-.6-2.8 0-1 .2-1.9.6-2.7.4-.8 1-1.5 1.7-2s1.6-.8 2.6-.8 1.9.2 2.6.7c.7.4 1.3 1.1 1.7 1.8.4.8.6 1.7.6 2.7v.5h-8.8V107h7c0-.3-.1-.6-.2-.9-.1-.3-.3-.6-.5-.9-.2-.3-.6-.5-.9-.7-.4-.2-.8-.3-1.4-.3-.7 0-1.2.2-1.7.5s-.8.8-1.1 1.4c-.3.6-.4 1.2-.4 2 0 .9.2 1.6.5 2.2.3.6.8 1 1.3 1.3.5.3 1.1.4 1.7.4.8 0 1.4-.2 1.8-.5.5-.4.9-.8 1.2-1.3l1.4.7c-.4.8-1 1.4-1.7 1.9-1 .5-1.9.8-3 .8zm5.5-.3 4.1-5.9h.2l2.9-4.3h2l-4 5.6h-.1l-3.1 4.6h-2zm.1-10.2h1.9l3.2 4.5h.1l4 5.7h-2l-3-4.5h-.1l-4.1-5.7zm9.9 0h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zm11.2 2.7V99h4.8c.8 0 1.5.2 2.2.5.7.4 1.2.8 1.6 1.5.4.6.6 1.4.6 2.2 0 .8-.2 1.6-.6 2.2-.4.6-.9 1.1-1.6 1.5-.7.4-1.4.5-2.2.5h-3.9v-1.6h4c.6 0 1-.1 1.4-.4.4-.3.7-.6.9-1 .2-.4.3-.8.3-1.2 0-.4-.1-.8-.3-1.2-.2-.4-.5-.7-.9-1-.4-.3-.9-.4-1.4-.4h-3.2v12.7h-1.7zm14 .3c-.8 0-1.4-.1-2-.4-.6-.3-1-.7-1.3-1.2-.3-.5-.5-1.1-.5-1.8 0-.8.2-1.4.6-1.9.4-.5.9-.9 1.5-1.2.7-.3 1.4-.4 2.2-.4.4 0 .9 0 1.2.1.4.1.7.2 1 .3.3.1.5.2.7.3v-.6c0-.8-.3-1.4-.8-1.8-.5-.5-1.2-.7-2-.7-.6 0-1.1.1-1.6.4-.5.2-.9.6-1.1 1l-1.3-1c.3-.4.6-.7 1-1 .4-.3.9-.5 1.4-.7.5-.2 1.1-.2 1.6-.2 1.4 0 2.5.4 3.2 1.1.8.7 1.2 1.7 1.2 3v6.5h-1.6v-1.5h-.1c-.2.3-.4.6-.7.8-.3.3-.7.5-1.1.7-.5.1-.9.2-1.5.2zm.2-1.5c.6 0 1.1-.1 1.6-.4.5-.3.9-.7 1.2-1.2.3-.5.5-1 .5-1.6-.3-.2-.7-.4-1.2-.5-.5-.1-1-.2-1.5-.2-1 0-1.7.2-2.1.6-.4.4-.7.9-.7 1.5s.2 1 .6 1.4c.4.2 1 .4 1.6.4zm7.4 1.2v-10.2h1.7v10.2h-1.7zm.8-12.1c-.3 0-.6-.1-.9-.4-.2-.2-.4-.5-.4-.9 0-.3.1-.6.4-.9.2-.2.5-.4.9-.4.3 0 .6.1.9.4.2.2.4.5.4.9 0 .3-.1.6-.4.9-.3.3-.5.4-.9.4zm3.5 12.1v-10.2h1.6v1.5h.1c.3-.5.7-.9 1.3-1.3.6-.4 1.3-.5 2-.5 1.2 0 2.2.4 2.8 1.1.6.7 1 1.7 1 2.9v6.5h-1.7V107c0-1-.2-1.7-.7-2.1-.5-.4-1.1-.6-1.8-.6-.6 0-1.1.2-1.5.5-.4.3-.8.7-1 1.2-.2.5-.4 1-.4 1.6v5.7h-1.7zm10-10.2h6v1.5h-6v-1.5zm1.8 7.5v-10.4h1.7v10c0 .5.1.9.3 1.2.2.3.6.4 1.1.4.2 0 .4 0 .6-.1.2-.1.4-.2.5-.2v1.7c-.2.1-.4.1-.6.2-.2.1-.5.1-.8.1-.9 0-1.5-.2-2.1-.8-.4-.5-.7-1.2-.7-2.1zM418.1 55.2c-1.8 0-3.3 1.5-3.3 3.3 0 1.5 1 2.7 2.3 3.1V83h2V61.6c1.3-.4 2.3-1.7 2.3-3.1 0-1.8-1.5-3.3-3.3-3.3zM546.5 58.6c0-1.8-1.5-3.3-3.3-3.3s-3.3 1.5-3.3 3.3c0 1.5 1 2.7 2.3 3.1v21.2h2V61.7c1.3-.4 2.3-1.6 2.3-3.1z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-fuzzy-beginning&quot;&gt;The fuzzy beginning &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#the-fuzzy-beginning&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When Google initially introduced INP as an experimental metric with the potential to evolve into one of the Core Web Vitals metrics, the Economic Times team took up the challenge to fix it before it graduates into one, since providing a world class user experience is crucial to our core business values.&lt;/p&gt;
&lt;p&gt;INP has been one of the most difficult metrics to solve thus far. In the beginning, it was unclear on how to measure INP effectively. What made it more difficult was the lack of community support—including most Real User Monitoring (RUM) providers not supporting it yet. However, we had Google RUM tools like &lt;a href=&quot;https://developer.chrome.com/docs/crux/about/&quot; rel=&quot;noopener&quot;&gt;Chrome User Experience Report (CrUX)&lt;/a&gt;, the &lt;a href=&quot;https://github.com/GoogleChrome/web-vitals&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;web-vitals&lt;/code&gt; JavaScript library&lt;/a&gt;, and others supporting it, which gave us a sense of where we stood while we were evaluating the path ahead. Our INP was close to 1,000 milliseconds at the origin level when we started.&lt;/p&gt;
&lt;p&gt;One thing that emerged while fixing INP in &lt;a href=&quot;https://web.dev/find-slow-interactions-in-the-field/&quot;&gt;the field&lt;/a&gt; was that one of the lab metrics to target could be &lt;a href=&quot;https://web.dev/tbt/&quot;&gt;Total Blocking Time (TBT)&lt;/a&gt;. TBT was already well documented and supported by the community. Despite already meeting the thresholds for Core Web Vitals, however, we weren&#39;t doing as well on the TBT front, as it was over 3 seconds when we began.&lt;/p&gt;
&lt;h2 id=&quot;what-is-tbt,-and-what-steps-did-we-take-to-improve-it&quot;&gt;What is TBT, and what steps did we take to improve it? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#what-is-tbt,-and-what-steps-did-we-take-to-improve-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TBT is a lab metric that measures the responsiveness of a web page to user input during page load. Any task that takes more than 50 milliseconds to execute is considered a long task, and the time after the 50 millisecond threshold is known as the &lt;strong&gt;blocking time&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;TBT is calculated by taking the sum of the blocking time of all long tasks during page load. For example, if there are two long tasks during load, the blocking time is determined as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Task A takes 80 milliseconds (30 milliseconds more than 50 milliseconds).&lt;/li&gt;
&lt;li&gt;Task B takes 100 milliseconds (50 milliseconds more than 50 milliseconds).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The page&#39;s TBT will be: 80 milliseconds (30 + 50). The lower the TBT, the better, and TBT also &lt;a href=&quot;https://almanac.httparchive.org/en/2022/performance#inp-and-tbt&quot; rel=&quot;noopener&quot;&gt;correlates well with INP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here’s a quick lab comparison of our TBT before and after taking steps to improve it:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A composite image of long tasks during startup as shown in the performance panel of Chrome DevTools, and a report of page metrics. The main thread is blocked during page load for 3,260 milliseconds.&quot; decoding=&quot;async&quot; height=&quot;502&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/UfZ9zaCLHjCMcPg74xHV.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    The main thread during startup before optimizing TBT. The TBT is 3,260 milliseconds.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A composite image of long tasks during startup as shown in the performance panel of Chrome DevTools, and a report of page metrics. The main thread is blocked during page load for 120 milliseconds.&quot; decoding=&quot;async&quot; height=&quot;701&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/RLx2y7zTItkaklqxSG17.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    The main thread during startup after optimizing TBT. The TBT is 120 milliseconds.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;minimize-main-thread-work&quot;&gt;Minimize main thread work &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#minimize-main-thread-work&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The browser’s main thread handles everything from parsing HTML, building the DOM, to parsing CSS and applying styles, as well as evaluating and executing JavaScript. The main thread also handles user interactions—that is, click, tap, and keypresses. If the main thread is occupied with doing other work, it may not respond to user inputs efficiently, and may lead to a janky user experience.&lt;/p&gt;
&lt;p&gt;This was the most difficult task for us, since we have our own algorithms to detect user identity for serving ads based on subscription status and third party scripts for A/B testing, analytics, and more.&lt;/p&gt;
&lt;p&gt;We took small steps at first, such as de-prioritizing loading of less critical business assets. Second, we used &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/requestIdleCallback&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;requestIdleCallback&lt;/code&gt;&lt;/a&gt; for non-critical work, which can help to reduce TBT.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;requestIdleCallback&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;requestIdleCallbackId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requestIdleCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchMarketsData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;fetchMarketsData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Fallback in case requestIdleCallback is not supported&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Specifying a timeout is recommended when using &lt;code&gt;requestIdleCallback&lt;/code&gt;, since it makes sure that if the given time is elapsed and the callback is not already been called, it executes the callback immediately after the timeout.&lt;/p&gt;
&lt;h3 id=&quot;minimize-script-evaluation-time&quot;&gt;Minimize script evaluation time &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#minimize-script-evaluation-time&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We also lazy loaded third party libraries using &lt;a href=&quot;https://loadable-components.com/&quot; rel=&quot;noopener&quot;&gt;Loadable components&lt;/a&gt;. We also removed unused JavaScript and CSS by profiling the page with the &lt;a href=&quot;https://developer.chrome.com/docs/devtools/coverage/&quot; rel=&quot;noopener&quot;&gt;coverage tool&lt;/a&gt; in Chrome DevTools. It helped us to identify areas where &lt;a href=&quot;https://webpack.js.org/guides/tree-shaking/&quot; rel=&quot;noopener&quot;&gt;tree shaking&lt;/a&gt; was needed to ship less code during page load, and therefore reduce the initial bundle size of the application.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the coverage tool in Chrome DevTools. Here, the tool displays unused portions of JavaScript and CSS files during page load.&quot; decoding=&quot;async&quot; height=&quot;100&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/uynCVTUjcv4ujJva41PS.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;reduce-dom-size&quot;&gt;Reduce DOM size &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#reduce-dom-size&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Per Lighthouse, large DOM sizes increase memory usage, causes longer &lt;a href=&quot;https://web.dev/economic-times-inp/reduce-the-scope-and-complexity-of-style-calculations/&quot;&gt;style recalculations&lt;/a&gt;, and produces costly &lt;a href=&quot;https://developers.google.com/speed/docs/insights/browser-reflow&quot; rel=&quot;noopener&quot;&gt;layout reflows&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the DOM size audit in Lighthouse. The number of DOM elements reported is 2,706 elements.&quot; decoding=&quot;async&quot; height=&quot;86&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 712px) 712px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/JLQfvWp1Fouc55Xbgy7X.png?auto=format&amp;w=1424 1424w&quot; width=&quot;712&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;We reduced the number of DOM nodes in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, we rendered our menu items at the user’s request (on click). It decreased the DOM size by around 1,200 nodes.&lt;/li&gt;
&lt;li&gt;Second, we lazy loaded less important widgets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because of all these efforts, we reduced TBT significantly, and our INP was reduced accordingly by almost 50%:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the INP audit in CrUX. The INP for the page is 539 milliseconds, which exceeds the &amp;#x27;poor&amp;#x27; threshold.&quot; decoding=&quot;async&quot; height=&quot;216&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 574px) 574px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ojm0miY1lwoFqxZWnYVM.png?auto=format&amp;w=1148 1148w&quot; width=&quot;574&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;At this point, we nearly ran out of easy wins to further reduce TBT (and INP by proxy), but we knew we had a lot of room for improvement. This is when we decided to upgrade our custom-built UI boilerplate to the latest version of React along with &lt;a href=&quot;https://nextjs.org/&quot; rel=&quot;noopener&quot;&gt;Next.js&lt;/a&gt; to make better use of &lt;a href=&quot;https://react.dev/reference/react&quot; rel=&quot;noopener&quot;&gt;hooks&lt;/a&gt; to avoid unnecessary re-rendering of components.&lt;/p&gt;
&lt;p&gt;Due to more frequent updates and comparatively lesser traffic as compared to the other portions of the website, we began to migrate our &lt;a href=&quot;https://economictimes.indiatimes.com/topic/home&quot; rel=&quot;noopener&quot;&gt;topic pages&lt;/a&gt; to Next.js. We also used &lt;a href=&quot;https://partytown.builder.io/&quot; rel=&quot;noopener&quot;&gt;PartyTown&lt;/a&gt; for offloading additional heavy main thread work to web workers, along with techniques like &lt;code&gt;requestIdleCallBack&lt;/code&gt; for deferring non-critical tasks.&lt;/p&gt;
&lt;h2 id=&quot;how-has-improving-inp-helped-the-economic-times&quot;&gt;How has improving INP helped The Economic Times? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#how-has-improving-inp-helped-the-economic-times&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;current-tbt-and-inp-on-origin&quot;&gt;Current TBT and INP on origin &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#current-tbt-and-inp-on-origin&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the time of publishing this post, the TBT for our origin was 120 milliseconds, down from 3,260 milliseconds when we began our optimization efforts. Similarly, the INP for our origin was 257 milliseconds after our optimization efforts, down from over 1,000 milliseconds.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of the INP audit in CrUX. The INP for the page is 257 milliseconds, which is within the &amp;#x27;needs improvement&amp;#x27; thresholds.&quot; decoding=&quot;async&quot; height=&quot;218&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 582px) 582px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/6cMvebBQKG2nhyc1eYeB.png?auto=format&amp;w=1164 1164w&quot; width=&quot;582&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;inp-crux-trend&quot;&gt;INP CrUX trend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#inp-crux-trend&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The traffic received on topic pages represents a significantly smaller portion of overall traffic. Hence, it was an ideal place for experimentation. The CrUX results along with the business outcomes were very encouraging, and led us to expand our efforts across the entire website to reap further benefits.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of INP distributions as visualized in CrUX over a period of four months, starting in July 2022 and ending in October 2022. Values within the &amp;#x27;poor&amp;#x27; and &amp;#x27;needs improvement&amp;#x27; thresholds declined somewhat, while the values within the &amp;#x27;good&amp;#x27; threshold increased.&quot; decoding=&quot;async&quot; height=&quot;190&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pkPEYIQIeEDKdIKOCFSY.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;akamai-mpulse-tbt-analysis&quot;&gt;Akamai mPulse TBT Analysis &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#akamai-mpulse-tbt-analysis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We use &lt;a href=&quot;https://www.akamai.com/products/mpulse-real-user-monitoring&quot; rel=&quot;noopener&quot;&gt;Akamai mPulse&lt;/a&gt; as our RUM solution, which measures TBT in the field. We observed a consistent decrease in TBT, clearly mapping to the outcomes of our efforts to reduce INP. As can be seen in the screenshot below, TBT values eventually dropped from approximately 5 seconds in to around 200 milliseconds in the field.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of a chart in Akamai mPulse, showing a decline in TBT over the course of roughly a month.&quot; decoding=&quot;async&quot; height=&quot;118&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/eS3iIvNxEUhe19GGdDBG.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;business-outcome&quot;&gt;Business outcome &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#business-outcome&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Overall, our efforts to bring down TBT by 30 times, along with migrating to Next.js helped us reduce INP nearly by 4 times, which eventually led to a &lt;strong&gt;50% decrease in bounce rate and 43% uplift in pageviews&lt;/strong&gt; on topic pages.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of Google Analytics comparing pageviews versus bounce rate. Because of the optimizations made to INP on The Economic Times website, a 50% decrease in bounce rate and a 43% increase in pageviews was realized.&quot; decoding=&quot;async&quot; height=&quot;288&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/WOzP0OjtPV6rsjqbtbfe.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/economic-times-inp/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To summarize, INP extensively helped to determine runtime performance issues on parts of the Economic Times website. It has proven to be one of the most effective metrics to positively impact business outcomes. Due to the very encouraging numbers we&#39;ve observed as the result of this effort, we are motivated to scale our optimization efforts to other areas of our website and reap additional benefits.&lt;/p&gt;
</content>
      <author>
          <name>Saurabh Rajpal</name>
        </author><author>
          <name>Daya Ram Yadav</name>
        </author><author>
          <name>Barun Kumar</name>
        </author>
    </entry>
    
</feed>
