<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Mustafa Kurtuldu on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Mustafa Kurtuldu</name>
  </author>
  <link href="https://web.dev/authors/mustafakurtuldu/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/0MyqDvMQmaxVodxo5kr9.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Our latest news, updates, and stories by Mustafa Kurtuldu.</subtitle>
  
  
  <entry>
    <title>Patterns for promoting PWA installation</title>
    <link href="https://web.dev/promote-install/"/>
    <updated>2019-06-04T00:00:00Z</updated>
    <id>https://web.dev/promote-install/</id>
    <content type="html" mode="escaped">&lt;p&gt;Installing your Progressive Web App (PWA) can make it easier for users to
find and use. Even with browser promotion, some users don&#39;t realize that
they can install a PWA, so it can be helpful to provide an in-app experience
that you can use to promote and enable installation of your PWA.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Screenshot of simple install button in PWA.&quot; decoding=&quot;async&quot; height=&quot;368&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PtJp54jasjOYyh9Soqzu.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A simple install button provided within your PWA.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This article is by no means exhaustive, but offers a starting point for different
ways to promote the installation of your PWA. Regardless of which pattern, &lt;em&gt;or
patterns&lt;/em&gt; you use,  they all lead to the same code that triggers the install
flow, documented in
&lt;a href=&quot;https://web.dev/customize-install/&quot;&gt;How to provide your own in-app install experience&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;best-practices&quot;&gt;Best practices &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#best-practices&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are some best practices that apply no matter which promotional patterns
you&#39;re using on your site.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep promotions outside of the flow of your user journeys. For example,
in a PWA login page, put the call to action below the login form and submit
button. Disruptive use of promotional patterns reduces the usability of your
PWA and negatively impacts your engagement metrics.&lt;/li&gt;
&lt;li&gt;Include the ability to dismiss or decline the promotion. Remember the
user&#39;s preference if they do this and only re-prompt if there&#39;s a change
in the user&#39;s relationship with your content such as if they signed in or
completed a purchase.&lt;/li&gt;
&lt;li&gt;Combine techniques in different parts of your PWA, but be careful not to
overwhelm or annoy your user with install promotion.&lt;/li&gt;
&lt;li&gt;Only show the promotion &lt;strong&gt;after&lt;/strong&gt; the
&lt;a href=&quot;https://web.dev/customize-install/#beforeinstallprompt&quot;&gt;&lt;code&gt;beforeinstallprompt&lt;/code&gt; event&lt;/a&gt; has
fired.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;browser-promotion&quot;&gt;Automatic browser promotion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#browser-promotion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When &lt;a href=&quot;https://web.dev/install-criteria/&quot;&gt;certain criteria&lt;/a&gt; are met, most browsers automatically
indicate to the user that your Progressive Web App is installable. For example,
desktop Chrome shows an install button in the omnibox.&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
  &lt;figure id=&quot;browser-install-promo&quot;&gt;
    &lt;img alt=&quot;Screenshot of omnibox with a visible install indicator.&quot; decoding=&quot;async&quot; height=&quot;307&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/zIfRss5zOrZ49c4VdJ52.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
    &lt;figcaption&gt;
      Browser-provided install promotion (desktop).
    &lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;Screenshot of browser-provided install promotion.&quot; decoding=&quot;async&quot; height=&quot;307&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kRjcsxlHDZa9Nqg2Fpei.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
    &lt;figcaption&gt;
      Browser-provided install promotion (mobile).
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Chrome for Android shows a mini infobar to the user, though this can be
prevented by calling &lt;code&gt;preventDefault()&lt;/code&gt; on the &lt;code&gt;beforeinstallprompt&lt;/code&gt; event.
If you do not call &lt;code&gt;preventDefault()&lt;/code&gt;, the banner will be shown the first time
a user visits your site and meets the installability criteria on Android,
and then again after approximately 90 days.&lt;/p&gt;
&lt;h2 id=&quot;app-ui-patterns&quot;&gt;User interface promotional patterns &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#app-ui-patterns&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;User interface promotional patterns can be used for almost any kind of PWA and
appear in places such as site navigation and banners. As with
any other type of promotional pattern, it&#39;s important to be aware of the
user&#39;s context to minimize disruption of the user&#39;s journey.&lt;/p&gt;
&lt;p&gt;Sites which are thoughtful about when they trigger promotion UI achieve a
larger number of installs and avoid interfering with the journeys of users
who aren&#39;t interested in installation.&lt;/p&gt;
&lt;h3 id=&quot;simple-button&quot;&gt;Simple install button &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#simple-button&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The simplest possible UX is to include an &#39;Install&#39; or &#39;Get app&#39; button at an
appropriate location in your web content. Ensure the button doesn&#39;t block
other important functionality and is out of the way of the user&#39;s journey
through your application.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install button..&quot; decoding=&quot;async&quot; height=&quot;448&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kv0x9hxZ0TLVaIiP4Bqx.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Simple install button.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;header&quot;&gt;Fixed header &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#header&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is an install button that is part of the header of your site. Other
header content often includes site branding such as a logo and the hamburger
menu. Headers may be &lt;code&gt;position:fixed&lt;/code&gt; or not depending on your site&#39;s
functionality and user needs.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install button in header.&quot; decoding=&quot;async&quot; height=&quot;448&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GPJdkXcpNLR30r2zo7RR.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Custom install button in header.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;When used appropriately, promoting PWA installation from the header of your
site is a great way to make it easier for your most loyal customers to
return to your experience. Pixels in your PWA header are precious,
so make sure your installation call to action is appropriately sized, of greater
importance than other possible header content, and unintrusive.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install button in header&quot; decoding=&quot;async&quot; height=&quot;430&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/L01AoSoy7LNk1ttMMax0.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Custom install button in header
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do not show the install button unless the &lt;code&gt;beforeinstallprompt&lt;/code&gt; has been
fired.&lt;/li&gt;
&lt;li&gt;Evaluate the value of your installed use case for your users. Consider
selective targeting to only present your promotion for users that are
likely to benefit from it.&lt;/li&gt;
&lt;li&gt;Use precious header space efficiently. Consider what else would be helpful
to offer your user in the header, and weigh the priority of the install
promotion relative to other options.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;nav&quot;&gt;Navigation menu &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#nav&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install button in nav menu&quot; decoding=&quot;async&quot; height=&quot;1117&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aT7NHi8lbsZW8TOm3Gaw.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Add an install button/promotion in a slide out navigation menu.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The navigation menu is a great place for promoting the installation of your
app since users who open the menu are signaling engagement with your experience.&lt;/p&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid disrupting important navigational content. Put the PWA install
promotion below other menu items.&lt;/li&gt;
&lt;li&gt;Offer a short, relevant pitch for why the user would benefit from
installing your PWA.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;landing&quot;&gt;Landing page &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#landing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The purpose of a landing page is to promote your products and services,
so this is one place where it is appropriate to go large when promoting
the benefits of installing your PWA.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install prompt on a landing page.&quot; decoding=&quot;async&quot; height=&quot;1117&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7q09M12HFxgIiWhKPGma.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Custom install prompt on a landing page.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;First, explain your site&#39;s value proposition, then let visitors know what
they&#39;ll get from installation.&lt;/p&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Appeal to features that matter most to your visitors and emphasize
keywords that might have brought them to your landing page.&lt;/li&gt;
&lt;li&gt;Make your install promotion and call to action eye catching, but only after
you&#39;ve made your value proposition clear. This is your landing page, after
all.&lt;/li&gt;
&lt;li&gt;Consider adding an install promotion in the part of your app where users spend
most of their time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;banner&quot;&gt;Install banner &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#banner&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most users have encountered installation banners in mobile experiences and are
familiar with the interactions offered by a banner. Banners should be used
carefully because they can disrupt the user.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install banner at top of page.&quot; decoding=&quot;async&quot; height=&quot;1000&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/7fLCQQhdk2OzrQD3Xh4E.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A dismissible banner at the top of the page.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wait until the user has demonstrated interest in your site before showing
a banner. If the user dismisses your banner, don&#39;t show it again unless
the user triggers a conversion event that indicates a higher level of
engagement with your content such as a purchase on an e‑commerce site or
signing up for an account.&lt;/li&gt;
&lt;li&gt;Provide a brief explanation of the value of installing your PWA in the
banner. For example, you can differentiate the install of a PWA from an
iOS/Android app by mentioning that it uses almost no storage on the user&#39;s
device or that it will install instantly without a store redirect.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;temporary-ui&quot;&gt;Temporary UI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#temporary-ui&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Temporary UI, such as the &lt;a href=&quot;https://material.io/components/snackbars/&quot; rel=&quot;noopener&quot;&gt;Snackbar&lt;/a&gt;
design pattern, notifies the user, and allows them to easily complete an
action, in this case, installing the app. When used properly, these kinds of UI
patterns don&#39;t interrupt the user flow, and are typically automatically
dismissed if ignored by the user.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install banner as snackbar.&quot; decoding=&quot;async&quot; height=&quot;448&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/6DySYRtyegazEfMcWXQL.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A dismissible snackbar indicating the PWA is installable.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Show the snackbar after a few interactions with your app. If it
appears on  page load, or out of context, it can be easily missed, or lead
to cognitive overload. When this happens, users will simply dismiss everything
they see. Remember, new users to your site may not be ready to install your
PWA. Therefore, it&#39;s best to wait until you have strong interest signals from
the user before using this pattern, for example, repeat visits, a user sign
in, or similar conversion event.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Custom install banner as snackbar.&quot; decoding=&quot;async&quot; height=&quot;424&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/d8dwdIe1rYSgd0JdCGtt.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A dismissible snackbar indicating the PWA is installable.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Show the snackbar for between 4 and 7 seconds to give users enough
time to see and react to it, and without getting in the way.&lt;/li&gt;
&lt;li&gt;Avoid showing it over other temporary UI such as banners, etc.&lt;/li&gt;
&lt;li&gt;Wait until you have strong interest signals from the user before
using this pattern, for example, repeat visits, a user sign in,
or similar conversion event.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;after-conversion&quot;&gt;After conversion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#after-conversion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Immediately after a user conversion event, for example after a purchase on
an e‑commerce site, is an excellent opportunity to promote the installation of
your PWA. The user is clearly engaged with your content, and a conversion
often signals that the user will engage with your services again.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;An install promotion after conversion.&quot; decoding=&quot;async&quot; height=&quot;448&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/DrepSPFAm64d5cvTFoXe.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    An install promotion after a user has completed a purchase.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;journey&quot;&gt;Booking or checkout journey &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#journey&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Show an install promotion during or after a sequential journey such as after
booking or checkout flows. If you&#39;re displaying the promotion after the user
has completed the journey, you can often make it more prominent since the
journey is completed.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;An install promotion after a user journey.&quot; decoding=&quot;async&quot; height=&quot;1419&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/bOYZM2UiWK5itVSpjKWO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    An install promotion after a user journey.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Include a relevant call to action. Which users will benefit from installing
your app and why? How is it relevant to the journey they are currently on?&lt;/li&gt;
&lt;li&gt;If your brand has unique offers for installed app users, mention them.&lt;/li&gt;
&lt;li&gt;Keep the promotion out of the way of next steps in your journey or you can
negatively affect journey completion rates. In the e‑commerce example
above, notice how the key call to action to checkout is above the
app install promotion.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;sign-up&quot;&gt;Sign up, sign in, or sign out flow &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#sign-up&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This promotion is a special case of the &lt;a href=&quot;https://web.dev/promote-install/#journey&quot;&gt;journey&lt;/a&gt; promotional
pattern where the promotion card can be more prominent.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A custom install button on the sign up page.&quot; decoding=&quot;async&quot; height=&quot;1117&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/PQXqSqtwRSwyELdJMjtd.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    A custom install button on the sign up page.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;These pages are usually only viewed by engaged users, where the value
proposition of your PWA has already been established. There&#39;s also often not
a lot of other useful content to place on these pages. As a result, it&#39;s less
disruptive to make a larger call-to-action as long as it&#39;s not in the way.&lt;/p&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid disrupting the user&#39;s journey inside the sign up form. If it&#39;s a
multi-step process, you might want to wait until the user has completed the
journey.&lt;/li&gt;
&lt;li&gt;Promote features most relevant to a signed-up user.&lt;/li&gt;
&lt;li&gt;Consider adding an additional install promotion within the signed-in areas
of your app.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;inline-promotional-patterns&quot;&gt;Inline promotional patterns &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#inline-promotional-patterns&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Inline promotional techniques interweave promotions with site content. This
is often more subtle than promotion in the user interface, which has tradeoffs.
You want your promotion to stand out enough that interested users will notice
it, but not so much that it detracts from the quality of your user experience.&lt;/p&gt;
&lt;h3 id=&quot;in-feed&quot;&gt;In-feed &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/promote-install/#in-feed&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An in-feed install promotion appears between news articles or other lists of
information cards in your PWA.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;An install promotion within a content feed.&quot; decoding=&quot;async&quot; height=&quot;1000&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/LS5qSE2vicfjRBBkA47a.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    An install promotion within a content feed.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Your goal is to show users how to access the content they&#39;re enjoying more
conveniently. Focus on promoting features and functionality that will be
helpful to your users.&lt;/p&gt;
&lt;p&gt;Make sure you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Limit the frequency of the promotions to avoid annoying users.&lt;/li&gt;
&lt;li&gt;Give your users the ability to dismiss the promotions.&lt;/li&gt;
&lt;li&gt;Remember your user&#39;s choice to dismiss.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Penny McLachlan</name>
    </author><author>
      <name>Mustafa Kurtuldu</name>
    </author>
  </entry>
  
  <entry>
    <title>Introduction to variable fonts on the web</title>
    <link href="https://web.dev/variable-fonts/"/>
    <updated>2018-02-19T00:00:00Z</updated>
    <id>https://web.dev/variable-fonts/</id>
    <content type="html" mode="escaped">&lt;p&gt;In this article, we will look at what variable fonts are, the benefits they
offer, and how we can use them in our work. First, let&#39;s review how typography
works on the web, and what innovations variable fonts bring.&lt;/p&gt;
&lt;h2 id=&quot;browser-compatibility&quot;&gt;Browser compatibility &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#browser-compatibility&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As of May 2020 variable fonts are supported in most browsers. See
&lt;a href=&quot;https://caniuse.com/#feat=variable-fonts&quot; rel=&quot;noopener&quot;&gt;Can I use variable fonts?&lt;/a&gt;
and &lt;a href=&quot;https://web.dev/variable-fonts/#fallbacks&quot;&gt;Fallbacks&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The terms font and typeface are often used interchangeably by developers.
However there is a difference: A typeface is the underlying visual design that
can exist in many different typesetting technologies, and a font is one of these
implementations, in a digital file format. In other words, a typeface is what
you &lt;em&gt;see&lt;/em&gt;, and the font is what you &lt;em&gt;use&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Another concept that is often overlooked is the distinction between a style, and
a family. A style is a single and specific typeface, such as Bold Italic, and a
family is the complete set of styles.&lt;/p&gt;
&lt;p&gt;Before variable fonts, each style was implemented as a separate font file. With
variable fonts, all styles can be contained in a single file.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A specimen composition and list of different styles of the Roboto family&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/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/RbhgXwS81Y9PVRJnTjPX.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Left: a specimen of the Roboto typeface family. Right: named styles within the family.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;challenges-for-the-designer-and-developer&quot;&gt;Challenges for the designer and developer &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#challenges-for-the-designer-and-developer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a designer creates a print project they face some constraints, such as the
physical size of the page layout, the number of colors they can use (which is
determined by the kind of printing press that will be used), and so on. But they
can use as many typeface styles as they like. This means that the typography of
print media is often rich and sophisticated, so that the reading experience is
truly delightful. Think of the last time you enjoyed browsing an excellent
magazine.&lt;/p&gt;
&lt;p&gt;Web designers and developers have different constraints than print designers,
and an important one is the associated bandwidth costs of our designs. This
has been a sticking point for richer typographic experiences, as they come at
a cost. With traditional web fonts, each style used in our designs requires
users to download a separate font file, which increases latency and page
rendering time. Only including the Regular and Bold styles, plus their italic
counterparts, can amount to 500 KB or more of font data. This is even before
we have dealt with how the fonts are rendered, the fallback patterns we need
to use, or undesirable side-effects such as &lt;a href=&quot;https://www.zachleat.com/web/fout-vs-foit/&quot; rel=&quot;noopener&quot;&gt;FOIT and
FOUT&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many font families offer a much wider range of styles, from Thin to Black
weights, narrow and wide widths, a variety of stylistic details, and even
size-specific designs (optimized for large or small text sizes.) Since you&#39;d
have to load a new font file for every style (or combinations of styles), many
web developers choose not to use these capabilities, reducing the reading
experience of their users.&lt;/p&gt;
&lt;h2 id=&quot;anatomy-of-a-variable-font&quot;&gt;Anatomy of a variable font &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#anatomy-of-a-variable-font&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Variable fonts address these challenges, by packing styles into a single file.&lt;/p&gt;
&lt;p&gt;This works by starting with a central or &#39;default&#39; style, usually the
&#39;Regular&#39;–an upright roman design with the most typical weight and width that
is most suitable for plain text. This is then connected to other styles in a
continuous range, called an &#39;axis.&#39; The most common axis is &lt;strong&gt;Weight&lt;/strong&gt;, which
can connect the default style through to a Bold style. Any individual style
can be located along an axis, and is called an &#39;instance&#39; of the variable
font. Some instances are named by the font developer, for example Weight axis
location 600 is called SemiBold.&lt;/p&gt;
&lt;p&gt;The variable font &lt;a href=&quot;https://github.com/TypeNetwork/Roboto-Flex&quot; rel=&quot;noopener&quot;&gt;Roboto Flex&lt;/a&gt;
has three styles for its &lt;strong&gt;Weight&lt;/strong&gt; axis. The Regular style is at the center,
and there are two styles at the opposite ends of the axis, one lighter and
the other heavier. Between these, you can choose from 900 instances:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The letter &amp;#x27;A&amp;#x27; shown in different weights&quot; decoding=&quot;async&quot; height=&quot;218&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Ecr5godvTKunVXP7W8aU.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Above: Illustrated anatomy of the Weight axis for the typeface Roboto.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The font developer can offer a set of different axes. You can combine them
because they all share the same default styles. Roboto has three styles in a
Width axis: the Regular is at the center of the axis, and two styles, narrower
and wider, are at each end. These provide all the widths of the Regular style,
and combine with the Weight axis to provide all the widths for every weight.&lt;/p&gt;
&lt;figure data-size=&quot;full&quot;&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/roboto-dance.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Roboto Flex in random combinations of Width and Weight
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This means there are thousands of styles! This may seem like massive overkill,
but the quality of the reading experience can be remarkably enhanced by this
diversity of type styles. And, if it is without performance penalty, web
developers can use a few or as many styles as they wish–it&#39;s up to their design.&lt;/p&gt;
&lt;h3 id=&quot;italics&quot;&gt;Italics &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#italics&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The way that Italics are handled in variable fonts is interesting, as there are
two difference approaches. Typefaces like Helvetica or Roboto have interpolation
compatible contours, so their Roman and Italic styles can be interpolated
between and the &lt;strong&gt;Slant&lt;/strong&gt; axis can be used to get from Roman to Italic.&lt;/p&gt;
&lt;p&gt;Other typefaces (such as Garamond, Baskerville, or Bodoni) have Roman and Italic
glyph contours that are not interpolation compatible. For example, the contours
that typically define a Roman lowercase &amp;quot;n&amp;quot; do not match the contours used to
define an Italic lowercase &amp;quot;n&amp;quot;. Instead of interpolating one contour to the
other, the &lt;strong&gt;Italic&lt;/strong&gt; axis toggles from Roman to Italic contours.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Example of the Weight Axes for the typeface Amstelvar&quot; decoding=&quot;async&quot; height=&quot;520&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/EySl1LIfX1QIrGq654PO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Amstelvar&#39;s &quot;n&quot; contours in Italic (12 point, regular weight, normal width),
    and in Roman. Image supplied by David Berlow, type designer and typographer
    at Font Bureau.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After the switch to Italic, the axes available to the user should be the same as
those for the Roman, just as the character set should be the same.&lt;/p&gt;
&lt;p&gt;A glyph substitution capability can also be seen for individual glyphs, and used
anywhere in the design space of a variable font. For example, a dollar sign
design with two vertical bars works best at larger point sizes, but at smaller
point sizes a design with only one bar is better. When we have fewer pixels for
rendering the glyph, a two bar design can become illegible. To combat this, much
like the Italic axis, a glyph substitution of one glyph for another can occur
along the &lt;strong&gt;Optical Size&lt;/strong&gt; axis at a point decided by the type designer.&lt;/p&gt;
&lt;p&gt;In summary, where the contours allow for it, type designers can create fonts
that interpolate between various styles in a multi-dimensional design space.
This gives you granular control over your typography, and a great deal of power.&lt;/p&gt;
&lt;h2 id=&quot;axes-definitions&quot;&gt;Axes definitions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#axes-definitions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are five &lt;a href=&quot;https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg#registered-axis-tags&quot; rel=&quot;noopener&quot;&gt;registered
axes&lt;/a&gt;,
which control known, predictable features of the font: weight, width, optical
size, slant and italics. Besides those, a font can contain custom axes. These
can control any design aspect of the font the type designer wishes: the size of
serifs, the length of swashes, the height of ascenders or the size of the dot on
the i.&lt;/p&gt;
&lt;p&gt;Even though axes can control the same feature, they might use different values.
For example, in the Oswald and Hepta Slab variable fonts there is only one axis
available, Weight, but the ranges are different–Oswald has the same range as
before it was upgraded to be variable, 200 to 700, but Hepta Slab has an extreme
hairline weight at 1 that goes all the up to 900.&lt;/p&gt;
&lt;p&gt;The five registered axes have 4-character lowercase tags that are used to
set their values in CSS:&lt;/p&gt;
&lt;table&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;th colspan=&quot;2&quot;&gt;Axis names and CSS values&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;
				Weight
			&lt;/td&gt;
			&lt;td&gt;
				&lt;code&gt;wght&lt;/code&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;
				Width
			&lt;/td&gt;
			&lt;td&gt;
				&lt;code&gt;wdth&lt;/code&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;
				Slant
			&lt;/td&gt;
			&lt;td&gt;
				&lt;code&gt;slnt&lt;/code&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;
				Optical Size
			&lt;/td&gt;
			&lt;td&gt;
				&lt;code&gt;opsz&lt;/code&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;
				Italics
			&lt;/td&gt;
			&lt;td&gt;
				&lt;code&gt;ital&lt;/code&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Since the font developer defines which axes are available in a variable font,
and which values they can have, it is essential to find out what each font
offers. The font&#39;s documentation should provide this, or you can inspect the
font using a tool like &lt;a href=&quot;https://wakamaifondue.com/&quot; rel=&quot;noopener&quot;&gt;Wakamai Fondue&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;use-cases-and-benefits&quot;&gt;Use cases and benefits &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#use-cases-and-benefits&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Setting the axes values comes down to personal taste and applying typographic
best practices. The danger with any new technology is possible misuse, and
settings that are overly artistic or exploratory could also decrease legibility
of the actual text. For titles, exploring different axes to create great
artistic designs are exciting, but for body copy this risks making the text
illegible.&lt;/p&gt;
&lt;h3 id=&quot;exciting-expression&quot;&gt;Exciting expression &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#exciting-expression&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Grass example by Mandy Michael&quot; decoding=&quot;async&quot; height=&quot;174&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 495px) 495px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Rh7wLaBLauEF02D2dqMC.png?auto=format&amp;w=990 990w&quot; width=&quot;495&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;One great example of artistic expression is shown above, an exploration of the
typeface
&lt;a href=&quot;https://www.typenetwork.com/brochure/decovar-a-decorative-variable-font-by-david-berlow&quot; rel=&quot;noopener&quot;&gt;Decovar&lt;/a&gt;
by Mandy Michael.&lt;/p&gt;
&lt;p&gt;You can view the working example and source code for the above sample
&lt;a href=&quot;https://codepen.io/mandymichael/pen/YYaWop&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;animation&quot;&gt;Animation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#animation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/vgdbNJBYHma2o62ZqYmcnkq3j0o1/2Du2L0Ii5nUqz8n6S3Vz.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Typeface Zycon, designed for animation by David Berlow, type designer and
    typographer at Font Bureau.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There is also a possibility to explore animating characters with variable fonts.
Above is an example of different axes being used with the typeface Zycon. See
the live &lt;a href=&quot;https://www.axis-praxis.org/specimens/zycon&quot; rel=&quot;noopener&quot;&gt;animation example on Axis
Praxis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://typogram.github.io/Anicons&quot; rel=&quot;noopener&quot;&gt;Anicons&lt;/a&gt; is the world&#39;s first animated
color icon font, based on Material Design Icons. Anicons is an experiment that
combines two cutting edge font technologies: variable fonts and color fonts.&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/anicons-animation.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    A few examples of hover animations from Anicon&#39;s color icon font
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;finesse&quot;&gt;Finesse &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#finesse&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/larger-widths.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Amstelvar using little bits of XTRA in opposite directions so the words&#39; widths are evened out
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TypeNetwork/Roboto-Flex&quot; rel=&quot;noopener&quot;&gt;Roboto Flex&lt;/a&gt; and
&lt;a href=&quot;https://github.com/TypeNetwork/Amstelvar&quot; rel=&quot;noopener&quot;&gt;Amstelvar&lt;/a&gt; offer a set of
&amp;quot;Parametric Axes.&amp;quot; In these axes, the letters are deconstructed into 4
fundamental aspects of form: black or positive shapes, white or negative
shapes, and the x and y dimensions. In the same way that primary colors can be
blended with any other color to adjust it, these 4 aspects can be used to fine
tune any other axis.&lt;/p&gt;
&lt;p&gt;The XTRA axis in Amstelvar allows you to adjust the &amp;quot;white&amp;quot; per mille value,
as shown above. Using little bits of XTRA in opposite directions, the words&#39;
widths are evened out.&lt;/p&gt;
&lt;h2 id=&quot;variable-fonts-in-css&quot;&gt;Variable fonts in CSS &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#variable-fonts-in-css&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;loading-variable-font-files&quot;&gt;Loading variable font files &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#loading-variable-font-files&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Variable fonts are loaded though the same &lt;code&gt;@font-face&lt;/code&gt; mechanism as traditional
static web fonts, but with two new enhancements:&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;&#39;Roboto Flex&#39;&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;RobotoFlex-VF.woff2&#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;woff2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tech&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;variations&#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 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;RobotoFlex-VF.woff2&#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;woff2-variations&#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 property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100 1000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;font-stretch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 25% 151%&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;1. Source Formats:&lt;/strong&gt; We don&#39;t want the browser to download the font if it
doesn&#39;t support variable fonts, so we add &lt;code&gt;format&lt;/code&gt; and &lt;code&gt;tech&lt;/code&gt; descriptions: once in the
&lt;a href=&quot;https://www.w3.org/TR/css-fonts-4/#font-face-src-parsing&quot; rel=&quot;noopener&quot;&gt;future
syntax&lt;/a&gt;
(&lt;code&gt;format(&#39;woff2&#39;) tech(&#39;variations&#39;)&lt;/code&gt;), once in the deprecated but supported among browsers
syntax (&lt;code&gt;format(&#39;woff2-variations&#39;)&lt;/code&gt;). If the browser supports variable fonts and supports
the upcoming syntax, it will use the first declaration. If it supports variable
fonts and the current syntax, it will use the second declaration. They both
point to the same font file.&lt;/p&gt;
&lt;!-- TODO 2021 Q1 revisit this, based on progress in
     https://www.w3.org/TR/css-fonts-4/#font-face-src-requirement-types
     to allow removing the 2nd src --&gt;
&lt;p&gt;&lt;strong&gt;2. Style Ranges:&lt;/strong&gt; You&#39;ll notice we&#39;re supplying two values for &lt;code&gt;font-weight&lt;/code&gt;
and &lt;code&gt;font-stretch&lt;/code&gt;. Instead of telling the browser which specific weight this
font provides (for example &lt;code&gt;font-weight: 500;&lt;/code&gt;), we now give it the &lt;strong&gt;range&lt;/strong&gt; of
weights supported by the font. For Roboto Flex, the Weight axis ranges from 100
to 1000, and CSS directly maps the axis range to the &lt;code&gt;font-weight&lt;/code&gt; style
property. By specifying the range in &lt;code&gt;@font-face&lt;/code&gt;, any value outside this range
will be &amp;quot;capped&amp;quot; to the nearest valid value. The Width axis range is mapped in
the same way to the &lt;code&gt;font-stretch&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;If you&#39;re using the Google Fonts API, this will all be taken care of. Not only
will the CSS contain the proper source formats and ranges, Google Fonts will
also send static fallback fonts in case variable fonts aren&#39;t supported.&lt;/p&gt;
&lt;h3 id=&quot;using-weights-and-widths&quot;&gt;Using weights and widths &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#using-weights-and-widths&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Currently, the axes you can reliably set from CSS are the &lt;code&gt;wght&lt;/code&gt; axis through
&lt;code&gt;font-weight&lt;/code&gt;, and the &lt;code&gt;wdth&lt;/code&gt; axis through &lt;code&gt;font-stretch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Traditionally, you would set &lt;code&gt;font-weight&lt;/code&gt; as a keyword (&lt;code&gt;light&lt;/code&gt;, &lt;code&gt;bold&lt;/code&gt;) or as
a numerical value between 100 and 900, in steps of 100. With variable fonts, you
can set any value within the font&#39;s Width range:&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;.kinda-light&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-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 125&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;.super-heavy&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-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1000&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;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/roboto-flex-weight.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Roboto Flex&#39; Weight axis being changed from its minimum to its maximum.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Likewise, we can set &lt;code&gt;font-stretch&lt;/code&gt; with keywords (&lt;code&gt;condensed&lt;/code&gt;,
&lt;code&gt;ultra-expanded&lt;/code&gt;) or with percentage values:&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;.kinda-narrow&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-stretch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 33.3%&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;.super-wide&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-stretch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 151%&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;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/roboto-flex-width.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Roboto Flex&#39; Width axis being changed from its minimum to its maximum.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;using-italics-and-obliques&quot;&gt;Using italics and obliques &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#using-italics-and-obliques&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ital&lt;/code&gt; axis is intended for fonts that contain both a regular style, and an
italic style. The axis is meant to be an on/off switch: value &lt;code&gt;0&lt;/code&gt; is off and
will show the regular style, value &lt;code&gt;1&lt;/code&gt; will show the italics. Unlike other axes,
there&#39;s no transition. A value of &lt;code&gt;0.5&lt;/code&gt; won&#39;t give you &amp;quot;half italics&amp;quot;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;slnt&lt;/code&gt; axis is different from italics in that it&#39;s not a new &lt;em&gt;style&lt;/em&gt;, but
just slants the regular style. By default its value is &lt;code&gt;0&lt;/code&gt;, which means the
default upright letter shapes. Roboto Flex has a maximum slant of -10 degrees,
meaning the letters will lean to the right when going from 0 to -10.&lt;/p&gt;
&lt;p&gt;It would be intuitive to set these axis through the &lt;code&gt;font-style&lt;/code&gt; property, but
as of April 2020, how to exactly do this is &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/3125&quot; rel=&quot;noopener&quot;&gt;still being worked
out&lt;/a&gt;. So for now, you should
treat these as custom axes, and set them through &lt;code&gt;font-variation-settings&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;i, em, .italic&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;/* Should be font-style: italic; */&lt;/span&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;span class=&quot;token string&quot;&gt;&#39;ital&#39;&lt;/span&gt; 1&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;.slanted&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;/* Should be font-style: oblique 10deg; */&lt;/span&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;span class=&quot;token string&quot;&gt;&#39;slnt&#39;&lt;/span&gt; 10&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;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/roboto-flex-slant.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Roboto Flex&#39; Slant axis being changed from its minimum to its maximum.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;using-optical-sizes&quot;&gt;Using optical sizes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#using-optical-sizes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A typeface can be rendered very small (a 12px footnote) or very large (a 80px
headline). Fonts can respond to these size changes by changing its letter shapes
to better suit its size. A small size might be better off without fine details,
while a large size might benefit from more details and thinner strokes.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The letter &amp;#x27;a&amp;#x27; shown at different optical sizes&quot; decoding=&quot;async&quot; height=&quot;147&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wrVCGSQNaGWhNp97BoRS.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    The letter &#39;a&#39; in Roboto Flex at different pixel sizes, then scaled to be the same size,
    shows the differences in design.
    &lt;a href=&quot;https://codepen.io/RoelN/pen/PoPvdeV&quot;&gt;Try it yourself on Codepen&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A new CSS property has been introduced for this axis: &lt;code&gt;font-optical-sizing&lt;/code&gt;. By
default it&#39;s set to &lt;code&gt;auto&lt;/code&gt;, which makes the browser set the axis value based on
the &lt;code&gt;font-size&lt;/code&gt;. This means the browser will pick the best optical size
automatically, but if you wish to turn this off you can set
&lt;code&gt;font-optical-sizing&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also set a custom value for the &lt;code&gt;opsz&lt;/code&gt; axis, if you deliberately want an
optical size that doesn&#39;t match the font size. The following CSS would cause
text to be displayed at a large size, but at an optical size as if it were
printed in &lt;code&gt;8pt&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;.small-yet-large&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-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&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;span class=&quot;token string&quot;&gt;&#39;opsz&#39;&lt;/span&gt; 8&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;using-custom-axes&quot;&gt;Using custom axes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#using-custom-axes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unlike registered axes, custom axes will not be mapped to an existing CSS
property, so you will always have to set them through &lt;code&gt;font-variation-settings&lt;/code&gt;.
Tags for custom axes are always in uppercase, to distinguish them from
registered axes.&lt;/p&gt;
&lt;p&gt;Roboto Flex offers a few custom axes, and the most important is Grade (&lt;code&gt;GRAD&lt;/code&gt;).
A Grade axis is interesting as it changes the weight of the font without
changing the widths, so line breaks do not change. By playing with a Grade axis,
you can avoid being forced to fiddle with changes to Weight axis that affects
the overall width, and then changes to the Width axis that affect the overall
weight.&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/variable-fonts/roboto-flex-grade.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    Roboto Flex&#39; Grade axis being changed from its minimum to its maximum.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As &lt;code&gt;GRAD&lt;/code&gt; is a custom axis, with a range of -200 to 150 in Roboto Flex.
We need to address it with &lt;code&gt;font-variation-settings&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;.grade-light&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-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; `GRAD` -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;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.grade-normal&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-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; `GRAD` 0&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;.grade-heavy&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-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; `GRAD` 150&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;variable-fonts-on-google-fonts&quot;&gt;Variable fonts on Google Fonts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#variable-fonts-on-google-fonts&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Google Fonts has expanded their catalog with &lt;a href=&quot;https://fonts.google.com/?vfonly=true&quot; rel=&quot;noopener&quot;&gt;variable
fonts&lt;/a&gt;, and adding new ones regularly.
The interface is currently aimed at picking single instances from the font:
you select the variation you want, click &amp;quot;Select this style&amp;quot;, and it will be
added to the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; element that fetches the CSS and fonts from Google Fonts.&lt;/p&gt;
&lt;p&gt;To use all the available axes, or ranges of values, you will have to &lt;a href=&quot;https://developers.google.com/fonts/docs/css2&quot; rel=&quot;noopener&quot;&gt;manually
compose&lt;/a&gt; the URL to the Google
Fonts API. The &lt;a href=&quot;https://fonts.google.com/variablefonts&quot; rel=&quot;noopener&quot;&gt;variable fonts overview&lt;/a&gt; lists all axes and values.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/RoelN/google-variable-fonts-links&quot; rel=&quot;noopener&quot;&gt;Google Variable Fonts Links&lt;/a&gt;
tool can also give you the latest URLs for the full variable fonts.&lt;/p&gt;
&lt;h2 id=&quot;font-variation-settings-inheritance&quot;&gt;Font-variation-settings inheritance &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#font-variation-settings-inheritance&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While all registered axes will soon be supported through existing CSS
properties, for the time being you might need to rely on
&lt;code&gt;font-variation-settings&lt;/code&gt; as a fallback. And if your font has custom axes,
you&#39;ll need &lt;code&gt;font-variation-settings&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;However, here&#39;s a little gotcha with &lt;code&gt;font-variation-settings&lt;/code&gt;. Every property
you &lt;em&gt;don&#39;t explicitly set&lt;/em&gt; will automatically be reset to its default.
Previously set values aren&#39;t inherited! This means the following will not work
as expected:&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;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&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;slanted grade-light&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;br /&gt;	I should be slanted and have a light grade&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;span&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;First the browser will apply &lt;code&gt;font-variation-settings: &#39;slnt&#39; 10&lt;/code&gt; from the
&lt;code&gt;.slanted&lt;/code&gt; class. Then it will apply &lt;code&gt;font-variation-settings: &#39;GRAD&#39; -200&lt;/code&gt; from
the &lt;code&gt;.grade-light&lt;/code&gt; class. But this will reset the &lt;code&gt;slnt&lt;/code&gt; back to its default of
0! The result will be text in a light grade, but not slanted.&lt;/p&gt;
&lt;p&gt;Luckily, we can work around this by using CSS variables:&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 comment&quot;&gt;/* Set the default values */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;:root&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;--slnt&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;span class=&quot;token property&quot;&gt;--GRAD&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;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* Change value for these elements and their children */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.slanted&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;--slnt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10&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;.grade-light&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;--GRAD&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;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.grade-normal&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;--GRAD&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;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.grade-heavy&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;--GRAD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 150&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;/* Apply whatever value is kept in the CSS variables */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.slanted,&lt;br /&gt;.grade-light,&lt;br /&gt;.grade-normal,&lt;br /&gt;.grade-heavy&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-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;slnt&#39;&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;--slnt&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 string&quot;&gt;&#39;GRAD&#39;&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;--GRAD&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;CSS variables will cascade, so if an element (or one of its parents) will have
set the &lt;code&gt;slnt&lt;/code&gt; to &lt;code&gt;10&lt;/code&gt;, it will keep that value, even if you set &lt;code&gt;GRAD&lt;/code&gt; to
something else. See
&lt;a href=&quot;https://pixelambacht.nl/2019/fixing-variable-font-inheritance/&quot; rel=&quot;noopener&quot;&gt;Fixing variable font inheritance&lt;/a&gt;
for an in-depth explanation of this technique.&lt;/p&gt;
&lt;p&gt;Note that animating CSS variables doesn&#39;t work (by design), so something like
this doesn&#39;t work:&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;@keyframes&lt;/span&gt; width-animation&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;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--wdth&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;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token selector&quot;&gt;to&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--wdth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 151&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;These animations will have to happen directly on &lt;code&gt;font-variation-settings&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;performance-gains&quot;&gt;Performance gains &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#performance-gains&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OpenType variable fonts allow us to store multiple variations of a type family
into a single font file.
&lt;a href=&quot;https://medium.com/@monotype/part-2-from-truetype-gx-to-variable-fonts-4c28b16997c3&quot; rel=&quot;noopener&quot;&gt;Monotype&lt;/a&gt;
ran an experiment by combining 12 input fonts to generate eight weights,
across three widths, across both the Italic and Roman styles. Storing 48
individual fonts in a single variable font file meant a &lt;em&gt;88% reduction in file
size&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However, if you are using a single font such as Roboto Regular and nothing
else, you might not see a net gain in font size if you were to switch to a
variable font with many axes. As always, it depends on your use-case.&lt;/p&gt;
&lt;p&gt;On the flip side, animating the font between settings may cause performance
issues. Although this will improve once variable font support in browsers gets
more mature, the problem can be reduced somewhat by only animating fonts that are
currently on screen. This handy snippet by
&lt;a href=&quot;https://abcdinamo.com/news/using-variable-fonts-on-the-web&quot; rel=&quot;noopener&quot;&gt;Dinamo&lt;/a&gt; pauses
animations in elements with the class &lt;code&gt;vf-animation&lt;/code&gt;, when they&#39;re not on
screen:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&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 class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; observer&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 comment&quot;&gt;// Pause/Play the animation&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; entry&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;animationPlayState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;running&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;else&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;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;animationPlayState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;paused&quot;&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; variableTexts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.vf-animation&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;variableTexts&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;el&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; observer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&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;p&gt;If your font responds to user interaction, it&#39;s a good idea to &lt;a href=&quot;https://css-tricks.com/debouncing-throttling-explained-examples/&quot; rel=&quot;noopener&quot;&gt;throttle or
debounce&lt;/a&gt;
input events. This will prevent the browser from rendering instances of the
variable font that changed so little from the previous instance the human eye
wouldn&#39;t see the difference.&lt;/p&gt;
&lt;p&gt;If you&#39;re using Google Fonts, it&#39;s a good idea to
&lt;a href=&quot;https://web.dev/preconnect-and-dns-prefetch/&quot;&gt;preconnect&lt;/a&gt; to &lt;code&gt;https://fonts.gstatic.com&lt;/code&gt;,
the domain where Google&#39;s fonts are hosted. This will make sure the browser
knows early on where to get the fonts when it comes across them in the CSS:&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;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&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;preconnect&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&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://fonts.gstatic.com&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This tip works for other CDNs as well: the sooner you let the browser set up a
network connection, the sooner it can download your fonts.&lt;/p&gt;
&lt;p&gt;Find more performance tips for loading Google Fonts in &lt;a href=&quot;https://csswizardry.com/2020/05/the-fastest-google-fonts/&quot; rel=&quot;noopener&quot;&gt;The Fastest
Google Fonts&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fallbacks&quot;&gt;Fallbacks and browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#fallbacks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All modern browsers &lt;a href=&quot;https://caniuse.com/#feat=variable-fonts&quot; rel=&quot;noopener&quot;&gt;support variable
fonts&lt;/a&gt;. In case you need to support
older browsers, you can choose to build your site with static fonts, and use
variable fonts as progressive enhancement:&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 comment&quot;&gt;/* Set up Roboto for old browsers, only regular + bold */&lt;/span&gt;&lt;br /&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 keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&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; normal&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 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; Roboto&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;Roboto-Regular.woff2&#39;&lt;/span&gt;&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 property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; normal&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;@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; Roboto&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;Roboto-Bold.woff2&#39;&lt;/span&gt;&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 property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&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;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&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;.super-bold&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-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&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 comment&quot;&gt;/* Set up Roboto for modern browsers, all weights */&lt;/span&gt;&lt;br /&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;font-variation-settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; normal&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 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;&#39;Roboto&#39;&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;RobotoFlex-VF.woff2&#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;woff2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tech&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;variations&#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 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;RobotoFlex-VF.woff2&#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;woff2-variations&#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 property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100 1000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-stretch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 25% 151%&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;.super-bold&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-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1000&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;For older browsers, text with the class &lt;code&gt;.super-bold&lt;/code&gt; will get rendered in the
normal bold, as that&#39;s the only bold font we have available. When variable fonts
are supported, we can actually use the heaviest weight of 1000.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;@supports&lt;/code&gt; rule is not supported by Internet Explorer, so this browser would
not show any styling. If this is a problem, you could always use one of the
&lt;a href=&quot;https://stackoverflow.com/a/20541859/6255000&quot; rel=&quot;noopener&quot;&gt;oldschool hacks&lt;/a&gt; to target relevant
older browsers.&lt;/p&gt;
&lt;p&gt;If you are using the Google Fonts API, it will take care of loading the proper
fonts for your visitor&#39;s browsers. Say you request the font Oswald in weight
range 200 to 700, like so:&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;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&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://fonts.googleapis.com/css2?family=Oswald:wght@200..700&amp;amp;display=swap&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&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;stylesheet&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Modern browsers that can handle variable fonts will get the variable font, and
will have every weight between 200 and 700 available. Older browsers will get
served individual static fonts for every weight. In this case, this means
they&#39;ll download 6 font files: one for weight 200, one for weight 300, and so
on.&lt;/p&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/variable-fonts/#thanks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article would have only been made possible with the help of the following
people:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/mustafa_x&quot; rel=&quot;noopener&quot;&gt;Mustafa Kurtuldu&lt;/a&gt;, UX designer and design advocate at Google&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/PixelAmbacht&quot; rel=&quot;noopener&quot;&gt;Roel Nieskens&lt;/a&gt;, UX designer/developer and typography expert at &lt;a href=&quot;https://kabisa.nl/&quot; rel=&quot;noopener&quot;&gt;Kabisa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/davelab6&quot; rel=&quot;noopener&quot;&gt;Dave Crossland&lt;/a&gt;, Program Manager, Google Fonts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/dberlow&quot; rel=&quot;noopener&quot;&gt;David Berlow&lt;/a&gt;, type designer and typographer at
&lt;a href=&quot;https://fontbureau.typenetwork.com/&quot; rel=&quot;noopener&quot;&gt;Font Bureau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/lorp&quot; rel=&quot;noopener&quot;&gt;Laurence Penney&lt;/a&gt;, developer of &lt;a href=&quot;https://axis-praxis.org/&quot; rel=&quot;noopener&quot;&gt;axis-praxis.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/Mandy_Kerr&quot; rel=&quot;noopener&quot;&gt;Mandy Michael&lt;/a&gt;, developer of &lt;a href=&quot;https://variablefonts.dev/&quot; rel=&quot;noopener&quot;&gt;variablefonts.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hero image by &lt;a href=&quot;https://unsplash.com/@brunus&quot; rel=&quot;noopener&quot;&gt;Bruno Martins&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/OhJmwB4XWLE&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Mustafa Kurtuldu</name>
    </author><author>
      <name>Thomas Steiner</name>
    </author><author>
      <name>Dave Crossland</name>
    </author><author>
      <name>Roel Nieskens</name>
    </author>
  </entry>
  
  <entry>
    <title>Offline UX design guidelines</title>
    <link href="https://web.dev/offline-ux-design-guidelines/"/>
    <updated>2016-11-10T00:00:00Z</updated>
    <id>https://web.dev/offline-ux-design-guidelines/</id>
    <content type="html" mode="escaped">&lt;p&gt;This article provides design guidelines on how to create a great experience
on both slow networks and offline.&lt;/p&gt;
&lt;p&gt;The quality of a network connection can be affected by a number of factors such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Poor coverage of a provider.&lt;/li&gt;
&lt;li&gt;Extreme weather conditions.&lt;/li&gt;
&lt;li&gt;Power outages.&lt;/li&gt;
&lt;li&gt;Entering into permanent &amp;quot;dead zones&amp;quot; such as in buildings with walls that block network connections.&lt;/li&gt;
&lt;li&gt;Entering into temporary &amp;quot;dead zones&amp;quot; such as when traveling on a train and going through a tunnel.&lt;/li&gt;
&lt;li&gt;Time-boxed internet connections such as those in airports or hotels.&lt;/li&gt;
&lt;li&gt;Cultural practices that require limited or no internet access at specific times or days.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your goal is to provide a good experience that lessens the impact of changes in connectivity.&lt;/p&gt;
&lt;h2 id=&quot;decide-what-to-show-your-users-when-they-have-a-bad-network-connection&quot;&gt;Decide what to show your users when they have a bad network connection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#decide-what-to-show-your-users-when-they-have-a-bad-network-connection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first question that must be asked is what does success and failure of a network connection look
like? A successful connection is your app&#39;s normal online experience. The failure of a connection,
however, can be both the offline state of your app as well how the app behaves when there is a laggy
network.&lt;/p&gt;
&lt;p&gt;When thinking about the success or failure of a network connection you need to ask yourself these
important UX questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How long do you wait to determine the success or failure of a connection?&lt;/li&gt;
&lt;li&gt;What can you do while success or failure is being determined?&lt;/li&gt;
&lt;li&gt;What should you do in the event of failure?&lt;/li&gt;
&lt;li&gt;How do you inform the user of the above?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;inform-users-of-their-current-state-and-change-of-state&quot;&gt;Inform users of their current state and change of state &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#inform-users-of-their-current-state-and-change-of-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Inform the user of both the actions they can still take when they have a network failure and the
current state of the application. For example, a notification could say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You seem to have a bad network connection. Not to worry! Messages will be sent when the
network is restored.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;The Emojoy emoji messaging app informing the user when a change in state occurs.&quot; decoding=&quot;async&quot; height=&quot;601&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 335px) 335px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/roxoXuJ9x7qUHFVWMgXZ.png?auto=format&amp;w=670 670w&quot; width=&quot;335&quot; /&gt;
  &lt;figcaption&gt;
    Clearly inform the user when a change in state occurs as soon as possible.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;The I/O 2016 app informing the user when a change in state occurs.&quot; decoding=&quot;async&quot; height=&quot;601&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 335px) 335px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/GvE07BeSsnTyxnRbkZhz.png?auto=format&amp;w=670 670w&quot; width=&quot;335&quot; /&gt;
  &lt;figcaption&gt;
    The Google I/O app used a &quot;toast&quot; to let the user know when they were offline.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;inform-users-when-the-network-connection-improves-or-is-restored&quot;&gt;Inform users when the network connection improves or is restored &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#inform-users-when-the-network-connection-improves-or-is-restored&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;How you inform the user that their network connection has improved depends
on your application. Apps such as a stock market app that prioritize current information
should auto-update and notify the user as soon as possible.&lt;/p&gt;
&lt;p&gt;It is recommended that you let the user know that your web app has been updated &amp;quot;in the background&amp;quot;
by using a visual cue such as, for example, a material design toast element. This involves detecting both the
the presence of a service worker and an update to its managed
content. You can see a code example of this &lt;a href=&quot;https://github.com/GoogleChrome/sw-precache/blob/master/demo/app/js/service-worker-registration.js#L29&quot;&gt;function
at work here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One example of this would be &lt;a href=&quot;https://chromestatus.com/&quot; rel=&quot;noopener&quot;&gt;Chrome Platform Status&lt;/a&gt;
which posts a note to the user when the app has been updated.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;An example weather app.&quot; decoding=&quot;async&quot; height=&quot;598&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 324px) 324px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ikam7evJEVSicAnVxvWA.png?auto=format&amp;w=648 648w&quot; width=&quot;324&quot; /&gt;
  &lt;figcaption&gt;
    Some apps, such as the weather app, need to auto-update because old data
    is not useful.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Chrome Status uses a toast&quot; decoding=&quot;async&quot; height=&quot;598&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 336px) 336px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5TtIkRCPsuxAOajX8LPF.png?auto=format&amp;w=672 672w&quot; width=&quot;336&quot; /&gt;
  &lt;figcaption&gt;
    Apps such as Chrome Status let the user know
    when content has been updated via a toast.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You may also show the last time the app was updated at all times in a prominent space. This would
be useful for a currency converter app, for example.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;The Material Money app being out-of-date.&quot; decoding=&quot;async&quot; height=&quot;598&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 324px) 324px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/nK4V7aUvmLvaNJgF1S2I.png?auto=format&amp;w=648 648w&quot; width=&quot;324&quot; /&gt;
  &lt;figcaption&gt;
    Material Money caches rates…
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Material money has been updated&quot; decoding=&quot;async&quot; height=&quot;598&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 324px) 324px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/wqaFuHzeAC2wR0D3pt7R.png?auto=format&amp;w=648 648w&quot; width=&quot;324&quot; /&gt;
  &lt;figcaption&gt;
    …and notifies the user when the app has been updated.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Applications such as news apps could show a simple tap-to-update notification
informing the user of new content. Auto-updating would cause users to lose
their place.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;An example news app, Tailpiece in its normal state&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    Tailpiece, an online newspaper, will auto-download the latest news…
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Example news app, Tailpiece when its ready to be updated&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/WNIMNF14cSF29fntl1Lc.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    …but allow users to refresh manually so they do not lose their place in an article.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;update-the-ui-to-reflect-the-current-contextual-state&quot;&gt;Update the UI to reflect the current contextual state &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#update-the-ui-to-reflect-the-current-contextual-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Each bit of UI may have its own context and functionality that will change depending on if it
requires a successful connection. One example would be an e‑commerce site that can be browsed
offline. The Buy button and pricing would be disabled until a connection is reestablished.&lt;/p&gt;
&lt;p&gt;Other forms of contextual states could include data. For example, the financial application
Robinhood allows users to buy stock and uses color and graphics to notify the user when the market
is open. The whole interface turns white and then grays out when the market closes. When the value
of stock increases or decreases, each individual stock widget turns green or red depending on its
state.&lt;/p&gt;
&lt;h3 id=&quot;educate-the-user-so-they-understand-what-the-offline-model-is&quot;&gt;Educate the user so they understand what the offline model is &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#educate-the-user-so-they-understand-what-the-offline-model-is&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Offline is a new mental model for everyone. You need to educate your users about what changes will
occur when they don&#39;t have a connection. Inform them of where large data is saved and give them
settings to change the default behavior. Make sure you use multiple UI design components such as
informative language, icons, notifications, color, and imagery to convey these ideas collectively
rather than relying on a single design choice, such as an icon on its own, to tell the whole story.&lt;/p&gt;
&lt;h2 id=&quot;provide-an-offline-experience-by-default&quot;&gt;Provide an offline experience by default &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#provide-an-offline-experience-by-default&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your app doesn&#39;t require much data, then cache that data by default. Users can become
increasingly frustrated if they can only access their data with a network connection. Try to make
the experience as stable as possible. An unstable connection will make your app feel untrustworthy,
where an app that lessens the impact of a network failure will feel magical to the user.&lt;/p&gt;
&lt;p&gt;News sites could benefit from auto-downloading and auto-saving the latest news so a
user could read today&#39;s news without a connection, perhaps downloading the text without the article
images. Also, adapt to the user&#39;s behavior. For example, if the sports section is what they typically view,
make that the priority download.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Tailpiece informs the user that they are offline with various design widgets.&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/M39yiHQYpXacVII6d7zX.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    If the device is offline, Tailpiece will notify the user with a status message…
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Tailpiece has a visual indicator that shows what sections are ready for offline use.&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/KpkzjYNoCWquWKXTvM28.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    …letting them know that they can at least partially still use the app.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; When it comes to communicating an app&#39;s status, saying &amp;quot;The network is down&amp;quot; sends the message that the app&#39;s network is experiencing problems, whereas &amp;quot;You are disconnected&amp;quot; makes it clearer to the user that the problem is on their end. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;inform-the-user-when-the-app-is-ready-for-offline-consumption&quot;&gt;Inform the user when the app is ready for offline consumption &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#inform-the-user-when-the-app-is-ready-for-offline-consumption&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a web app first loads you need to indicate to the user if it is ready for offline use. Do this
with a
&lt;a href=&quot;https://material.io/components/snackbars&quot; rel=&quot;noopener&quot;&gt;widget that provides brief feedback&lt;/a&gt;
about an operation through a message at the bottom of the screen such as, for example, when a section has
been synced or a data file has downloaded.&lt;/p&gt;
&lt;p&gt;Again think of the language you are using to make sure it is fit for your audience. Ensure the
messaging is the same in all instances where it&#39;s used. The term offline is generally
misunderstood by a non-technical audience so use action-based language that your audience can relate
to.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;I/O app offline.&quot; decoding=&quot;async&quot; height=&quot;664&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/fNOute6xBzFcDUNMeXDe.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    The Google I/O 2016 app notified the user when
    the app is ready for offline use…
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;Chrome Status site is offline.&quot; decoding=&quot;async&quot; height=&quot;664&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Od6jUnazP8n7CMe18G2C.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    …and so does the Chrome Platform Status site, which includes information about the occupied storage.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;make-save-for-offline-an-obvious-part-of-the-interface-for-data-heavy-apps&quot;&gt;Make &#39;save for offline&#39; an obvious part of the interface for data-heavy apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#make-save-for-offline-an-obvious-part-of-the-interface-for-data-heavy-apps&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If an application uses large amounts of data, make sure that there is a switch or pin to add an item
for offline use rather than auto-downloading, unless a user has specifically asked for this behavior
via a settings menu. Make sure that the pin or download UI is not obscured by other UI elements and
that the feature is obvious to the user.&lt;/p&gt;
&lt;p&gt;One example would be a music player that requires large data files. The user is aware of the
associated data cost, but may also want to use the player offline.
Downloading music for later use requires the user to plan ahead, so education about this may be
required during onboarding.&lt;/p&gt;
&lt;h3 id=&quot;clarify-what-is-available-offline&quot;&gt;Clarify what is available offline &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#clarify-what-is-available-offline&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Be clear as to the option you are providing. You may need to show a tab or setting that shows an
&amp;quot;offline library&amp;quot; or &lt;a href=&quot;https://web.dev/content-indexing-api/&quot;&gt;content index&lt;/a&gt;,
so the user can easily see what they have stored on their phone and what needs to
be saved. Make sure the settings are concise and be clear where the data will be stored and who has
access to it.&lt;/p&gt;
&lt;h3 id=&quot;show-the-actual-cost-of-an-action&quot;&gt;Show the actual cost of an action &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#show-the-actual-cost-of-an-action&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many users equate offline capability with &#39;downloading&#39;. Users in countries where network
connections regularly fail or aren&#39;t available often share content with other users, or save content
for offline use when they have connectivity.&lt;/p&gt;
&lt;p&gt;Users on data plans may avoid downloading large files for fear of cost, so you may also want to
display an associated cost so users can make an active comparison for a specific file or task. For
example, if the music app above could detect if the user is on a data plan and show the file size so
that users can see the cost of a file.&lt;/p&gt;
&lt;h3 id=&quot;help-prevent-hacked-experiences&quot;&gt;Help prevent hacked experiences &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#help-prevent-hacked-experiences&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Often users hack an experience without realizing they are doing it. For example before cloud-based
file sharing web apps, it was common for users to save large files and attach them to emails so
they could carry on editing from a different device. It is important not to be pulled into their
hacked experience but rather look at what they are trying to achieve. In other words instead of
thinking of how you can make attaching a large file more user-friendly, solve the problem of
sharing large files across multiple devices.&lt;/p&gt;
&lt;h2 id=&quot;make-experiences-transferable-from-one-device-to-another&quot;&gt;Make experiences transferable from one device to another &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#make-experiences-transferable-from-one-device-to-another&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When building for flaky networks, try to sync as soon as the connection improves
so that the experience is transferable. For example, imagine a travel app losing
a network connection mid-way through a booking. When the connection is reestablished, the app syncs
with the user&#39;s account allowing them to continue their booking on their desktop device. Not being
able to transfer experiences can be incredibly jarring to users.&lt;/p&gt;
&lt;p&gt;Inform the user of the current state of their data. For example, you could show whether the
app has synced. Educate them where possible but try not to overburden them with messaging.&lt;/p&gt;
&lt;h2 id=&quot;create-inclusive-design-experiences&quot;&gt;Create inclusive design experiences &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#create-inclusive-design-experiences&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When designing seek to be inclusive by providing meaningful design devices, simple language,
standard iconography, and meaningful imagery that will guide the user to complete the action or task
rather than hinder their progress.&lt;/p&gt;
&lt;h3 id=&quot;use-simple,-concise-language&quot;&gt;Use simple, concise language &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#use-simple,-concise-language&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Good UX is not just about a well designed interface. It includes the path a user takes as well as
the words used in the app. Avoid tech jargon when explaining the state of the app or
individual UI components. Consider that the phrase &amp;quot;app offline&amp;quot; might not convey to the user the
current state of the app.&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;worse&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Don&#39;t&lt;/p&gt;
  &lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
    &lt;img alt=&quot;A service worker icon is a bad example.&quot; decoding=&quot;async&quot; height=&quot;149&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 350px) 350px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/MaYiuInHsZ2mbPQcbD4l.png?auto=format&amp;w=700 700w&quot; width=&quot;350&quot; /&gt;
    &lt;figcaption&gt;
      Avoid terms that aren&#39;t intelligible to non-technical users.
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/figure&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;better&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Do&lt;/p&gt;
  &lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
    &lt;img alt=&quot;A download icon is a good example.&quot; decoding=&quot;async&quot; height=&quot;149&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 350px) 350px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ZIjYKLFK5DbrDJDJeDqu.png?auto=format&amp;w=700 700w&quot; width=&quot;350&quot; /&gt;
    &lt;figcaption&gt;
      Use language and imagery that describe the action.
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;h3 id=&quot;use-multiple-design-devices-to-create-accessible-user-experiences&quot;&gt;Use multiple design devices to create accessible user experiences &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#use-multiple-design-devices-to-create-accessible-user-experiences&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use language, color, and visual components to demonstrate a change of state or current status.
Solely using color to demonstrate state may not be noticed by the user and may be inaccessible to
users with visual disabilities. Also, the instinct for designers is to use grayed UI
to represent offline, but this can have a loaded meaning on the web. Grayed UI such as input elements
on a form also means that an element is disabled. This can cause confusion if you &lt;em&gt;only&lt;/em&gt;
use color to depict state.&lt;/p&gt;
&lt;p&gt;To prevent misunderstandings, express different states to the user in multiple ways, for example
with color, labels, and UI components.&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;worse&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Don&#39;t&lt;/p&gt;
  &lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
    &lt;img alt=&quot;A bad example only using color.&quot; decoding=&quot;async&quot; height=&quot;368&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 720px) 720px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Uj28SN1ZepiIvya4YTe1.png?auto=format&amp;w=1440 1440w&quot; width=&quot;720&quot; /&gt;
    &lt;figcaption&gt;
      Avoid using color as the sole means to describe what is happening.
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/figure&gt;
&lt;figure class=&quot;compare flow&quot; data-type=&quot;better&quot; data-size=&quot;full&quot;&gt;&lt;p class=&quot;compare__label&quot;&gt;Do&lt;/p&gt;
  &lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
    &lt;img alt=&quot;A good example that uses color and text to show an error.&quot; decoding=&quot;async&quot; height=&quot;368&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 720px) 720px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/s78eC2GBEkDQouqhBYMO.png?auto=format&amp;w=1440 1440w&quot; width=&quot;720&quot; /&gt;
    &lt;figcaption&gt;
      Use a mixture of design elements to convey meaning.
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;h3 id=&quot;use-icons-that-convey-meaning&quot;&gt;Use icons that convey meaning &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#use-icons-that-convey-meaning&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Make sure that information is conveyed correctly with meaningful text labels as well as icons. Icons
alone can be problematic, since the concept of offline on the web is relatively new. Users may
misunderstand icons used on their own. For example, using a floppy disc for save makes sense to an
older generation but young users who have never seen a floppy disc may be confused by the metaphor.
Likewise, the &#39;hamburger&#39; menu icon has been known to confuse users when presented without a label.&lt;/p&gt;
&lt;p&gt;When introducing an offline icon try to remain consistent with industry standard visuals (when they
exist) as well as providing a text label and description. For example, saving for offline might be
a typical download icon or perhaps if the action involves syncing it could be a syncing icon. Some
actions may be interpreted as saving for offline rather than demonstrating a network&#39;s status. Think
of the action you are trying to convey rather than presenting the user with an abstract concept. For
example, save or download data would be action-based.&lt;/p&gt;
&lt;img alt=&quot;Various icon examples that convey offline&quot; decoding=&quot;async&quot; height=&quot;299&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 700px) 700px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/h2FFD3nLIOdSzWg5H5kO.png?auto=format&amp;w=1400 1400w&quot; width=&quot;700&quot; /&gt;
&lt;p&gt;Offline can mean a number of things depending on the context, such as download, export, pin, etc.
For more inspiration checkout the
&lt;a href=&quot;https://material.io/resources/icons/&quot; rel=&quot;noopener&quot;&gt;Material Design icon set&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;use-skeleton-layouts-with-other-feedback-mechanisms&quot;&gt;Use skeleton layouts with other feedback mechanisms &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#use-skeleton-layouts-with-other-feedback-mechanisms&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A skeleton layout is essentially a wireframe version of your app that displays while content is
being loaded. This helps demonstrate to the user that content is about to be loaded. Consider also
using a preloader UI as well, with a text label informing the user that the app is loading. One
example would be to pulsate the wireframe content giving the app the feeling that it is alive and
loading. This reassures the user that something is happening and helps prevent resubmissions or
refreshes of your app.&lt;/p&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;A skeleton layout example.&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/pUIrcbblhHe5YPSrrwRy.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    A skeleton placeholder layout is shown during the download of the article…
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;display: inline-block; max-width: 45%;&quot;&gt;
  &lt;img alt=&quot;A loaded article example.&quot; decoding=&quot;async&quot; height=&quot;665&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/rRLScscdU9BE9Wt4RYAx.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
  &lt;figcaption&gt;
    …that gets replaced with the real contents once the download finishes.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;dont-block-content&quot;&gt;Don&#39;t block content &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#dont-block-content&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In some applications, a user might trigger an action such as creating a new document. Some apps will
try to connect to a server in order to sync the new document and to demonstrate this they display an
intrusive loading modal dialog that covers the entire screen. This may work fine if the user has a
stable network connection, but if the network is unstable they won&#39;t be able to escape from this
action and the UI effectively blocks them from doing anything else. Network requests that block
content should be avoided. Allow the user to continue to browse your app and queue tasks that will
be performed and synced once the connection has improved.&lt;/p&gt;
&lt;p&gt;Demonstrate the state of an action by providing your users with feedback. For example, if a user is
editing a doc, consider changing the feedback design so it is visibly different from when they are
online but still shows that their file was &amp;quot;saved&amp;quot; and will sync when they have a network
connection. This will educate the user about the different states available and reassure them that
their task or action has been stored. This has the added benefit of the user growing more confident
using your application.&lt;/p&gt;
&lt;h2 id=&quot;design-for-the-next-billion&quot;&gt;Design for the next billion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#design-for-the-next-billion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In many regions, low-end devices are commonplace, connectivity is unreliable and, for many users,
data is unaffordable. You will need to earn user trust by being transparent and frugal with data.
Think about ways to help users on poor connections and simplify the interface to help speed up
tasks. Always try to ask users before downloading data-heavy content.&lt;/p&gt;
&lt;p&gt;Offer low bandwidth options for users on laggy connections. So if the network connection is slow,
provide small assets. Offer an option to choose high or low quality assets.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/offline-ux-design-guidelines/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Education is key to offline UX as users are unfamiliar with these concepts. Try to create associations
with things that are familiar, e.g downloading for later use is the same as offlining data.&lt;/p&gt;
&lt;p&gt;When designing for unstable network connections, remember these guidelines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Design for the success, failure, and instability of a network connection.&lt;/li&gt;
&lt;li&gt;Data may be expensive, so be considerate to the user.&lt;/li&gt;
&lt;li&gt;For most users globally, the tech environment is almost exclusively mobile.&lt;/li&gt;
&lt;li&gt;Low-end devices are commonplace, with limited storage, memory, and processing power, and small
displays and lower touchscreen quality. Make sure performance is a part of your design process.&lt;/li&gt;
&lt;li&gt;Allow users to browse your application when they are offline.&lt;/li&gt;
&lt;li&gt;Inform users of their current state and of changes in states.&lt;/li&gt;
&lt;li&gt;Try to provide offline by default if your app doesn&#39;t require much data.&lt;/li&gt;
&lt;li&gt;If the app is data-heavy, educate users about how they can download for offline use.&lt;/li&gt;
&lt;li&gt;Make experiences transferable between devices.&lt;/li&gt;
&lt;li&gt;Use language, icons, imagery, typography, and color together to express ideas to the user.&lt;/li&gt;
&lt;li&gt;Provide reassurance and feedback to help the user.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Mustafa Kurtuldu</name>
    </author><author>
      <name>Thomas Steiner</name>
    </author>
  </entry>
</feed>
