<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Paul Kinlan on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Paul Kinlan</name>
  </author>
  <link href="https://web.dev/authors/paulkinlan/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/0O1ZGr2P0l9oTKabyUK5.jpeg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Developer Advocate</subtitle>
  
  
  <entry>
    <title>Farewell to HTML5Rocks</title>
    <link href="https://web.dev/farewell-html5rocks/"/>
    <updated>2022-06-29T00:00:00Z</updated>
    <id>https://web.dev/farewell-html5rocks/</id>
    <content type="html" mode="escaped">&lt;p&gt;After 10 years and 100 million pageviews this
&lt;a href=&quot;https://github.com/html5rocks/www.html5rocks.com/pull/1548&quot; rel=&quot;noopener&quot;&gt;commit&lt;/a&gt; completes
our transition of content of HTML5Rocks to homes that are maintained on
&lt;a href=&quot;https://developer.chrome.com/&quot; rel=&quot;noopener&quot;&gt;developer.chrome.com&lt;/a&gt; and
&lt;a href=&quot;https://web.dev/&quot;&gt;web.dev&lt;/a&gt;. It feels like a bit of an end of an era.&lt;/p&gt;
&lt;p&gt;I was around for the founding of HTML5Rocks. We had so much fun building the
serving infrastructure (several times) and creating a lot of the content—from
walkthroughs of WebSQL and AppCache, the first introductions to new APIs such as
IndexedDB, and explainers for How the Browser works.&lt;/p&gt;
&lt;p&gt;Our most popular article was about CORS (Cross Origin Resource Sharing),
followed by dragging and dropping files, and then one of the first introductions
to getUserMedia and WebRTC. Contrasting the popularity of core &amp;quot;simple&amp;quot; tasks
against the new and shiny capabilities is something that impacts developers
today just as much as it did in 2012.&lt;/p&gt;
&lt;p&gt;One thing I will miss the most is the community that developed around the site.
HTML5Rocks was the first public site I helped to create that managed to build a
huge community around it. It was one of the quickest ways to get feedback from
developers that could be fed right back into the browser engineering teams.
However, over the last couple of years as our priorities changed, &amp;quot;HTML5&amp;quot; became
&amp;quot;HTML&amp;quot;, and we slowly stopped creating new content and engaging with the
community on the site. As the founders of our team moved on, I was left as the
only person who could deploy the site and so I felt it was time to ensure that
we had a permanent home that has a dedicated team supporting both the content
and the infrastructure.&lt;/p&gt;
&lt;p&gt;With this transition it was important for us to maintain the content (it&#39;s still
valuable), but more importantly maintain the in-bound links. People found our
content interesting enough for them to share with their audiences, so I&#39;d like
to maintain that trust given to us and ensure that all the links will still
resolve to the content. If you do see an issue with any of the content, reach out
to us and file an issue on
&lt;a href=&quot;https://github.com/googlechrome/web.dev/issues&quot; rel=&quot;noopener&quot;&gt;web.dev&lt;/a&gt; or
&lt;a href=&quot;https://github.com/googlechrome/developer.chrome.com/issues&quot; rel=&quot;noopener&quot;&gt;developer.chrome.com&lt;/a&gt;
issue trackers.&lt;/p&gt;
&lt;p&gt;Thank you to everyone who wrote content for the site, for the people who
translated the content so that it could be read everywhere, and all the readers
and commenters who made the site the place to go and learn about what&#39;s new on
the web.&lt;/p&gt;
&lt;p&gt;I&#39;m off to register HTMLLivingStandardRocks.com…&lt;/p&gt;
&lt;p&gt;♥️ Paul&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@photolli?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Oliver Paaske&lt;/a&gt;
on &lt;a href=&quot;https://unsplash.com/s/photos/rocks?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Google I/O 2022: That&#39;s a wrap!</title>
    <link href="https://web.dev/googleio22-recap/"/>
    <updated>2022-05-13T00:00:00Z</updated>
    <id>https://web.dev/googleio22-recap/</id>
    <content type="html" mode="escaped">&lt;p&gt;At &lt;a href=&quot;https://io.google/2022/products/web/&quot; rel=&quot;noopener&quot;&gt;Google IO 2022&lt;/a&gt; we shared updates on our progress to help create a web that is instant, and connects people, no matter their device or bandwidth. A powerful platform that delivers experiences that we once never thought possible in a browser. And one that people can trust to keep their data safe. Here&#39;s a recap on how we&#39;re making it easy for you to build experiences that people will love.&lt;/p&gt;
&lt;h2 id=&quot;an-instant-web&quot;&gt;An instant web &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/googleio22-recap/#an-instant-web&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Great web performance is a partnership between the browser and web developers. That&#39;s why we&#39;ve made it easy for you to measure how well your website performs with the three Core Web Vitals. Optimizing your Vitals results in a better user experience, and better discoverability through Google Search. Be sure to check out our session, &lt;a href=&quot;https://io.google/2022/program/7cb6e1ad-504b-42d8-9ab6-105c48a65b80/&quot; rel=&quot;noopener&quot;&gt;Core Web Vitals in the real world&lt;/a&gt; to learn how websites around the world are optimizing their scores to achieve better user experiences.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; is an important, user-centric metric for measuring perceived load speed. A fast LCP helps reassure the user that the page is useful, because it marks the point in the page load timeline when the main content has loaded. To learn more about this complex metric, check out our session, &lt;a href=&quot;https://io.google/2022/program/3d49f700-4e86-4a50-9f8a-1a2742bc4c22/&quot; rel=&quot;noopener&quot;&gt;A deep dive into optimizing LCP&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://io.google/2022/program/3d49f700-4e86-4a50-9f8a-1a2742bc4c22/&quot;&gt;
&lt;img alt=&quot;A still from a talk with the speaker sharing an LCP value of 52.7%&quot; decoding=&quot;async&quot; height=&quot;442&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/DzsyLVvbTlGL6MT3cHcW.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Another new performance metric is something we are calling &lt;a href=&quot;http://web.dev/inp/&quot; rel=&quot;noopener&quot;&gt;Interaction to Next Paint&lt;/a&gt; (INP). Unlike First Input Delay, it considers not just the first interaction, but all interactions on a page. INP therefore does a better job of capturing the interaction latency as experienced by the user. Learn more by checking out &lt;a href=&quot;https://io.google/2022/program/62e33209-bd18-48c5-801f-d6d1cc442e4b/&quot; rel=&quot;noopener&quot;&gt;The State of Responsiveness on the Web&lt;/a&gt; session. For help with your performance journey, be sure to &lt;a href=&quot;https://io.google/2022/program/6213f6fd-c940-4e80-b011-beec59d610f8/&quot; rel=&quot;noopener&quot;&gt;check out the new Performance Insights panel in Chrome DevTools along with many more updates&lt;/a&gt; based on your feedback.&lt;/p&gt;
&lt;h2 id=&quot;powerful-capabilities&quot;&gt;Powerful capabilities &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/googleio22-recap/#powerful-capabilities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since last I/O, an array of new APIs have landed in stable Chrome. These unlock powerful new web experiences for the user. One of my favorite examples is how &lt;a href=&quot;https://io.google/2022/program/b235121c-8e48-4cfb-89a6-1481c220fce1/&quot; rel=&quot;noopener&quot;&gt;Adobe brought Creative Cloud to the web, starting with Photoshop and Illustrator.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We&#39;re also continuing to expand on the ways websites can integrate with the underlying operating system and hardware. Advanced apps now have the capability to seamlessly integrate with the operating system, so users can find the app on their desktop or homescreen, or easily access their files. We&#39;ve also continued to improve installability, so be sure to &lt;a href=&quot;https://io.google/2022/program/a8a9892b-ae1d-4078-a818-2ff0b674a12b/&quot; rel=&quot;noopener&quot;&gt;check out how to make a richer install experience&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://io.google/2022/program/a8a9892b-ae1d-4078-a818-2ff0b674a12b/&quot;&gt;
&lt;img alt=&quot;A still from a talk with the speaker showing examples of a richer install UI.&quot; decoding=&quot;async&quot; height=&quot;441&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/bA4Q4h2lp1ZkBws5N5hi.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 id=&quot;safe-and-secure&quot;&gt;Safe and secure &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/googleio22-recap/#safe-and-secure&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chrome innovation extends to our work on user privacy and security. That&#39;s why we&#39;re taking a different approach by providing a path for developers to maintain functionality, while keeping the user safe. This is our &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/&quot; rel=&quot;noopener&quot;&gt;Privacy Sandbox vision&lt;/a&gt;. Learn more about the &lt;a href=&quot;https://io.google/2022/program/fd566197-8194-4989-91dc-6fd0173faa7e/&quot; rel=&quot;noopener&quot;&gt;progress we&#39;ve made to phase out third-party cookies and land new APIs without cross-site tracking&lt;/a&gt;. We have a number of new origin trials that you can participate in today that will help you preserve web functionality, while safeguarding user privacy.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://io.google/2022/program/fd566197-8194-4989-91dc-6fd0173faa7e/&quot;&gt;
&lt;img alt=&quot;A still from a talk showing set-cookie code along with the speaker.&quot; decoding=&quot;async&quot; height=&quot;441&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/Y2CyrX6t1IeG014OKBsn.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;And to keep users safe from phishing, we need better authentication methods. We&#39;re removing the friction of sign on and passwords with passkeys, which you can learn more in our session, &lt;a href=&quot;https://io.google/2022/program/e3bb37a4-2723-4d72-a5b3-1a23abb94ac0/&quot; rel=&quot;noopener&quot;&gt;A path to a world without passwords&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;beautiful-and-delightful&quot;&gt;Beautiful and delightful &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/googleio22-recap/#beautiful-and-delightful&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This last year has seen huge improvements across all browsers in CSS and layout primitives. For Chrome, &lt;a href=&quot;https://developer.chrome.com/blog/renderingng/&quot; rel=&quot;noopener&quot;&gt;RenderingNG&lt;/a&gt; has made it possible to deliver a number of features that have been long hoped for by developers. Watch our &lt;a href=&quot;https://io.google/2022/program/9f58d739-87b1-42f0-b715-32584508a69b/&quot; rel=&quot;noopener&quot;&gt;State of CSS&lt;/a&gt; and explore new styling APIs available today and tomorrow: container queries, subgrid, color functions, or check out our &lt;a href=&quot;https://io.google/2022/program/81ed353d-20e4-4e9a-9b4d-d65b103cfc71/&quot; rel=&quot;noopener&quot;&gt;Shared Element Transitions&lt;/a&gt; talk to learn how we are working to bring seamless transitions between pages.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://io.google/2022/program/9f58d739-87b1-42f0-b715-32584508a69b/&quot;&gt;
&lt;img alt=&quot;A still from a talk featuring a speaker and a slide showing the CSS accent-color property.&quot; decoding=&quot;async&quot; height=&quot;440&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/883tzmfbbcALNf8itivk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 id=&quot;simplifying-web-development&quot;&gt;Simplifying web development &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/googleio22-recap/#simplifying-web-development&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We share our innovation through Chromium, our open-source browser project that brings the web to Android apps, TVs and VR headsets, and is the engine powering other browsers.&lt;/p&gt;
&lt;p&gt;We&#39;re mindful that your priorities are for building features that work across many browsers. &lt;a href=&quot;https://io.google/2022/program/6c749c36-e85f-470f-a981-49b1ddbe9d20/&quot; rel=&quot;noopener&quot;&gt;Learn about how we, along with other browsers, are working together to make it easier to develop for the web&lt;/a&gt; by ensuring features are interoperable so you can focus on building rich web experiences for users.&lt;/p&gt;
&lt;p&gt;Finally, be sure to check out our &lt;a href=&quot;https://io.google/2022/program/3c60e411-5340-4c54-a037-3aceb2825b16/&quot; rel=&quot;noopener&quot;&gt;What&#39;s new for the web platform&lt;/a&gt; keynote where we&#39;ll walk you through the latest web platform features and their availability across browsers so you know when you can rely on them in your sites and apps.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://io.google/2022/program/3c60e411-5340-4c54-a037-3aceb2825b16/&quot;&gt;
&lt;img alt=&quot;A still from the What&amp;#x27;s new for the web platform talk.&quot; decoding=&quot;async&quot; height=&quot;440&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/QuNDlrtCHpe5kbgmnsXT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/a&gt;&lt;/figure&gt;</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Quickly create nice CSS gradients with the CSS Gradient Creator</title>
    <link href="https://web.dev/css-gradient-generator/"/>
    <updated>2022-05-04T00:00:00Z</updated>
    <id>https://web.dev/css-gradient-generator/</id>
    <content type="html" mode="escaped">&lt;p&gt;This &lt;a href=&quot;https://www.joshwcomeau.com/gradient-generator/&quot; rel=&quot;noopener&quot;&gt;CSS Gradient Generator&lt;/a&gt; by Josh W Comeau is a very good, simple Web App that helps you to create &amp;quot;Beautiful, lush gradients&amp;quot;.&lt;/p&gt;
&lt;img alt=&quot;A screenshot of the Gradient Editor with a simple linear gradient.&quot; decoding=&quot;async&quot; height=&quot;693&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/rq1kLlxRBubsZSyX0gs2nghLSZc2/CGKiSTSDSv30GLu7JuQR.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;I personally struggle mapping the syntax to a visual so this tool has been a great help for me. It focuses on creating &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/gradient/linear-gradient&quot; rel=&quot;noopener&quot;&gt;linear gradients&lt;/a&gt; and it allows you to configure them using a number of different color modes (like HCL) even though they aren&#39;t directly supported on the &lt;code&gt;linear-gradient&lt;/code&gt; CSS function. &lt;a href=&quot;https://www.joshwcomeau.com/css/make-beautiful-gradients/&quot; rel=&quot;noopener&quot;&gt;Josh&#39;s supporting blog post&lt;/a&gt; goes into more detail about how the color interpolation is calculated and applied to something the browser can render—it&#39;s a fascinating read into some of the theory behind how it works.&lt;/p&gt;
&lt;h3 id=&quot;linear-gradient&quot;&gt;Linear gradient &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-gradient-generator/#linear-gradient&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 26, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      26
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 16, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 7, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      7
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/gradient/linear-gradient#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Hero image by &lt;a href=&quot;https://unsplash.com/@lukechesser?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Luke Chesser&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/linear-gradient?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Recording Audio from the User</title>
    <link href="https://web.dev/media-recording-audio/"/>
    <updated>2016-08-23T00:00:00Z</updated>
    <id>https://web.dev/media-recording-audio/</id>
    <content type="html" mode="escaped">&lt;p&gt;Many browsers now have the ability to access video and audio input from the
user. However, depending on the browser, it might be a full dynamic and inline
experience, or it could be delegated to another app on the user&#39;s device.&lt;/p&gt;
&lt;h2 id=&quot;start-simple-and-progressively&quot;&gt;Start simple and progressively &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#start-simple-and-progressively&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The easiest thing to do is simply ask the user for a pre-recorded file. Do this by creating a simple
file input element and adding an &lt;code&gt;accept&lt;/code&gt; filter that indicates we can only accept audio files, and
a &lt;code&gt;capture&lt;/code&gt; attribute that indicates we want to get it direct from the microphone.&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;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;audio/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;capture&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 method works on all platforms. On desktop, it will prompt the user to
upload a file from the file system (ignoring the &lt;code&gt;capture&lt;/code&gt; attribute). In Safari
on iOS, it will open up the microphone app, allowing you to record audio and
then send it back to the web page; on Android, it will give the user the
choice of which app to use record the audio in before sending it back to the web
page.&lt;/p&gt;
&lt;p&gt;Once the user has finished recording and they are back in the website, you
need to somehow get ahold of the file data. You can get quick access by
attaching an &lt;code&gt;onchange&lt;/code&gt; event to the input element and then reading
the &lt;code&gt;files&lt;/code&gt; property of the event object.&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;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;audio/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;capture&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;recorder&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;&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;audio&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;player&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;audio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; recorder &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;recorder&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; player &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;player&#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;br /&gt;    recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;change&#39;&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;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&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;// Do something with the audio file.&lt;/span&gt;&lt;br /&gt;      player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;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;audio&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;Once you have access to the file, you can do anything you want with it. For
example, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Attach it directly to an &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element so that you can play it&lt;/li&gt;
&lt;li&gt;Download it to the user&#39;s device&lt;/li&gt;
&lt;li&gt;Upload it to a server by attaching it to an &lt;code&gt;XMLHttpRequest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pass it through the Web Audio API and apply filters on to it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whilst using the input element method of getting access to audio data is
ubiquitous, it is the least appealing option. We really want to get access to
the microphone and provide a nice experience directly in the page.&lt;/p&gt;
&lt;h2 id=&quot;access-the-microphone-interactively&quot;&gt;Access the microphone interactively &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#access-the-microphone-interactively&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Modern browsers can have a direct line to the microphone allowing us to build
experiences that are fully integrated with the web page and the user will never
leave the browser.&lt;/p&gt;
&lt;h3 id=&quot;acquire-access-to-the-microphone&quot;&gt;Acquire access to the microphone &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#acquire-access-to-the-microphone&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We can directly access the Microphone by using an API in the WebRTC
specification called &lt;code&gt;getUserMedia()&lt;/code&gt;. &lt;code&gt;getUserMedia()&lt;/code&gt; will prompt the user for
access to their connected microphones and cameras.&lt;/p&gt;
&lt;p&gt;If successful the API will return a &lt;code&gt;Stream&lt;/code&gt; that will contain the data from either the camera or
the microphone, and we can then either attach it to an &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element, attach it to a WebRTC
stream, attach it to a Web Audio &lt;code&gt;AudioContext&lt;/code&gt;, or save it using the &lt;code&gt;MediaRecorder&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;To get data from the microphone, we just set &lt;code&gt;audio: true&lt;/code&gt; in the constraints
object that is passed to the &lt;code&gt;getUserMedia()&lt;/code&gt; API.&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;audio&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;player&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;audio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; player &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;player&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;URL&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;      player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;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 function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleSuccess&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&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you want to choose a particular microphone, you can first enumerate the available microphones.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enumerateDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  devices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; devices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;audioinput&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can then pass the &lt;code&gt;deviceId&lt;/code&gt; that you wish to use when you call &lt;code&gt;getUserMedia&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;deviceId&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; devices&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deviceId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;By itself, this isn&#39;t that useful. All we can do is take the audio data and play it back.&lt;/p&gt;
&lt;h3 id=&quot;access-the-raw-data-from-the-microphone&quot;&gt;Access the raw data from the microphone &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#access-the-raw-data-from-the-microphone&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To access the raw data from the microphone, we have to take the stream created by
&lt;code&gt;getUserMedia()&lt;/code&gt; and then use the Web Audio API to process the data. The
Web Audio API is a simple API that takes input sources and connects those
sources to nodes which can process the audio data (adjust Gain etc.) and
ultimately to a speaker so that the user can hear it.&lt;/p&gt;
&lt;p&gt;One of the nodes that you can connect is an &lt;code&gt;AudioWorkletNode&lt;/code&gt;. This node gives
you the low-level capability for custom audio processing. The actual audio
processing happens in the &lt;code&gt;process()&lt;/code&gt; callback method in the &lt;code&gt;AudioWorkletProcessor&lt;/code&gt;.
Call this function to feed inputs and parameters and fetch outputs.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://developer.chrome.com/blog/audio-worklet/&quot; rel=&quot;noopener&quot;&gt;Enter Audio Worklet&lt;/a&gt;
to learn more.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token 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;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; context &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;AudioContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; source &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createMediaStreamSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stream&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;await&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;audioWorklet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addModule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;processor.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; worklet &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;AudioWorkletNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;worklet-processor&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;worklet&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;    worklet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;destination&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;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 function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleSuccess&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&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// processor.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WorkletProcessor&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AudioWorkletProcessor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;inputs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; outputs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; parameters&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;// Do something with the data, e.g. convert it to WAV&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inputs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;registerProcessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;worklet-processor&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WorkletProcessor&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;The data that is held in the buffers is the raw data from the microphone and
you have a number of options with what you can do with that data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upload it straight to the server&lt;/li&gt;
&lt;li&gt;Store it locally&lt;/li&gt;
&lt;li&gt;Convert it to a dedicated file format, such as WAV, and then save it to your
servers or locally&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;save-the-data-from-the-microphone&quot;&gt;Save the data from the microphone &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#save-the-data-from-the-microphone&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The easiest way to save the data from the microphone is to use the
&lt;code&gt;MediaRecorder&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;MediaRecorder&lt;/code&gt; API will take the stream created by &lt;code&gt;getUserMedia&lt;/code&gt; and then
progressively save the data that is on the stream into your preferred
destination.&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;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;download&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;Download&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;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;stop&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;Stop&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;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; downloadLink &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;download&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stopButton &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;stop&#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;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;mimeType&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;audio/webm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; recordedChunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mediaRecorder &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;MediaRecorder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&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;    mediaRecorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;dataavailable&#39;&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;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; recordedChunks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&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;    mediaRecorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;stop&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      downloadLink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;recordedChunks&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;      downloadLink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;download &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;acetest.wav&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    stopButton&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      mediaRecorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    mediaRecorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;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 function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleSuccess&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&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In our case, we are saving the data directly into an array that we can later turn
into a &lt;code&gt;Blob&lt;/code&gt;, which can be then used to save the data to our Web Server or directly
to the storage on the user&#39;s device.&lt;/p&gt;
&lt;h3 id=&quot;ask-permission-to-use-microphone-responsibly&quot;&gt;Ask permission to use microphone responsibly &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#ask-permission-to-use-microphone-responsibly&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If the user has not previously granted your site access to the microphone, then
the instant that you call &lt;code&gt;getUserMedia&lt;/code&gt;, the browser will prompt the user to
grant your site permission to the microphone.&lt;/p&gt;
&lt;p&gt;Users hate getting prompted for access to powerful devices on their machine and
they will frequently block the request, or they will ignore it if they don&#39;t
understand the context of which the prompt has been created. It is best practice
to only ask to access the microphone when first needed. Once the user has
granted access, they won&#39;t be asked again, however, if they reject access,
you can&#39;t ask the user for permission again.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Asking for access to the microphone on page load will result in most of your users rejecting access to the mic. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;use-the-permissions-api-to-check-if-you-already-have-access&quot;&gt;Use the permissions API to check if you already have access &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#use-the-permissions-api-to-check-if-you-already-have-access&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;getUserMedia&lt;/code&gt; API provides you with no knowledge of if you already have
access to the microphone. This presents you with a problem, to provide a nice UI
to get the user to grant you access to the microphone, you have to ask for
access to the microphone.&lt;/p&gt;
&lt;p&gt;This can be solved in some browsers by using the Permission API. The
&lt;code&gt;navigator.permission&lt;/code&gt; API allows you to query the state of the ability to
access specific API&#39;s without having to prompt again.&lt;/p&gt;
&lt;p&gt;To query if you have access to the user&#39;s microphone, you can pass in
&lt;code&gt;{name: &#39;microphone&#39;}&lt;/code&gt; into the query method and it will return either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;granted&lt;/code&gt; — the user has previously given you access to the microphone;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompt&lt;/code&gt; — the user has not given you access and will be prompted when
you call &lt;code&gt;getUserMedia&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;denied&lt;/code&gt; — the system or the user has explicitly blocked access to the
microphone and you won&#39;t be able to get access to it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And you can now quickly check to see if you need to alter your user
interface to accommodate the actions that the user needs to take.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permissions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;microphone&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&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;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;granted&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;prompt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;denied&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onchange&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-recording-audio/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Capturing an image from the user</title>
    <link href="https://web.dev/media-capturing-images/"/>
    <updated>2016-08-23T00:00:00Z</updated>
    <id>https://web.dev/media-capturing-images/</id>
    <content type="html" mode="escaped">&lt;p&gt;Many browsers now have the ability to access video and audio input from the
user. However, depending on the browser it might be a full dynamic and inline
experience, or it could be delegated to another app on the user&#39;s device. On top
of that, not every device even has a camera. So how can you create an experience
that uses a user generated image that works well everywhere?&lt;/p&gt;
&lt;h2 id=&quot;start-simple-and-progressively&quot;&gt;Start simple and progressively &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#start-simple-and-progressively&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to progressively enhance your experience, you need to start with something that works
everywhere. The easiest thing to do is simply ask the user for a pre-recorded file.&lt;/p&gt;
&lt;h3 id=&quot;ask-for-a-url&quot;&gt;Ask for a URL &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#ask-for-a-url&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the best supported but least satisfying option. Get the user to give you a URL, and then
use that. For just displaying the image this works everywhere. Create an &lt;code&gt;img&lt;/code&gt; element, set the
&lt;code&gt;src&lt;/code&gt; and you&#39;re done.&lt;/p&gt;
&lt;p&gt;Though, if you want to manipulate the image in any way, things are a bit more complicated.
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS&quot; rel=&quot;noopener&quot;&gt;CORS&lt;/a&gt; prevents you from
accessing the actual pixels unless the server sets the appropriate headers and you
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/CORS_enabled_image&quot; rel=&quot;noopener&quot;&gt;mark the image as crossorigin&lt;/a&gt;
; the only practical way around that is to run a proxy server.&lt;/p&gt;
&lt;h3 id=&quot;file-input&quot;&gt;File input &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#file-input&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can also use a simple file input element, including an &lt;code&gt;accept&lt;/code&gt; filter that indicates you only
want image files.&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;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;image/*&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 method works on all platforms. On desktop it will prompt the user to
upload an image file from the file system. In Chrome and Safari on iOS and Android this method will
give the user a choice of which app to use to capture the image, including the option of taking a
photo directly with the camera or choosing an existing image file.&lt;/p&gt;
&lt;img alt=&quot;An Android menu, with two options: capture image and files&quot; decoding=&quot;async&quot; height=&quot;225&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 250px) 250px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0ntcSaXvXa2SF8tMZPAf.png?auto=format&amp;w=500 500w&quot; width=&quot;250&quot; /&gt;
&lt;img alt=&quot;An iOS menu, with three options: take photo, photo library, iCloud&quot; decoding=&quot;async&quot; height=&quot;225&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 250px) 250px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/0be5Qo05FEpWvPxy5F6p.png?auto=format&amp;w=500 500w&quot; width=&quot;250&quot; /&gt;
&lt;p&gt;The data can then be attached to a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; or manipulated with JavaScript by
listening for an &lt;code&gt;onchange&lt;/code&gt; event on the input element and then reading
the &lt;code&gt;files&lt;/code&gt; property of the event &lt;code&gt;target&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;image/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;file-input&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;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileInput &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;file-input&#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;br /&gt;  fileInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;change&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;doSomethingWithFiles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;files&lt;/code&gt; property is a &lt;code&gt;FileList&lt;/code&gt; object, which I&#39;ll talk more about later.&lt;/p&gt;
&lt;p&gt;You can also optionally add the &lt;code&gt;capture&lt;/code&gt; attribute to the element, which indicates to the browser
that you prefer getting an image from the camera.&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;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;image/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;capture&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;image/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;capture&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;user&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;&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;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&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;file&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;accept&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;image/*&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;capture&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;environment&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;Adding the &lt;code&gt;capture&lt;/code&gt; attribute without a value let&#39;s the browser decide which camera to use, while
the &lt;code&gt;&amp;quot;user&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;environment&amp;quot;&lt;/code&gt; values tell the browser to prefer the front and rear cameras,
respectively.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;capture&lt;/code&gt; attribute works on Android and iOS, but is ignored on desktop. Be aware, however,
that on Android this means that the user will no longer have the option of choosing an existing
picture. The system camera app will be started directly, instead.&lt;/p&gt;
&lt;h3 id=&quot;drag-and-drop&quot;&gt;Drag and drop &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#drag-and-drop&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you are already adding the ability to upload a file, there are a couple of easy ways that you
can make the user experience a little richer.&lt;/p&gt;
&lt;p&gt;The first is to add a drop target to your page that allows the user to drag in a file from the
desktop or another application.&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;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;target&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;You can drag an image file here&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;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; target &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;target&#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;br /&gt;  target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;drop&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stopPropagation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;doSomethingWithFiles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dataTransfer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&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;  target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;dragover&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stopPropagation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dataTransfer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dropEffect &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;copy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Similar to the file input, you can get a &lt;code&gt;FileList&lt;/code&gt; object from the &lt;code&gt;dataTransfer.files&lt;/code&gt; property of
the &lt;code&gt;drop&lt;/code&gt; event;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;dragover&lt;/code&gt; event handler lets you signal to the user what will happen when they drop the file
by using
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/DataTransfer/dropEffect&quot; rel=&quot;noopener&quot;&gt;the &lt;code&gt;dropEffect&lt;/code&gt; property&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Drag and drop has been around for a long time and is well-supported by the major browsers.&lt;/p&gt;
&lt;h3 id=&quot;paste-from-clipboard&quot;&gt;Paste from clipboard &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#paste-from-clipboard&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The final way to get an existing image file is from the clipboard. The code for this is very simple,
but the user experience is a little harder to get right.&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;textarea&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;target&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;Paste an image here&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;textarea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; target &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;target&#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;br /&gt;  target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paste&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;doSomethingWithFiles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clipboardData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;(&lt;code&gt;e.clipboardData.files&lt;/code&gt; is yet another &lt;code&gt;FileList&lt;/code&gt; object.)&lt;/p&gt;
&lt;p&gt;The tricky part with the clipboard API is that, for full cross-browser support, the target element
needs to be both selectable and editable. Both &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;input type=&amp;quot;text&amp;quot;&amp;gt;&lt;/code&gt; fit the bill
here, as do elements with the &lt;code&gt;contenteditable&lt;/code&gt; attribute. But these are also obviously designed for
editing text.&lt;/p&gt;
&lt;p&gt;It can be difficult to make this work smoothly if you don&#39;t want the user to be able to input
text. Tricks like having a hidden input that gets selected when you click on some other element may
make maintaining accessibility harder.&lt;/p&gt;
&lt;h3 id=&quot;handling-a-filelist-object&quot;&gt;Handling a FileList object &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#handling-a-filelist-object&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Since most of the above methods produce a &lt;code&gt;FileList&lt;/code&gt;, I should talk a little about what that is.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;FileList&lt;/code&gt; is similar to an &lt;code&gt;Array&lt;/code&gt;. It has numeric keys and a &lt;code&gt;length&lt;/code&gt; property, but it isn&#39;t
&lt;em&gt;actually&lt;/em&gt; an array. There are no array methods, like &lt;code&gt;forEach()&lt;/code&gt; or &lt;code&gt;pop()&lt;/code&gt;, and it isn&#39;t iterable.
Of course, you can get a real Array by using &lt;code&gt;Array.from(fileList)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The entries of the &lt;code&gt;FileList&lt;/code&gt; are &lt;code&gt;File&lt;/code&gt; objects. These are exactly the same as &lt;code&gt;Blob&lt;/code&gt; objects
except that they have additional &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;lastModified&lt;/code&gt; read-only properties.&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;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;output&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;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; output &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;output&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doSomethingWithFiles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fileList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&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;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; fileList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;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;fileList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&lt;span class=&quot;token anchor function&quot;&gt;^&lt;/span&gt;image&lt;span class=&quot;token escape&quot;&gt;\/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fileList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;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;file &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&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;      output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This example finds the first file that has an image MIME type, but it could also handle multiple
images being selected/pasted/dropped at once.&lt;/p&gt;
&lt;p&gt;Once you have access to the file you can do anything you want with it. For
example, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Draw it into a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element so that you can manipulate it&lt;/li&gt;
&lt;li&gt;Download it to the user&#39;s device&lt;/li&gt;
&lt;li&gt;Upload it to a server with &lt;code&gt;fetch()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;access-the-camera-interactively&quot;&gt;Access the camera interactively &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#access-the-camera-interactively&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you&#39;ve covered your bases, it&#39;s time to progressively enhance!&lt;/p&gt;
&lt;p&gt;Modern browsers can get direct access to cameras, allowing you to build
experiences that are fully integrated with the web page, so the user need never
leave the browser.&lt;/p&gt;
&lt;h3 id=&quot;acquire-access-to-the-camera&quot;&gt;Acquire access to the camera &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#acquire-access-to-the-camera&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can directly access a camera and microphone by using an API in the WebRTC
specification called &lt;code&gt;getUserMedia()&lt;/code&gt;. This will prompt the user for
access to their connected microphones and cameras.&lt;/p&gt;
&lt;p&gt;Support for &lt;code&gt;getUserMedia()&lt;/code&gt; is pretty good, but it isn&#39;t yet everywhere. In particular, it is not
available in Safari 10 or lower, which at the time of writing is still the latest stable version.
However, &lt;a href=&quot;https://webkit.org/blog/7726/announcing-webrtc-and-media-capture/&quot; rel=&quot;noopener&quot;&gt;Apple have announced&lt;/a&gt;
that it will be available in Safari 11.&lt;/p&gt;
&lt;p&gt;It&#39;s very simple to detect support, however.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; supported &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mediaDevices&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Direct access to the camera is a powerful feature. It requires consent from the user, and your site MUST be on a secure origin (HTTPS). &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;When you call &lt;code&gt;getUserMedia()&lt;/code&gt;, you need to pass in an object that describes what kind of media you
want. These choices are called constraints. There are a several possible constraints, covering
things like whether you prefer a front- or rear-facing camera, whether you want audio, and your
preferred resolution for the stream.&lt;/p&gt;
&lt;p&gt;To get data from the camera, however, you need just one constraint, and that is &lt;code&gt;video: true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If successful the API will return a &lt;code&gt;MediaStream&lt;/code&gt; that contains data from
the camera, and you can then either attach it to a &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element and play it
to show a real time preview, or attach it to a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; to get a
snapshot.&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;video&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;player&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autoplay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;video&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; player &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;player&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;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;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constraints&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;By itself, this isn&#39;t that useful. All you can do is take the video data and play
it back. If you want to get an image, you have to do a little extra work.&lt;/p&gt;
&lt;h3 id=&quot;grab-a-snapshot&quot;&gt;Grab a snapshot &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#grab-a-snapshot&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Your best supported option for getting an image is to draw a frame from the video to a canvas.&lt;/p&gt;
&lt;p&gt;Unlike the Web Audio API, there isn&#39;t a dedicated stream processing API for video on the web so you
have to resort to a tiny bit of hackery to capture a snapshot from the user&#39;s camera.&lt;/p&gt;
&lt;p&gt;The process is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a canvas object that will hold the frame from the camera&lt;/li&gt;
&lt;li&gt;Get access to the camera stream&lt;/li&gt;
&lt;li&gt;Attach it to a video element&lt;/li&gt;
&lt;li&gt;When you want to capture a precise frame, add the data from the video element
to a canvas object using &lt;code&gt;drawImage()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&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;video&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;player&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autoplay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;video&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;capture&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;Capture&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;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;canvas&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;canvas&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&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;320&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&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;240&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;canvas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; player &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;player&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canvas &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;canvas&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2d&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; captureButton &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;capture&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;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;  captureButton&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Draw the video frame to the canvas.&lt;/span&gt;&lt;br /&gt;    context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;drawImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height&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 comment&quot;&gt;// Attach the video stream to the video element and autoplay.&lt;/span&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constraints&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once you have data from the camera stored in the canvas you can do many
things with it. You could:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upload it straight to the server&lt;/li&gt;
&lt;li&gt;Store it locally&lt;/li&gt;
&lt;li&gt;Apply funky effects to the image&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tips&quot;&gt;Tips &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#tips&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;stop-streaming-from-the-camera-when-not-needed&quot;&gt;Stop streaming from the camera when not needed &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#stop-streaming-from-the-camera-when-not-needed&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It is good practice to stop using the camera when you no longer need it.
Not only will this save battery and processing power, it will also give
users confidence in your application.&lt;/p&gt;
&lt;p&gt;To stop access to the camera you can simply call &lt;code&gt;stop()&lt;/code&gt; on each video track
for the stream returned by &lt;code&gt;getUserMedia()&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;video&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;player&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autoplay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;video&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;capture&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;Capture&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;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;canvas&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&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;canvas&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&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;320&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&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;240&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;canvas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; player &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;player&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canvas &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;canvas&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2d&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; captureButton &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;capture&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;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;  captureButton&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;drawImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; canvas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Stop all video streams.&lt;/span&gt;&lt;br /&gt;    player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVideoTracks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; track&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constraints&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Attach the video stream to the video element and autoplay.&lt;/span&gt;&lt;br /&gt;    player&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;ask-permission-to-use-camera-responsibly&quot;&gt;Ask permission to use camera responsibly &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#ask-permission-to-use-camera-responsibly&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If the user has not previously granted your site access to the camera then
the instant that you call &lt;code&gt;getUserMedia()&lt;/code&gt; the browser will prompt the user to
grant your site permission to the camera.&lt;/p&gt;
&lt;p&gt;Users hate getting prompted for access to powerful devices on their machine
and they will frequently block the request, or they will ignore it if they don&#39;t
understand the context for which the prompt has been created. It is best
practice to only ask to access the camera when first needed. Once the user has
granted access they won&#39;t be asked again. However, if the user rejects access,
you can&#39;t get access again, unless they manually change camera permission
settings.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Asking for access to the camera on page load will result in most of your users rejecting access to it. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;compatibility&quot;&gt;Compatibility &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#compatibility&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;More information about mobile and desktop browser implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromestatus.com/feature/5989005896187904&quot; rel=&quot;noopener&quot;&gt;srcObject&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromestatus.com/features/5755699816562688&quot; rel=&quot;noopener&quot;&gt;navigator.mediaDevices.getUserMedia()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also recommend using the &lt;a href=&quot;https://github.com/webrtc/adapter&quot; rel=&quot;noopener&quot;&gt;adapter.js&lt;/a&gt; shim to protect apps
from WebRTC spec changes and prefix differences.&lt;/p&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/media-capturing-images/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author><author>
      <name>Mat Scales</name>
    </author>
  </entry>
  
  <entry>
    <title>Beyond the Rack</title>
    <link href="https://web.dev/beyond-the-rack/"/>
    <updated>2015-10-25T00:00:00Z</updated>
    <id>https://web.dev/beyond-the-rack/</id>
    <content type="html" mode="escaped">&lt;figure&gt;
&lt;img alt=&quot;Beyond the rack detail&quot; decoding=&quot;async&quot; height=&quot;1352&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3odtSs9WBTjfum9Kw3vC.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.beyondtherack.com/&quot; rel=&quot;noopener&quot;&gt;Beyond the Rack&lt;/a&gt; re-engages users on the
mobile web, increasing revenue per visit by 26% with push notifications.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Push notifications allowed us to bring one of the most compelling
capabilities from our native app to our mobile site. We see a direct 20%
click-through rate from push notifications—having another channel to reach
our users is a game changer.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;Richard Cohene, VP Marketing, Beyond the Rack&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;key-insights&quot;&gt;Key Insights &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#key-insights&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;52%&lt;/strong&gt; of total users are mobile web&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;26%&lt;/strong&gt; is the average increase in spend that occurred by members who visited via push&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;20%&lt;/strong&gt; click through rate from push notifications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;72%&lt;/strong&gt; more time spent on the site per visit from members who visited via push notifications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://storage.googleapis.com/web-dev-uploads/file/T4FyVKpzu4WKF1kBNvXepbi08t52/5PZRlkNq4l8Ey6swesdC.pdf&quot; rel=&quot;noopener&quot;&gt;Download PDF Case study&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;about-beyond-the-rack&quot;&gt;About Beyond the Rack &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#about-beyond-the-rack&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beyond the Rack is a leading online retailer that runs sale events of designer products
for its 14 million members globally. Until recently, the company primarily depended on
targeted, daily emails to re-engage users. Recent internal research showed that &lt;strong&gt;52%&lt;/strong&gt; of
users were visiting their site via the mobile web, so they looked for ways to improve
their mobile engagement and sales. At this point Beyond the Rack reached out to their
mobile shopping platform partner Mobify. Working with Mobify, Beyond the Rack implemented
push notifications on their mobile website and saw a &lt;strong&gt;50%&lt;/strong&gt; increase in repeat visits within
3 months. The company also found push notifications delivered higher value visits, with
members spending &lt;strong&gt;26%&lt;/strong&gt; more per visit on average.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Three steps of Push: Ask, Register, Engage&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/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4ZbI8Avq8Nhc4CZ7zQ85.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;timely,-relevant-notifications&quot;&gt;Timely, relevant notifications &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#timely,-relevant-notifications&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every day, Beyond the Rack sends emails to their members about new and exclusive sales
events. With limited sale periods—usually 48 hours—the company couldn’t rely solely on
customers checking their email to generate sales. Beyond the Rack’s new push notifications
provided a &lt;strong&gt;20%&lt;/strong&gt; click through rate which worked perfectly for flash sales alerts. The
notifications also provided Beyond the Rack with another touchpoint to interact with a
highly-engaged and commercially-valuable audience.&lt;/p&gt;
&lt;h2 id=&quot;high-attention-users-arrive-from-push-notifications&quot;&gt;High attention users arrive from push notifications &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#high-attention-users-arrive-from-push-notifications&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beyond the Rack members who visited the site via push notifications  spent &lt;strong&gt;72%&lt;/strong&gt; more
time on the site per visit and shopped more often than the average visitor. By creating
timely pushes, Beyond the Rack increased the relevance and excitement of their pushes - and
customers showed their love through higher sales.&lt;/p&gt;
&lt;h2 id=&quot;the-value-of-web-based-push-notifications-for-business&quot;&gt;The value of web-based push notifications for business &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#the-value-of-web-based-push-notifications-for-business&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;More than &lt;strong&gt;50%&lt;/strong&gt; of new members discover Beyond the Rack via the mobile web so having an
avenue to re-engage them after this initial interaction in a personalized way makes it more
than just a platform for discovery. Because push messages appear at the front of a customer’s
mobile phone home screen, they prompt greater response and more immediate action.&lt;/p&gt;
&lt;h2 id=&quot;about-push-notification&quot;&gt;About Push Notification &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#about-push-notification&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Push notifications enable your mobile web users to choose to receive notifications on their
device just like an installed native app. This lets you effectively re-engage them with customized,
compelling content.&lt;/p&gt;
&lt;h2 id=&quot;more-information&quot;&gt;More Information &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/beyond-the-rack/#more-information&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For more information on Push Notifications on the web check out our resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/web/fundamentals/getting-started/codelabs/push-notifications/&quot; rel=&quot;noopener&quot;&gt;Getting Started with your first Push Notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/notifications/&quot;&gt;Push and Notifications guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>User Location</title>
    <link href="https://web.dev/user-location/"/>
    <updated>2014-01-01T00:00:00Z</updated>
    <id>https://web.dev/user-location/</id>
    <content type="html" mode="escaped">&lt;p&gt;The Geolocation API lets you discover, with the user&#39;s consent, the user&#39;s location. You can use this functionality for things like guiding a user to their destination and geo-tagging user-created content; for example, marking where a photo was taken.&lt;/p&gt;
&lt;p&gt;The Geolocation API also lets you see where the user is and keep tabs on them as
they move around, always with the user&#39;s consent (and only while the page is open). This
creates a lot of interesting use cases, such as integrating with backend systems to prepare an order for collection if the user is close by.&lt;/p&gt;
&lt;p&gt;You need to be aware of many things when using the Geolocation API. This guide walks you through the common use cases and solutions.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; As of Chrome 50, the &lt;a href=&quot;https://web.dev/web/updates/2016/04/geolocation-on-secure-contexts-only&quot;&gt;Geolocation API only works on secure contexts (HTTPS)&lt;/a&gt;. If your site is hosted on a non-secure origin (such as &lt;code&gt;HTTP&lt;/code&gt;), any requests for the user&#39;s location &lt;strong&gt;no longer&lt;/strong&gt; function. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#summary&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use geolocation when it benefits the user.&lt;/li&gt;
&lt;li&gt;Ask for permission as a clear response to a user gesture.&lt;/li&gt;
&lt;li&gt;Use feature detection in case a user&#39;s browser doesn&#39;t support geolocation.&lt;/li&gt;
&lt;li&gt;Don&#39;t just learn how to implement geolocation; learn the best way to use geolocation.&lt;/li&gt;
&lt;li&gt;Test geolocation with your site.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;when-to-use-geolocation&quot;&gt;When to use geolocation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#when-to-use-geolocation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Find where the user is closest to a specific physical location to tailor
the user experience.&lt;/li&gt;
&lt;li&gt;Tailor information (such as news) to the user&#39;s location.&lt;/li&gt;
&lt;li&gt;Show the position of a user on a map.&lt;/li&gt;
&lt;li&gt;Tag data created inside your application with the user&#39;s location
(that is, geo-tag a picture).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ask-permission-responsibly&quot;&gt;Ask permission responsibly &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#ask-permission-responsibly&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Recent user studies &lt;a href=&quot;http://static.googleusercontent.com/media/www.google.com/en/us/intl/ALL_ALL/think/multiscreen/pdf/multi-screen-moblie-whitepaper_research-studies.pdf&quot; rel=&quot;noopener&quot;&gt;have shown&lt;/a&gt;
that users are distrustful of sites that simply prompt the user to give away their
position on page load. So what are the best practices?&lt;/p&gt;
&lt;h3 id=&quot;assume-users-will-not-give-you-their-location&quot;&gt;Assume users will not give you their location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#assume-users-will-not-give-you-their-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many of your users won&#39;t want to give you their
location, so you need to adopt a defensive development style.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Handle all errors out of the geolocation API so that you can adapt your
site to this condition.&lt;/li&gt;
&lt;li&gt;Be clear and explicit about your need for the location.&lt;/li&gt;
&lt;li&gt;Use a fallback solution if needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;use-a-fallback-if-geolocation-is-required&quot;&gt;Use a fallback if geolocation is required &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#use-a-fallback-if-geolocation-is-required&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We recommend that your site or application not require
access to the user&#39;s current location. However, if your site or application
requires the user&#39;s current location, there are third-party solutions that allow you to obtain
a best guess of where the person currently is.&lt;/p&gt;
&lt;p&gt;These solutions often work by looking at the user&#39;s IP address and mapping that
to the physical addresses registered with the RIPE database. These locations
are often not very accurate, normally giving you the position of the
telecommunications hub or cell phone tower that is nearest to the user. In many
cases, they might not even be that accurate, especially if the user is on VPN
or some other proxy service.&lt;/p&gt;
&lt;h3 id=&quot;always-request-access-to-location-on-a-user-gesture&quot;&gt;Always request access to location on a user gesture &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#always-request-access-to-location-on-a-user-gesture&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Make sure that users understand why you’re asking for their location, and what
the benefit to them will be. Asking for it immediately on the homepage as
the site loads results in a poor user experience.&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
&lt;figure&gt;
&lt;img alt=&quot;A site requesting permission on a store finder page.&quot; decoding=&quot;async&quot; height=&quot;550&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 325px) 325px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/qn1gpMoMl6ho9iXZotf9.png?auto=format&amp;w=650 650w&quot; width=&quot;325&quot; /&gt;
&lt;figcaption class=&quot;success&quot;&gt;
    &lt;b&gt;DO&lt;/b&gt;: Always request access to location on a user gesture.
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure id=&quot;fig1&quot;&gt;
&lt;img alt=&quot;A site requesting permission on the homepage.&quot; decoding=&quot;async&quot; height=&quot;550&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 325px) 325px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/IjhzpxZecuHdV0tUCIxm.png?auto=format&amp;w=650 650w&quot; width=&quot;325&quot; /&gt;
&lt;figcaption class=&quot;warning&quot;&gt;
    &lt;b&gt;DON&#39;T&lt;/b&gt;: Ask for it on the homepage, as the site loads; this results in a poor user experience.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Instead, give the user a clear call to action or an indication that
an operation will require access to their location. The user can then more easily associate the system prompt for access with the action
just initiated.&lt;/p&gt;
&lt;h3 id=&quot;give-a-clear-indication-that-an-action-will-request-their-location&quot;&gt;Give a clear indication that an action will request their location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#give-a-clear-indication-that-an-action-will-request-their-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://static.googleusercontent.com/media/www.google.com/en/us/intl/ALL_ALL/think/multiscreen/pdf/multi-screen-moblie-whitepaper_research-studies.pdf&quot; rel=&quot;noopener&quot;&gt;In a study by the Google Ads team&lt;/a&gt;,
when a user was asked to book a hotel room in Boston for an upcoming conference
on one particular hotels site, they were prompted to share their GPS location
immediately after tapping the &amp;quot;Find and Book&amp;quot; call to action on the homepage.&lt;/p&gt;
&lt;p&gt;In some cases, the user became frustrated because they didn&#39;t understand why
they were being shown hotels in San Francisco when they wanted to book a room in
Boston.&lt;/p&gt;
&lt;p&gt;A better experience is to make sure users understand why you’re asking
them for their location. Add a well-known signifier that is common across
devices, such as a range finder, or an explicit call to action such as
“Find Near Me.”&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;A range finder.&quot; decoding=&quot;async&quot; height=&quot;170&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZuaG9vfBWZTXrYR2486u.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
    &lt;figcaption&gt;
      Use a range finder
     &lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;A form with a find near me button.&quot; decoding=&quot;async&quot; height=&quot;314&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 740px) 740px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/rlGQ3rvswe4M1nhKeYw8.png?auto=format&amp;w=1480 1480w&quot; width=&quot;740&quot; /&gt;
    &lt;figcaption&gt;
      A specific call to action to find near me
    &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;h3 id=&quot;gently-nudge-users-to-grant-permission-to-their-location&quot;&gt;Gently nudge users to grant permission to their location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#gently-nudge-users-to-grant-permission-to-their-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You don&#39;t have access to anything users are doing. You know
exactly when users disallow access to their locations but you don&#39;t know
when they grant you access; you only know you obtained access when results
appear.&lt;/p&gt;
&lt;p&gt;It&#39;s good practice to &amp;quot;nudge&amp;quot; users into action if you need them to
complete the action.&lt;/p&gt;
&lt;p&gt;We recommend:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up a timer that triggers after a short period; 5 seconds is a
good value.&lt;/li&gt;
&lt;li&gt;If you get an error message, show a message to the user.&lt;/li&gt;
&lt;li&gt;If you get a positive response, disable the timer and process the results.&lt;/li&gt;
&lt;li&gt;If, after the timeout, you haven&#39;t gotten a positive response, show a
notification to the user.&lt;/li&gt;
&lt;li&gt;If the response comes in later and the notification is still present,
remove it from the screen.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onclick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; nudge &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;nudge&#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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;showNudgeBanner&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    nudge&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;block&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hideNudgeBanner&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    nudge&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;display &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; nudgeTimeoutId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;showNudgeBanner&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&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; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;hideNudgeBanner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// We have the location, don&#39;t display banner&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nudgeTimeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Do magic with location&lt;/span&gt;&lt;br /&gt;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TIMEOUT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// The user didn&#39;t accept the callout&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;showNudgeBanner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoError&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The majority of browsers now support the Geolocation API but it&#39;s a
good practice to always check for support before you do anything.&lt;/p&gt;
&lt;p&gt;You can easily check for compatibility by testing for the presence of the
geolocation object:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// check for Geolocation support&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Geolocation is supported!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Geolocation is not supported for this Browser/OS.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;determining-the-users-current-location&quot;&gt;Determining the user&#39;s current location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#determining-the-users-current-location&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Geolocation API offers a simple, &amp;quot;one-shot&amp;quot; method to obtain the user&#39;s
location: &lt;code&gt;getCurrentPosition()&lt;/code&gt;. A call to this method asynchronously
reports on the user&#39;s current location.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&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;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If this is the first time that an application on this domain has requested
permissions, the browser typically checks for user consent. Depending on
the browser, there may also be preferences to always allow—or disallow—permission lookups, in which case the confirmation process is bypassed.&lt;/p&gt;
&lt;p&gt;Depending on the location device your browser is using, the position object
might actually contain a lot more than just latitude and longitude; for
example, it might include an altitude or a direction. You can&#39;t tell what
extra information that location system uses until it actually returns
the data.&lt;/p&gt;
&lt;h2 id=&quot;watching-the-users-location&quot;&gt;Watching the user&#39;s location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#watching-the-users-location&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Geolocation API allows you to obtain the user&#39;s location (with user
consent) with a single call to &lt;code&gt;getCurrentPosition()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to continually monitor the user&#39;s location, use the Geolocation
API method, &lt;code&gt;watchPosition()&lt;/code&gt;. It operates in a similar way to
&lt;code&gt;getCurrentPosition()&lt;/code&gt;, but it fires multiple times as the positioning
software:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gets a more accurate lock on the user.&lt;/li&gt;
&lt;li&gt;Determines that the user&#39;s position is changing.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; watchId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;watchPosition&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;position&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;  document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;currentLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;currentLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;when-to-use-geolocation-to-watch-the-users-location&quot;&gt;When to use geolocation to watch the user&#39;s location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#when-to-use-geolocation-to-watch-the-users-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You want to obtain a more precise lock on the user location.&lt;/li&gt;
&lt;li&gt;Your application needs to update the user interface based on new location
information.&lt;/li&gt;
&lt;li&gt;Your application needs to update business logic when the user enters a certain
defined zone.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;best-practices-when-using-geolocation&quot;&gt;Best practices when using geolocation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#best-practices-when-using-geolocation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;always-clear-up-and-conserve-battery&quot;&gt;Always clear up and conserve battery &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#always-clear-up-and-conserve-battery&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Watching for changes to a geolocation is not a free operation. While
operating systems might be introducing platform features to let applications
hook in to the geo subsystem, you, as a web developer, have no idea what support
the user&#39;s device has for monitoring the user&#39;s location, and, while you&#39;re watching
a position, you are engaging the device in a lot of extra processing.&lt;/p&gt;
&lt;p&gt;After you no longer need to track the user&#39;s position, call &lt;code&gt;clearWatch&lt;/code&gt; to turn
off the geolocation systems.&lt;/p&gt;
&lt;h3 id=&quot;handle-errors-gracefully&quot;&gt;Handle errors gracefully &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#handle-errors-gracefully&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unfortunately, not all location lookups are successful. Perhaps a GPS could
not be located or the user has suddenly disabled location lookups. In the event of an
error, a second, optional argument to &lt;code&gt;getCurrentPosition()&lt;/code&gt; is called so that you can notify the user inside the callback:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&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;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Error occurred. Error code: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&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;// error.code can be:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   0: unknown error&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   1: permission denied&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   2: position unavailable (error response from location provider)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   3: timed out&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoError&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;reduce-the-need-to-start-geolocation-hardware&quot;&gt;Reduce the need to start geolocation hardware &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#reduce-the-need-to-start-geolocation-hardware&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For many use cases, you don&#39;t need the user&#39;s most up-to-date location;
you just need a rough estimate.&lt;/p&gt;
&lt;p&gt;Use the &lt;code&gt;maximumAge&lt;/code&gt; optional property to tell the browser to use a recently
obtained geolocation result. This not only returns more quickly if the user has
requested the data before, but it also prevents the browser from starting
its geolocation hardware interfaces such as Wifi triangulation or the GPS.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; geoOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;maximumAge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&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;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Error occurred. Error code: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&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;// error.code can be:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   0: unknown error&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   1: permission denied&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   2: position unavailable (error response from location provider)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   3: timed out&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoOptions&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;dont-keep-the-user-waiting,-set-a-timeout&quot;&gt;Don&#39;t keep the user waiting, set a timeout &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#dont-keep-the-user-waiting,-set-a-timeout&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unless you set a timeout, your request for the current position might never return.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; geoOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&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;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Error occurred. Error code: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&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;// error.code can be:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   0: unknown error&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   1: permission denied&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   2: position unavailable (error response from location provider)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   3: timed out&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoOptions&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;prefer-a-coarse-location-over-a-fine-grained-location&quot;&gt;Prefer a coarse location over a fine-grained location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#prefer-a-coarse-location-over-a-fine-grained-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you want to find the nearest store to a user, it&#39;s unlikely that you need
1-meter precision. The API is designed to give a coarse
location that returns as quickly as possible.&lt;/p&gt;
&lt;p&gt;If you do need a high level of precision, it&#39;s possible to override the default setting
with the &lt;code&gt;enableHighAccuracy&lt;/code&gt; option. Use this sparingly: it&#39;s slower
to resolve and uses more battery.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; geoOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;enableHighAccuracy&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;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; &lt;span class=&quot;token function-variable function&quot;&gt;geoSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&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;    startPos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLat&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;startLon&#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;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; startPos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;geoError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Error occurred. Error code: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&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;// error.code can be:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   0: unknown error&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   1: permission denied&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   2: position unavailable (error response from location provider)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//   3: timed out&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;geoSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; geoOptions&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;devtools&quot;&gt;Emulate geolocation with Chrome DevTools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#devtools&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt=&quot;The sensor tab in DevTools.&quot; decoding=&quot;async&quot; height=&quot;485&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/dPDCek3EhZgLQPGtEG3y0fTn4v82/eyujkgsO6S5KupD8L7Ev.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Once you&#39;ve got geolocation set up, you&#39;ll want to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test out how your app works in different geolocations.&lt;/li&gt;
&lt;li&gt;Verify that your app degrades gracefully when geolocation is not available.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can do both from Chrome DevTools.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/web/tools/chrome-devtools/#open&quot;&gt;Open Chrome DevTools&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Press &lt;kbd&gt;Esc&lt;/kbd&gt; to &lt;a href=&quot;https://web.dev/web/tools/chrome-devtools/console/#open_as_drawer&quot;&gt;Open the Console drawer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/web/tools/chrome-devtools/settings#drawer-tabs&quot;&gt;Open the Console drawer menu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Sensors&lt;/strong&gt; option to show the Sensors tab.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From here you can override the location to a preset major city,
enter a custom location, or disable geolocation by setting the override
to &lt;strong&gt;Location unavailable&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/user-location/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Touch and mouse</title>
    <link href="https://web.dev/mobile-touchandmouse/"/>
    <updated>2013-03-13T00:00:00Z</updated>
    <id>https://web.dev/mobile-touchandmouse/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For close to thirty years, desktop computing experiences have centered around a keyboard and a mouse or trackpad as our main user input devices. Over the last decade, however, smartphones and tablets have brought a new interaction paradigm: touch. With the introduction of touch-enabled Windows 8 machines, and now with the release of the awesome touch-enabled Chromebook Pixel, touch is now becoming part of the expected desktop experience. One of the biggest challenges is building experiences that work not only on touch devices and mouse devices, but also on these devices where the user will use both input methods - sometimes simultaneously!&lt;/p&gt;
&lt;p&gt;This article will help you understand how touch capabilities are built into the browser, how you can integrate this new interface mechanism into your existing apps and how touch can play nicely with mouse input.&lt;/p&gt;
&lt;h2 id=&quot;the-state-of-touch-in-the-web-platform&quot;&gt;The State of Touch in the Web Platform &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/#the-state-of-touch-in-the-web-platform&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The iPhone was the first popular platform to have dedicated touch APIs built in to the web browser.  Several other browser vendors have created similar API interfaces built to be compatible with the iOS implementation, which is now described by the &lt;a href=&quot;http://www.w3.org/TR/touch-events/&quot; rel=&quot;noopener&quot;&gt;&amp;quot;Touch Events version 1&amp;quot; specification&lt;/a&gt;. Touch events are supported by Chrome and Firefox on desktop, and by Safari on iOS and Chrome and the Android browser on Android, as well as other mobile browsers like the Blackberry browser.&lt;/p&gt;
&lt;p&gt;My colleague Boris Smus wrote a great &lt;a href=&quot;http://www.html5rocks.com/en/mobile/touch/&quot; rel=&quot;noopener&quot;&gt;HTML5Rocks tutorial on Touch events&lt;/a&gt; that is still a good way to get started if you haven’t looked at Touch events before.  In fact, if you haven’t worked with touch events before, go read that article now, before you continue.  Go on, I’ll wait.&lt;/p&gt;
&lt;p&gt;All done?  Now that you have a basic grounding in touch events, the challenge with writing touch-enabled interactions is that the touch interactions can be quite a bit different from mouse (and mouse-emulating trackpad and trackball) events - and although touch interfaces typically try to emulate mice, that emulation isn’t perfect or complete; you really need to work through both interaction styles, and may have to support each interface independently.&lt;/p&gt;
&lt;h2 id=&quot;most-importantly-the-user-may-have-touch-and-a-mouse&quot;&gt;Most Importantly: The User May Have Touch And a Mouse &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/#most-importantly-the-user-may-have-touch-and-a-mouse&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many developers have built sites that statically detect whether an environment supports touch events, and then make the assumption that they only need to support touch (and not mouse) events.  This is now a faulty assumption - instead, just because touch events are present does not mean the user is primarily using that touch input device.  Devices such as the Chromebook Pixel and some Windows 8 laptops now support BOTH Mouse and Touch input methods, and more will in the near future.  On these devices, it is quite natural for users to use both the mouse and the touch screen to interact with applications, so  &amp;quot;supports touch&amp;quot; is not the same as &amp;quot;doesn’t need mouse support.&amp;quot;  You can’t think of the problem as &amp;quot;I have to write two different interaction styles and switch between them,&amp;quot; you need to think through how both interactions will work together as well as independently.  On my Chromebook Pixel, I frequently use the trackpad, but I also reach up and touch the screen - on the same application or page, I do whatever feels most natural at the moment.  On the other hand, some touchscreen laptop users will rarely if ever use the touchscreen at all - so the presence of touch input shouldn’t disable or hinder mouse control.&lt;/p&gt;
&lt;p&gt;Unfortunately, it can be hard to know if a user’s browser environment supports touch input or not; ideally, a browser on a desktop machine would always indicate support for touch events so a touchscreen display could be attached at any time (e.g. if a touchscreen attached through a &lt;a href=&quot;http://en.wikipedia.org/wiki/KVM_switch&quot; rel=&quot;noopener&quot;&gt;KVM&lt;/a&gt; becomes available).  For all these reasons, your applications shouldn’t attempt to switch between touch and mouse - just support both!&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In IE10 on Windows 8, Microsoft introduced a new model called Pointer Events.  Pointer Events are a unification of Mouse Events and touch input, as well as other input methods such as pen input.  There is &lt;a href=&quot;http://www.w3.org/TR/2013/WD-pointerevents-20130219/&quot;&gt;work to standardize the Pointer Event model at the W3C&lt;/a&gt;, and in the short term, there are libraries out there like &lt;a href=&quot;https://github.com/toolkitchen/PointerEvents&quot;&gt;PointerEvents&lt;/a&gt; and &lt;a href=&quot;http://blogs.msdn.com/b/eternalcoding/archive/2013/01/16/hand-js-a-polyfill-for-supporting-pointer-events-on-every-browser.aspx&quot;&gt;Hand.js&lt;/a&gt; that you can use to prototype how Pointer Events could work in your code to remove some of the need to independently support mouse and touch.  For really great touch and mouse interaction, you may need to customize your user experience for mouse and touch separately, but unified event handling can make this easier in many scenarios.  However, there are significant challenges with this model - namely, it requires supporting redundant input models, and it’s not broadly supported yet - and it will take some time to settle down into a solid, cross-browser standard.  In the meantime, the best advice is to support both mouse and touch interaction models.  There are a lot of challenges with simultaneously supporting touch and mouse events, so this article explains those challenges and the strategies to overcome them.  Additionally, some of this advice is just general &amp;quot;implementing touch&amp;quot; advice, so it may be redundant if you are already used to implementing touch in a mobile context. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;supporting-mouse-and-touch-together&quot;&gt;Supporting Mouse and Touch Together &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/#supporting-mouse-and-touch-together&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;#1-clicking-and-tapping-the-natural-order-of-things&quot;&gt;#1 - Clicking and Tapping - the &amp;quot;Natural&amp;quot; Order of Things &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##1-clicking-and-tapping-the-natural-order-of-things&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first problem is that touch interfaces typically try to emulate mouse clicks - obviously, since touch interfaces need to work on applications that have only interacted with mouse events before!  You can use this as a shortcut - because &amp;quot;click&amp;quot; events will continue to be fired, whether the user clicked with a mouse or tapped their finger on the screen.  However, there are a couple of problems with this shortcut.&lt;/p&gt;
&lt;p&gt;First, you have to be careful when designing more advanced touch interactions: when the user uses a mouse it will respond via a click event, but when the user touches the screen both touch and click events will occur.  For a single click the order of events is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;touchstart&lt;/li&gt;
&lt;li&gt;touchmove&lt;/li&gt;
&lt;li&gt;touchend&lt;/li&gt;
&lt;li&gt;mouseover&lt;/li&gt;
&lt;li&gt;mousemove&lt;/li&gt;
&lt;li&gt;mousedown&lt;/li&gt;
&lt;li&gt;mouseup&lt;/li&gt;
&lt;li&gt;click&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This, of course, means that if you are processing touch events like touchstart, you need to make sure that you don’t process the corresponding mousedown and/or click event as well.  If you can cancel the touch events (call preventDefault() inside the event handler), then no mouse events will get generated for touch.  One of the most important rules of touch handlers is:&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Use preventDefault() inside touch event handlers, so the default mouse-emulation handling doesn’t occur. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;However, this also prevents other default browser behavior (like scrolling) - although usually you’re handling the touch event entirely in your handler, and you will WANT to disable the default actions.  In general, you’ll either want to handle and cancel all touch events, or avoid having a handler for that event.&lt;/p&gt;
&lt;p&gt;Secondly, when a user taps on an element in a web page on a mobile device, pages that haven’t been designed for mobile interaction have a delay of at least 300 milliseconds between the touchstart event and the processing of mouse events (mousedown). It could be done using Chrome, you can turn on &lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/mobile-emulation#emulate-touch-events&quot; rel=&quot;noopener&quot;&gt;&amp;quot;Emulate touch events&amp;quot;&lt;/a&gt; in Chrome Developer Tools to help you test touch interfaces on a non-touch system!&lt;/p&gt;
&lt;p&gt;This delay is to allow the browser time to determine if the user is performing another gesture - in particular, double-tap zooming.  Obviously, this can be problematic in cases where you want to have instantaneous response to a finger touch.  There is &lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=169642&quot; rel=&quot;noopener&quot;&gt;ongoing work&lt;/a&gt; to try to limit the scenarios in which this delay occurs automatically.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;&lt;/th&gt;
        &lt;th&gt;Chrome for Android&lt;/th&gt;
        &lt;th&gt;Android Browser&lt;/th&gt;
        &lt;th&gt;Opera Mobile for Android)&lt;/th&gt;
        &lt;th&gt;Firefox for Android&lt;/th&gt;
        &lt;th&gt;Safari iOS&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Non-scalable viewport&lt;/td&gt;
        &lt;td&gt;No delay&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;No delay&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;No Viewport&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
        &lt;td&gt;300ms&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The first and easiest way to avoid this delay is to &amp;quot;tell&amp;quot; the mobile browser that your page is not going to need zooming - which can be done using a fixed viewport, e.g. by inserting into your page:&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;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&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;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&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;width=device-width,user-scalable=no&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 isn’t always appropriate, of course - this disables pinch-zooming, which may be required for accessibility reasons, so use it sparingly if at all (if you do disable user scaling, you may want to provide some other way to increase text readability in your application).  Also, for Chrome on desktop class devices that support touch, and other browsers on mobile platforms when the page has viewports that are not scalable, &lt;a href=&quot;http://paulkinlan.github.com/touch-patterns/touch-event-order-no-viewport&quot; rel=&quot;noopener&quot;&gt;this delay does not apply.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;#2-mousemove-events-arent-fired-by-touch&quot;&gt;#2: Mousemove Events Aren’t Fired by Touch &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##2-mousemove-events-arent-fired-by-touch&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It’s important to note at this point that the emulation of mouse events in a touch interface does not typically extend to emulating mousemove events - so if you build a beautiful mouse-driven control that uses mousemove events, it probably won’t work with a touch device unless you specifically add touchmove handlers too.&lt;/p&gt;
&lt;p&gt;Browsers typically automatically implement the appropriate interaction for touch interactions on the HTML controls - so, for example, HTML5 Range controls will just work when you use touch interactions.  However, if you’ve implemented your own controls, they will likely not work on click-and-drag type interactions; in fact, some commonly used libraries (like jQueryUI) do not yet natively support touch interactions in this way (although for jQueryUI, there are several monkey-patch fixes to this issue).  This was one of the first problems I ran into when upgrading my  Web Audio Playground application to work with touch - the sliders were jQueryUI-based, so they did not work with click-and-drag interactions.  I changed over to HTML5 Range controls, and they worked.  Alternately, of course, I could have simply added touchmove handlers to update the sliders, but there’s one problem with that…&lt;/p&gt;
&lt;h3 id=&quot;#3-touchmove-and-mousemove-arent-the-same-thing&quot;&gt;#3: Touchmove and MouseMove Aren’t the Same Thing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##3-touchmove-and-mousemove-arent-the-same-thing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A pitfall I&#39;ve seen a few developers fall into is having touchmove and mousemove handlers call into the same codepaths.  The behavior of these events is very close, but subtly different - in particular, &lt;strong&gt;&lt;strong&gt;touch events always target the element where that touch STARTED, while mouse events target the element currently under the mouse cursor.&lt;/strong&gt;&lt;/strong&gt;   This is why we have mouseover and mouseout events, but there are no corresponding touchover and touchout events - only touchend.&lt;/p&gt;
&lt;p&gt;The most common way this can bite you is if you happen to remove (or relocate) the element that the user started touching. For example, imagine an image carousel with a touch handler on the entire carousel to support custom scrolling behavior. As available images change, you remove some &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements and add others. If the user happens to start touching on one of those images and then you remove it, your handler (which is on an ancestor of the img element) will just stop receiving touch events (because they’re being dispatched to a target that’s no longer in the tree) - it&#39;ll look like the user is holding their finger in one place even though they may have moved and eventually removed it.&lt;/p&gt;
&lt;p&gt;You can of course avoid this problem by avoiding removing elements that have (or have ancestors that have) touch handlers while a touch is active. Alternately, the best guidance is rather than register static touchend/touchmove handlers, wait until you get a touchstart event and then add touchmove/touchend/touchcancel handlers to the &lt;strong&gt;&lt;strong&gt;target&lt;/strong&gt;&lt;/strong&gt; of the touchstart event (and remove them on end/cancel). This way you&#39;ll continue to receive events for the touch even if the target element is moved/removed. You can play with this a little &lt;a href=&quot;http://www.rbyers.net/eventTest.html&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt; - touch the red box and while holding hit escape to remove it from the DOM.&lt;/p&gt;
&lt;h3 id=&quot;#4-touch-and-hover&quot;&gt;#4: Touch and :Hover &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##4-touch-and-hover&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The mouse pointer metaphor separated cursor position from actively selecting, and this allowed developers to use hover states to hide and show information that might be pertinent to the users.  However, most touch interfaces right now do not detect a finger &amp;quot;hovering&amp;quot; over a target - so providing semantically important information (e.g. providing &amp;quot;what is this control?&amp;quot; popup) based on hovering is a no-no, unless you also give a touch-friendly way to access this information.  You need to be careful about how you use hovering to relay information to users.&lt;/p&gt;
&lt;p&gt;Interestingly enough, though, the CSS :hover pseudoclass CAN be triggered by touch interfaces in some cases - tapping an element makes it :active while the finger is down, and it also acquires the :hover state.  (With Internet Explorer, the :hover is only in effect while the user’s finger is down - other browsers keep the :hover in effect until the next tap or mouse move.) This is a good approach to making pop-out menus work on touch interfaces - a side effect of making an element active is that the :hover state is also applied.  For example:&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;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;img ~ .content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;none&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;img:hover ~ .content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;block&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&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/awesome.png&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;&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;div&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;content&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;This is an awesome picture of me&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;div&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;Once another element is tapped the element is no longer active, and the hover state disappears, just as if the user was using a mouse pointer and moved it off the element.  You may wish to wrap the content in an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element in order to make it a tabstop as well - that way the user can toggle the extra information on a mouse hover or click, a touch tap, or a keypress, with no JavaScript required.  I was pleasantly surprised as I began work to make my &lt;a href=&quot;http://webaudioplayground.appspot.com/&quot; rel=&quot;noopener&quot;&gt;Web Audio Playground&lt;/a&gt; to work well with touch interfaces that my pop-out menus already worked well on touch, because I’d used this kind of structure!&lt;/p&gt;
&lt;p&gt;The above method works well for mouse pointer based interfaces, as well as for touch interfaces. This is in contrast to using &amp;quot;title&amp;quot; attributes on hover, which will NOT show up when the element is activated:&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;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/awesome.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&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;this doesn&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;t show up in touch&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;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Additional hover-like semantics you may wish to consider:  - Implement &amp;quot;touch and hold&amp;quot; as a &amp;quot;secondary click&amp;quot;.  On many devices - mobile and desktop alike - a touch-and-hold is already used to implement a context menu, so you shouldn’t use your own timer - listen for the oncontextmenu event, and be sure to cancel the default behavior. - Make the UI take two single touch events to complete the click - the first click will show the hover information, the second will complete the action. - If you are implementing hover effects as a way to provide help information - &amp;quot;what does this control do&amp;quot; sort of information - you may wish to just provide a &amp;quot;help mode&amp;quot; that toggles on this behavior. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;#5-touch-vs-mouse-precision&quot;&gt;#5: Touch vs. Mouse Precision &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##5-touch-vs-mouse-precision&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While mice have a conceptual disassociation from reality, it turns out that they are extremely accurate, as the underlying operating system generally tracks exact pixel precision for the cursor.  Mobile developers on the other hand have learned that finger touches on a touch screen are not as accurate, mostly because of the size of the surface area of the finger when in contact with the screen (and partly because your fingers obstruct the screen).&lt;/p&gt;
&lt;p&gt;Many individuals and companies have done extensive user research on how to design applications and sites that are accommodating of finger based interaction, and many books have been written on the topic.  The basic advice is to increase the size of the touch targets by increasing the padding, and reduce the likelihood of incorrect taps by increasing the margin between elements.  (Margins are not included in the hit detection handling of touch and click events, while padding is.)  One of the primary fixes I had to make to the Web Audio Playground was to increase the sizes of the connection points so they were more easily touched accurately.&lt;/p&gt;
&lt;p&gt;Many browser vendors who are handling touch based interfaces have also introduced logic into the browser to help target the correct element when a user touches the screen and reduce the likelihood of incorrect clicks - although this usually only corrects click events, not moves (although Internet Explorer appears to modify mousedown/mousemove/mouseup events as well).&lt;/p&gt;
&lt;h3 id=&quot;#6-keep-touch-handlers-contained,-or-theyll-jank-your-scroll&quot;&gt;#6: Keep Touch Handlers Contained, or They’ll Jank Your Scroll &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##6-keep-touch-handlers-contained,-or-theyll-jank-your-scroll&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It’s also important to keep touch handlers confined only to the elements where you need them; touch elements can be very high-bandwidth, so it’s important to avoid touch handlers on scrolling elements (as your processing may interfere with browser optimizations for fast jank-free touch scrolling - modern browsers try to scroll on a GPU thread, but this is impossible if they have to check with javascript first to see if each touch event is going to be handled by the app).  You can check out &lt;a href=&quot;http://www.rbyers.net/janky-touch-scroll.html&quot; rel=&quot;noopener&quot;&gt;an example&lt;/a&gt; of this behavior.&lt;/p&gt;
&lt;p&gt;One piece of guidance to follow to avoid this problem is to make sure that if you are only handling touch events in a small portion of your UI, you only attach touch handlers there (not, e.g., on the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; of the page); in short, limit the scope of your touch handlers as much as possible.&lt;/p&gt;
&lt;h3 id=&quot;#7-multi-touch&quot;&gt;#7: Multi-touch &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/##7-multi-touch&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The final interesting challenge is that although we’ve been referring to it as &amp;quot;Touch&amp;quot; user interface, nearly universally the support is actually for Multi-touch - that is, the APIs provide more than one touch input at a time.  As you begin to support touch in your applications, you should consider how multiple touches might affect your application.&lt;/p&gt;
&lt;p&gt;If you have been building apps primarily driven by mouse, then you are used to building with at most one cursor point - systems don’t typically support multiple mice cursors.  For many applications, you will be just mapping touch events to a single cursor interface, but most of the hardware that we have seen for desktop touch input can handle at least 2 simultaneous inputs, and most new hardware appears to support at least 5 simultaneous inputs.  For developing an &lt;a href=&quot;http://webaudiodemos.appspot.com/midi-synth/index.html&quot; rel=&quot;noopener&quot;&gt;onscreen piano keyboard&lt;/a&gt;, of course, you would want to be able to support multiple simultaneous touch inputs.&lt;/p&gt;
&lt;p&gt;The currently implemented W3C Touch APIs have no API to determine how many touch points the hardware supports, so you’ll have to use your best estimation for how many touch points your users will want - or, of course, pay attention to how many touch points you see in practice and adapt.  For example, in a piano application, if you never see more than two touch points you may want to add some &amp;quot;chords&amp;quot; UI.  The PointerEvents API  does have an API to determine the capabilities of the device.&lt;/p&gt;
&lt;h2 id=&quot;touching-up&quot;&gt;Touching Up &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mobile-touchandmouse/#touching-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hopefully this article has given you some guidance on common challenges in implementing touch alongside mouse interactions.  More important than any other advice, of course, is that you need to test your app on mobile, tablet, and combined mouse-and-touch desktop environments.  If you don’t have touch+mouse hardware, use Chrome’s &amp;quot;&lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/mobile-emulation#emulate-touch-events&quot; rel=&quot;noopener&quot;&gt;Emulate touch events&lt;/a&gt;&amp;quot; to help you test the different scenarios.&lt;/p&gt;
&lt;p&gt;It’s not only possible, but relatively easy following these pieces of guidance, to build engaging interactive experiences that work well with touch input, mouse input, and even both styles of interaction at the same time.&lt;/p&gt;
</content>
    <author>
      <name>Chris Wilson</name>
    </author><author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>Multiplayer audio fun</title>
    <link href="https://web.dev/multiplayer-audio-fun/"/>
    <updated>2011-07-01T00:00:00Z</updated>
    <id>https://web.dev/multiplayer-audio-fun/</id>
    <content type="html" mode="escaped">&lt;p&gt;Using the Web Audio API, WebSockets and a very nice designed UI here comes a &lt;a href=&quot;http://labs.dinahmoe.com/plink&quot; rel=&quot;noopener&quot;&gt;demo&lt;/a&gt; where you can generate notes on the fly and with other people in real time. We will keep posting quick updates with the demos that developers around the world make with HTML5.&lt;/p&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>3D and CSS</title>
    <link href="https://web.dev/3d-css/"/>
    <updated>2010-09-07T00:00:00Z</updated>
    <id>https://web.dev/3d-css/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a long time 3D has been the preserve of desktop applications. Recently with the introduction of advanced smart-phones that have access to native GPU acceleration we have started to see 3D used nearly everywhere.&lt;/p&gt;
&lt;p&gt;Commonly, 3D is primarily used as a device for gaming or some advanced user interfaces.  It wasn&#39;t until the introduction of Perspective transforms in WPF and Silverlight that a suitable model for applying 3D effects to user interface elements became a practical solution for application developers (after all 3D isn&#39;t exactly easy).&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.w3.org/TR/css3-3d-transforms/&quot; rel=&quot;noopener&quot;&gt;CSS 3D Transform Model&lt;/a&gt; was introduced as a Draft specification in March 2009 to allow web developers to create interesting and compelling user interfaces that take advantage of 3D by allowing application authors to apply 3D perspective transformations to any visual DOM element.&lt;/p&gt;
&lt;p&gt;The CSS 3D Transformation Working Draft is a logical extension to the &lt;a href=&quot;http://www.w3.org/TR/css3-2d-transforms&quot; rel=&quot;noopener&quot;&gt;CSS 2D Transformation Model&lt;/a&gt;, introducing some extra properties, including: perspectives, rotations and transforms in a 3D space.&lt;/p&gt;
&lt;p&gt;Never before have we been able build 3D interfaces so easily. These technologies have lowered the barrier to entry.  No longer do you have to be a mathematical whizz to build 3d elements.&lt;/p&gt;
&lt;p&gt;It must be noted that the CSS 3D module is designed to help developers build rich and visually interesting applications, it is not designed to enable you to build immersive 3d worlds.&lt;/p&gt;
&lt;h2 id=&quot;browser-support-and-hardware-acceleration&quot;&gt;Browser Support and Hardware Acceleration &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#browser-support-and-hardware-acceleration&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;webkit-perspective&quot;&gt;-webkit-perspective &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#webkit-perspective&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 36, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      36
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 16, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      16
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 9, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      9
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/perspective#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;webkit-transform-3d&quot;&gt;-webkit-transform-3d &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#webkit-transform-3d&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      2
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 49, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      49
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/-webkit-transform-3d#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The important piece of information to remember is that although a browser may &amp;quot;support&amp;quot; 3d, it may not be able to render 3D due to hardware and driver limitations.
3D scenes based on the DOM can be very computationally expensive and therefore browser vendors have decided rather than slow the browsers down with a pure software rendering solution, they instead will take advantage of GPU which might not be available on all platforms&lt;/p&gt;
&lt;h2 id=&quot;feature-detection&quot;&gt;Feature Detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#feature-detection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What about feature detection? I was hoping that you weren&#39;t going to ask!
Developers have been using tools such as Modernizr to detect support for specific browser features and abilities.  Whilst it is possible to detect the presence of support for 3D transformations, it is not possible to detect for the presence of hardware acceleration, and hardware acceleration is the key ingredient.&lt;/p&gt;
&lt;h2 id=&quot;basic-sample&quot;&gt;Basic Sample &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#basic-sample&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is nothing better than jumping straight in. In this sample we will apply a basic set of rotations of an arbitrary DOM element.&lt;/p&gt;
&lt;p&gt;We start by defining a perspective on the root element.&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;div&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&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;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-perspective&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 800&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;perspective&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 800&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100px 0 0 50px&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&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;Perspective is important because it defines how the depth of the 3D scene is rendered, values from 1-1000 will produce a very pronounced effect, and values over 1000 less so.
We then add an iframe and apply a 30 degree rotation around the Z and Y axis&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;iframe&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.html5rocks.com/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&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;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotate3d&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; 1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 30deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;iframe&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;BAM! That is it, the element is fully interactive, and in all respects it is a fully fledged DOM element (except that it now looks even cooler).
If your browser doesn&#39;t support 3D transformations, nothing will happen. You will just see a simple iframe with no rotation applied.  If your browser supports 3d transformations but without hardware acceleration, it might look a little odd.&lt;/p&gt;
&lt;h2 id=&quot;animating&quot;&gt;Animating &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#animating&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The thing that I love about CSS3 3D transformations is that it ties so beautifully with the CSS Transition module.  Animations and transitions are easy to define in CSS, and applying these to 3d is no exception.&lt;/p&gt;
&lt;p&gt;To animate elements that have a 3D perspective applied is easy.  Simply set the &amp;quot;transition&amp;quot; style to be &amp;quot;transform&amp;quot;, attach a duration and an animation function.  From then on, any change to the &amp;quot;tranform&amp;quot; style will be animated.&lt;/p&gt;
&lt;p&gt;We have re-factored the previous examples to use document styles, rather than inline styles. Not only does it clear the example up, it allows the sample to take advantage of the &lt;code&gt;:hover&lt;/code&gt; pseudo selector.  By using the &lt;code&gt;:hover&lt;/code&gt; selector, transitions can be initiated by simply moving the mouse over the element. Awesome!&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/3d-css/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was just a quick glance over some of the cool effects that can be applied to any visible DOM element using CSS 3D transformations.  There are still many things that can be done that have not been covered in this tutorial.&lt;/p&gt;
</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
  
  <entry>
    <title>A simple TODO list using HTML5 WebDatabases</title>
    <link href="https://web.dev/webdatabase-todo/"/>
    <updated>2010-02-17T00:00:00Z</updated>
    <id>https://web.dev/webdatabase-todo/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; On November 18, 2010, the &lt;a href=&quot;http://www.w3.org/TR/webdatabase/&quot;&gt;W3C announced&lt;/a&gt; that Web SQL database is a deprecated specification. This is a recommendation for web developers to no longer use the technology as effectively the spec will receive no new updates and browser vendors aren&#39;t encouraged to support this technology.  Instead, developers are encouraged to use &lt;a href=&quot;https://web.dev/indexeddb/&quot;&gt;IndexedDB&lt;/a&gt;, the replacement technology. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://dev.w3.org/html5/webdatabase&quot; rel=&quot;noopener&quot;&gt;Web Databases&lt;/a&gt; are new
in HTML5. Web Databases are hosted and persisted inside a user&#39;s browser.
By allowing developers to create applications with rich query abilities
it is envisioned that a new breed of web applications will emerge that
have the ability to work online and off-line.&lt;/p&gt;
&lt;p&gt;The example code in this article demonstrates how to create a very simple
todo list manager.  It is a very high level tour of some of the features
available in HTML5.&lt;/p&gt;
&lt;h2 id=&quot;pre-requisites&quot;&gt;Pre-requisites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#pre-requisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This sample uses a namespace to encapsulate the database logic.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; html5rocks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;asynchronous-and-transactional&quot;&gt;Asynchronous and Transactional &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#asynchronous-and-transactional&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the majority of cases where you are using Web Database
support you will be using the &lt;a href=&quot;http://dev.w3.org/html5/webdatabase/#asynchronous-database-api&quot; rel=&quot;noopener&quot;&gt;Asynchronous API&lt;/a&gt;.  The Asynchronous API
is a non-blocking system and as such will not get data
through return values, but rather will get data delivered to a defined
callback function.&lt;/p&gt;
&lt;p&gt;The Web Database support through HTML is transactional.  It is no possible to execute SQL statements outside of a transaction.
There are two types of transactions: read/write transactions (&lt;code&gt;transaction()&lt;/code&gt;) and read
only transactions (&lt;code&gt;readTransaction()&lt;/code&gt;). Please note, read/write will lock the entire database.&lt;/p&gt;
&lt;h2 id=&quot;step-1-opening-the-database&quot;&gt;Step 1. Opening the database &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-1-opening-the-database&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The database needs to be opened before it can be accessed.&lt;br /&gt;
You need to define the name, version, description and the size of the database.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; dbSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 5MB&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Todo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Todo manager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dbSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;There has been an error: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onSuccess&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; r&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;// re-render the data.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// loadTodoItems is defined in Step 4a&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllTodoItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loadTodoItems&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-2-creating-a-table&quot;&gt;Step 2. Creating a table &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-2-creating-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can only create a table by executing a CREATE TABLE SQL statemen inside a transaction.&lt;/p&gt;
&lt;p&gt;We have defined a function that will create a table in the body onload event. If the table doesn&#39;t already exist, a table will be created.&lt;/p&gt;
&lt;p&gt;The table is called todo and has 3 columns.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ID - a incrementing sequential ID column&lt;/li&gt;
&lt;li&gt;todo - a text column that is the body of the item&lt;/li&gt;
&lt;li&gt;added_on - the time that the todo item was created&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;createTable&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transaction&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;tx&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;tx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSql&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CREATE TABLE IF NOT EXISTS &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token string&quot;&gt;&quot;todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)&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;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-3-adding-data-to-a-table&quot;&gt;Step 3. Adding data to a table &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-3-adding-data-to-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We are building a todo list manager so it is pretty important that
we are able to add todo items in to the database.&lt;/p&gt;
&lt;p&gt;A transaction is created, inside the transaction an INSERT into the todo
table is performed.&lt;/p&gt;
&lt;p&gt;executeSql takes several parameters, the SQL to execute and the parameters
values to bind the query.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;addTodo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;todoText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transaction&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;tx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; addedOn &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;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;tx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSql&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;INSERT INTO todo(todo, added_on) VALUES (?,?)&quot;&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;todoText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; addedOn&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;    html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-4-selecting-data-from-a-table&quot;&gt;Step 4. Selecting data from a table &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-4-selecting-data-from-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that the data is in the database, you need a function that gets
the data back out.  In Chrome, Webdatabase&#39;s use standard SQLite SELECT queries.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;getAllTodoItems&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;renderFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transaction&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;tx&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;tx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSql&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SELECT * FROM todo&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;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; renderFunc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Note that all of these commands used in this sample
are asynchronous and as such the data is not returned from the transaction
or the executeSql call.  The results are passed through to the success
callback.&lt;/p&gt;
&lt;h2 id=&quot;step-4a-rendering-data-from-a-table&quot;&gt;Step 4a. Rendering data from a table &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-4a-rendering-data-from-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once the data has been fetched from the table, the loadTodoItems method
will be called.&lt;/p&gt;
&lt;p&gt;The onSuccess callback takes two parameters.  The first being the
transaction of the query and the second being the result set.  It is
fairly simple to iterate across the data:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadTodoItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; rowOutput &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; todoItems &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;todoItems&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;rowOutput &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rows&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;todoItems&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rowOutput&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;li&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todo &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;br /&gt;        &lt;span class=&quot;token string&quot;&gt;&quot; [&amp;lt;a href=&#39;javascript:void(0);&#39; onclick=\&#39;html5rocks.webdb.deleteTodo(&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;br /&gt;        row&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;);\&#39;&gt;Delete&amp;lt;/a&gt;]&amp;lt;/li&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The effect of this method call is that the todo list is rendered into
a DOM Element called &amp;quot;todoItems&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;step-5-deleting-data-from-a-table&quot;&gt;Step 5. Deleting data from a table &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-5-deleting-data-from-a-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;deleteTodo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transaction&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;tx&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;tx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSql&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DELETE FROM todo WHERE ID=?&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;id&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;    html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onSuccess&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;step-6-hooking-it-all-up&quot;&gt;Step 6. Hooking it all up &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webdatabase-todo/#step-6-hooking-it-all-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the page loads, open the database and create the table (if needed) and render any todo items that might already be in the database.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllTodoItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loadTodoItems&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;body onload&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;init();&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A function that takes the data out of the DOM is needed so,
call the html5rocks.webdb.addTodo method&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; todo &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;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;todo&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;html5rocks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webdb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&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;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&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;</content>
    <author>
      <name>Paul Kinlan</name>
    </author>
  </entry>
</feed>
