<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Alex Danilo on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Alex Danilo</name>
  </author>
  <link href="https://web.dev/authors/alexdanilo/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3EIOmsgE36khub8NbZgE.jpeg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Alex is a contributor to web.dev</subtitle>
  
  
  <entry>
    <title>WebAssembly Threads ready to try in Chrome 70</title>
    <link href="https://web.dev/wasm-threads/"/>
    <updated>2018-10-29T00:00:00Z</updated>
    <id>https://web.dev/wasm-threads/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; WebAssembly threads are enabled by default in Chrome 74 for desktop. The origin trial mentioned in this article ended in Chrome 75. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;WebAssembly (Wasm) enables compilation of code written in C++ and other
languages to run on the web. One very useful feature of native applications
is the ability to use threads - a primitive for parallel computation. Most C
and C++ developers would be familiar with
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/POSIX_Threads&quot; rel=&quot;noopener&quot;&gt;&lt;em&gt;pthreads&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt; which is a
standardized API for thread management in an application.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.w3.org/community/webassembly/&quot; rel=&quot;noopener&quot;&gt;WebAssembly Community Group&lt;/a&gt; has
been working on bringing threads to the web to enable real multi-threaded
applications. As part of this effort, V8 has implemented necessary support for
threads in the WebAssembly engine, available through an
&lt;a href=&quot;https://github.com/GoogleChrome/OriginTrials&quot; rel=&quot;noopener&quot;&gt;Origin Trial&lt;/a&gt;. Origin Trials
allow developers to experiment with new web features before they are fully
standardized. This allows us to gather real-world feedback from intrepid
developers, which is critical to validate and improve new features.&lt;/p&gt;
&lt;p&gt;The Chrome 70 release supports threads for WebAssembly and we encourage
interested developers to start using them and give us feedback.&lt;/p&gt;
&lt;h2 id=&quot;threads-what-about-workers&quot;&gt;Threads? What about Workers? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#threads-what-about-workers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Browsers have supported parallelism via Web Workers since 2012 in Chrome 4; in
fact it&#39;s normal to hear terms like &#39;on the main thread&#39; etc. However, Web
Workers do not share mutable data between them, instead relying on
message-passing for communication. In fact, Chrome allocates a new V8 engine
for each of them (called isolates). Isolates share neither compiled code nor
JavaScript objects, and thus they cannot share mutable data like pthreads.&lt;/p&gt;
&lt;p&gt;WebAssembly threads, on the other hand, are threads that can share the same Wasm
memory. The underlying storage of the shared memory is accomplished with a
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer&quot; rel=&quot;noopener&quot;&gt;SharedArrayBuffer&lt;/a&gt;,
a JavaScript primitive that allows sharing a single ArrayBuffer&#39;s contents
concurrently between workers. Each WebAssembly thread runs in a Web Worker, but
their shared Wasm memory allows them to work much like they do on native
platforms. This means that the applications that use Wasm threads are
responsible for managing access to the shared memory as in any traditional
threaded application. There are many existing code libraries written in C or C++
that use &lt;strong&gt;&lt;em&gt;pthreads&lt;/em&gt;&lt;/strong&gt;, and those can be compiled to Wasm and run in true
threaded mode, allowing more cores to work on the same data simultaneously.&lt;/p&gt;
&lt;h2 id=&quot;a-simple-example&quot;&gt;A simple example &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#a-simple-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s an example of a simple &#39;C&#39; program that uses threads.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Calculate Fibonacci numbers shared function&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; iterations&lt;span 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;int&lt;/span&gt;     val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;     last &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;&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;iterations &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; &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 number&quot;&gt;0&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 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;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; iterations&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;int&lt;/span&gt;     seq&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        seq &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; last&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        last &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; seq&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;return&lt;/span&gt; val&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 comment&quot;&gt;// Start function for the background thread&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bg_func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;arg&lt;span 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;int&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;iter &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 keyword&quot;&gt;void&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;arg&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;iter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;iter&lt;span 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; arg&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 comment&quot;&gt;// Foreground thread and main entry point&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;         fg_val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;54&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;int&lt;/span&gt;         bg_val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token class-name&quot;&gt;pthread_t&lt;/span&gt;   bg_thread&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;// Create the background thread&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pthread_create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;bg_thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bg_func&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;bg_val&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;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Thread create failed&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;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Calculate on the foreground thread&lt;/span&gt;&lt;br /&gt;    fg_val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fg_val&lt;span 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;// Wait for background thread to finish&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pthread_join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bg_thread&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&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;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;perror&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Thread join failed&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;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Show the result from background and foreground threads&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Fib(42) is %d, Fib(6 * 9) is %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bg_val&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fg_val&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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;That code begins with the &lt;strong&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt; function which declares 2
variables &lt;strong&gt;&lt;code&gt;fg_val&lt;/code&gt;&lt;/strong&gt; and
&lt;strong&gt;&lt;code&gt;bg_val&lt;/code&gt;&lt;/strong&gt;. There is also a function called
&lt;strong&gt;&lt;code&gt;fibonacci()&lt;/code&gt;&lt;/strong&gt;, which will be called by both of the
threads in this example. The &lt;strong&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt; function
creates a background thread using &lt;strong&gt;&lt;code&gt;pthread_create()&lt;/code&gt;&lt;/strong&gt;
whose task is to calculate the fibonacci number sequence value corresponding to
the value of the &lt;strong&gt;&lt;code&gt;bg_val&lt;/code&gt;&lt;/strong&gt; variable. Meanwhile, the
&lt;strong&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt; function running in the foreground thread
calculates it for the &lt;strong&gt;&lt;code&gt;fg_val&lt;/code&gt;&lt;/strong&gt; variable. Once the
background thread has completed running, the results are printed out.&lt;/p&gt;
&lt;h2 id=&quot;compile-for-thread-support&quot;&gt;Compile for thread support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#compile-for-thread-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, you should have the &lt;a href=&quot;https://github.com/juj/emsdk&quot; rel=&quot;noopener&quot;&gt;emscripten SDK&lt;/a&gt;
installed, preferably version 1.38.11 or later. To build our example code with
&lt;a href=&quot;https://kripken.github.io/emscripten-site/docs/porting/pthreads.html&quot; rel=&quot;noopener&quot;&gt;threads enabled&lt;/a&gt;
for running in the browser, we need to pass a couple of extra flags to the
&lt;a href=&quot;http://kripken.github.io/emscripten-site/&quot; rel=&quot;noopener&quot;&gt;emscripten&lt;/a&gt; &lt;strong&gt;&lt;em&gt;emcc&lt;/em&gt;&lt;/strong&gt; compiler. Our
command line looks like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;emcc -O2 -s &lt;span class=&quot;token assign-left variable&quot;&gt;USE_PTHREADS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; -s &lt;span class=&quot;token assign-left variable&quot;&gt;PTHREAD_POOL_SIZE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; -o test.js test.c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The command line argument &#39;&lt;code&gt;-s USE_PTHREADS=1&lt;/code&gt;&#39; turns on threading support for
the compiled WebAssembly module and the argument &#39;&lt;code&gt;-s PTHREAD_POOL_SIZE=2&lt;/code&gt;&#39;
tells the compiler to generate a pool of two (2) threads.&lt;/p&gt;
&lt;p&gt;When the program is run, under the hood it will load the WebAssembly module,
create a Web Worker for each of the threads in the thread pool, share the module
with each of the workers, in this case it&#39;s 2, and those will be used whenever a
call to &lt;strong&gt;&lt;code&gt;pthread_create()&lt;/code&gt;&lt;/strong&gt; is made. Each worker instantiates the
Wasm module with the same memory, allowing them to cooperate. V8&#39;s newest
changes in 7.0 share the compiled native code of Wasm modules that are passed
between workers, which allows even very large applications to scale to many
workers. Note, it makes sense to make sure the thread pool size is equal to the
maximum number of threads your application needs, or thread creation may fail.
At the same time, if the thread pool size is too large, you&#39;ll be creating
unnecessary Web Workers that&#39;ll sit around doing nothing but using memory.&lt;/p&gt;
&lt;h2 id=&quot;how-to-try-it-out&quot;&gt;How to try it out &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#how-to-try-it-out&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The quickest way to test out our WebAssembly module is to turn on the
experimental WebAssembly threads support in Chrome 70 onwards. Navigate to the
URL &lt;strong&gt;&lt;code&gt;about://flags&lt;/code&gt;&lt;/strong&gt; in your browser as shown below:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Chrome flags page&quot; decoding=&quot;async&quot; height=&quot;74&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 620px) 620px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AX0ONsIeZ00KYkft5CIn.png?auto=format&amp;w=1240 1240w&quot; width=&quot;620&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Next, find the experimental WebAssembly threads setting which looks like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;WebAssembly threads setting&quot; decoding=&quot;async&quot; height=&quot;114&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/J1Jud3AKlKeaki7cEZoo.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Change the setting to &lt;strong&gt;&lt;em&gt;Enabled&lt;/em&gt;&lt;/strong&gt; as shown below, then restart your browser.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;WebAssembly threads setting enabled&quot; decoding=&quot;async&quot; height=&quot;106&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/9YF7oXOYmC9AAghNrHFL.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;After the browser has restarted, we can try loading the threaded WebAssembly
module with a minimal HTML page, containing just this content:&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 doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&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;html&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;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Threads test&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;title&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;body&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 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;test.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;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;body&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;html&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;To try this page, you&#39;ll need to run some form of web server and load it from
your browser. That will cause the WebAssembly module to load and run. Opening
DevTools shows us the output from the run, and you should see something like the
output image below in the console:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Console output from fibonacci program&quot; decoding=&quot;async&quot; height=&quot;117&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 556px) 556px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/xDbn862GMbUOS2E1oNqi.png?auto=format&amp;w=1112 1112w&quot; width=&quot;556&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Our WebAssembly program with threads has executed successfully! We&#39;d encourage
you to try out your own threaded application using the steps outlined above.&lt;/p&gt;
&lt;h2 id=&quot;testing-in-the-field-with-an-origin-trial&quot;&gt;Testing in the field with an Origin Trial &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#testing-in-the-field-with-an-origin-trial&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Trying out threads by turning on experimental flags in the browser is fine for
development purposes, but if you&#39;d like to test your application out in the
field, you can do so with what&#39;s known as an
&lt;a href=&quot;https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md&quot; rel=&quot;noopener&quot;&gt;origin trial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Origin trials let you try out experimental features with your users by obtaining
a testing token that&#39;s tied to your domain. You can then deploy your app and
expect it to work in a browser that can support the feature you&#39;re testing (in
this case Chrome 70 onwards). To obtain your own token to run an origin trial,
use the application
&lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSfO0_ptFl8r8G0UFhT0xhV17eabG-erUWBDiKSRDTqEZ_9ULQ/viewform&quot; rel=&quot;noopener&quot;&gt;form here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&#39;ve hosted our simple example above using an origin trial token, so you can
&lt;a href=&quot;https://alex-wasm.appspot.com/threads/index.html&quot; rel=&quot;noopener&quot;&gt;try it out for yourself&lt;/a&gt;
without needing to build anything.&lt;/p&gt;
&lt;p&gt;If you want to see what 4 threads running in parallel can do for ASCII art, then
you must take a
&lt;a href=&quot;https://alex-wasm.appspot.com/threads/pthread.html&quot; rel=&quot;noopener&quot;&gt;look at this demo&lt;/a&gt; as well!&lt;/p&gt;
&lt;h2 id=&quot;give-us-feedback&quot;&gt;Give us feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-threads/#give-us-feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;WebAssembly threads are an extremely useful new primitive for porting
applications to the web. It&#39;s now possible to run C and C++ applications and
libraries which require &lt;strong&gt;&lt;em&gt;pthreads&lt;/em&gt;&lt;/strong&gt; support in the WebAssembly environment.&lt;/p&gt;
&lt;p&gt;We&#39;re looking for feedback from developers trying out this feature as it&#39;ll help
inform the standardization process as well as validate its usefulness. The best
way to send feedback is to
&lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/list&quot; rel=&quot;noopener&quot;&gt;report issues&lt;/a&gt; and/or get
involved with the &lt;a href=&quot;https://github.com/WebAssembly/threads&quot; rel=&quot;noopener&quot;&gt;standardization&lt;/a&gt;
process in the
&lt;a href=&quot;https://www.w3.org/community/webassembly/&quot; rel=&quot;noopener&quot;&gt;WebAssembly Community Group&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Alex Danilo</name>
    </author>
  </entry>
  
  <entry>
    <title>Extending the browser with WebAssembly</title>
    <link href="https://web.dev/wasm-av1/"/>
    <updated>2018-08-22T00:00:00Z</updated>
    <id>https://web.dev/wasm-av1/</id>
    <content type="html" mode="escaped">&lt;p&gt;One of the best things about &lt;a href=&quot;https://webassembly.org/&quot; rel=&quot;noopener&quot;&gt;WebAssembly&lt;/a&gt; is the
ability experiment with new capabilities and implement new ideas before the
browser ships those features natively (if at all). You can think of using
WebAssembly this way as a high-performance polyfill mechanism, where you
write your feature in C/C++ or Rust rather than JavaScript.&lt;/p&gt;
&lt;p&gt;With a plethora of existing code available for porting, it&#39;s possible to do
things in the browser that weren&#39;t viable until WebAssembly came along.&lt;/p&gt;
&lt;p&gt;This article will walk through an example of how to take the existing AV1
video codec source code, build a wrapper for it, and try it out inside your
browser and tips to help with building a test harness to debug the wrapper.
Full source code for the example here is available at
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1&quot; rel=&quot;noopener&quot;&gt;github.com/GoogleChromeLabs/wasm-av1&lt;/a&gt; for reference.&lt;/p&gt;
&lt;p&gt;Download one of these two 24fps test
&lt;a href=&quot;http://alex-wasm.appspot.com/av1/video/big_buck_bunny_360p24.ivf&quot; rel=&quot;noopener&quot;&gt;video&lt;/a&gt;
&lt;a href=&quot;http://alex-wasm.appspot.com/av1/video/elephants_dream_360p24.ivf&quot; rel=&quot;noopener&quot;&gt;files&lt;/a&gt;
and try them on our built &lt;a href=&quot;http://alex-wasm.appspot.com/av1/index.html&quot; rel=&quot;noopener&quot;&gt;demo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;choosing-an-interesting-code-base&quot;&gt;Choosing an interesting code-base &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#choosing-an-interesting-code-base&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a number of years now, we&#39;ve seen that a large percentage of traffic on
the web consists of video data, Cisco
&lt;a href=&quot;https://www.cisco.com/c/en/us/solutions/collateral/service-provider/visual-networking-index-vni/complete-white-paper-c11-481360.html#_Toc484813971&quot; rel=&quot;noopener&quot;&gt;estimates it&lt;/a&gt; as much as 80% in fact! Of course, browser
vendors and video sites are hugely aware of the desire to reduce the data
consumed by all this video content. The key to that, of course, is better
compression, and as you&#39;d expect there is a lot of research into
next-generation video compression aimed at reducing the data burden of shipping
video across the internet.&lt;/p&gt;
&lt;p&gt;As it happens, the &lt;a href=&quot;https://aomedia.org/&quot; rel=&quot;noopener&quot;&gt;Alliance for Open Media&lt;/a&gt; has been
working on a next generation video compression scheme called
&lt;a href=&quot;https://aomedia.org/av1-features/get-started/&quot; rel=&quot;noopener&quot;&gt;AV1&lt;/a&gt; that promises to shrink
video data size considerably. In the future, we&#39;d expect browsers to ship
native support for AV1, but luckily the source code for the compressor and
decompressor are &lt;a href=&quot;https://aomedia.googlesource.com/aom/&quot; rel=&quot;noopener&quot;&gt;open source&lt;/a&gt;, which
makes that an ideal candidate for trying to compile it into WebAssembly so
we can experiment with it in the browser.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Bunny movie image.&quot; decoding=&quot;async&quot; height=&quot;240&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 360px) 360px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Nxc2in5sTnWc8T1slk0h.png?auto=format&amp;w=720 720w&quot; width=&quot;360&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;adapting-for-use-in-the-browser&quot;&gt;Adapting for use in the browser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#adapting-for-use-in-the-browser&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the first things we need to do to get this code into the browser is to
get to know the existing code to understand what the API is like. When first
looking at this code, two things stand out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The source tree is built using a tool called &lt;code&gt;cmake&lt;/code&gt;; and&lt;/li&gt;
&lt;li&gt;There are a number of examples that all assume some kind of file-based interface.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All the examples that get built by default can be run on the command line, and
that is likely to be true in many other code bases available in the community.
So, the interface we&#39;re going to build to make it run in the browser could be
useful for many other command line tools.&lt;/p&gt;
&lt;h3 id=&quot;using-cmake-to-build-the-source-code&quot;&gt;Using &lt;code&gt;cmake&lt;/code&gt; to build the source code &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#using-cmake-to-build-the-source-code&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fortunately, the AV1 authors have been experimenting with
&lt;a href=&quot;http://kripken.github.io/emscripten-site/&quot; rel=&quot;noopener&quot;&gt;Emscripten&lt;/a&gt;, the SDK we&#39;re going to
use to build our WebAssembly version. In the root of the
&lt;a href=&quot;https://aomedia.googlesource.com/aom/+/master&quot; rel=&quot;noopener&quot;&gt;AV1 repository&lt;/a&gt;, the file
&lt;code&gt;CMakeLists.txt&lt;/code&gt;contains these build rules:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-wasm&quot;&gt;&lt;code class=&quot;language-wasm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;EMSCRIPTEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;add_preproc_definition&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_POSIX_SOURCE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;append_link_flag_to_target&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inspect&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-s TOTAL_MEMORY=402653184&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;append_link_flag_to_target&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inspect&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-s MODULARIZE=1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;append_link_flag_to_target&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inspect&quot;&lt;/span&gt;&lt;br /&gt;                            &lt;span class=&quot;token string&quot;&gt;&quot;-s EXPORT_NAME=\&quot;\&#39;DecoderModule\&#39;\&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;append_link_flag_to_target&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inspect&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--memory-init-file 0&quot;&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;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;${CMAKE_BUILD_TYPE}&quot;&lt;/span&gt; STREQUAL &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;    # Default to -O3 when no build &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; is specified.&lt;br /&gt;    append_compiler_flag&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;-O3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;endif&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;em_link_post_js&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inspect &lt;span class=&quot;token string&quot;&gt;&quot;${AOM_ROOT}/tools/inspect-post.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;endif&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 Emscripten toolchain can generate output in two formats, one is called
&lt;a href=&quot;http://asmjs.org/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;asm.js&lt;/code&gt;&lt;/a&gt; and the other is WebAssembly.
We&#39;ll be targeting WebAssembly as it produces smaller output and can run
faster. These existing build rules are meant to compile an
&lt;code&gt;asm.js&lt;/code&gt; version of the library for use in an
inspector application that&#39;s leveraged to look at the content of a video
file. For our usage, we need WebAssembly output so we add these lines just
before the closing &lt;code&gt;endif()&lt;/code&gt;statement in the
rules above.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-wasm&quot;&gt;&lt;code class=&quot;language-wasm&quot;&gt;# Force generation of Wasm instead of asm.js&lt;br /&gt;append_link_flag_to_target&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inspect&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-s WASM=1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;append_compiler_flag&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;-s WASM=1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; It&#39;s important to create a build directory that&#39;s separate from the source code tree, and run all the commands below inside that build directory. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Building with &lt;code&gt;cmake&lt;/code&gt; means first generating some
&lt;code&gt;Makefiles&lt;/code&gt; by running
&lt;code&gt;cmake&lt;/code&gt; itself, followed by running the command
&lt;code&gt;make&lt;/code&gt; which will perform the compilation step.
Note, that since we are using Emscripten we need to use the
Emscripten compiler toolchain rather than the default host compiler.
That&#39;s achieved by using &lt;code&gt;Emscripten.cmake&lt;/code&gt; which
is part of the &lt;a href=&quot;https://github.com/juj/emsdk&quot; rel=&quot;noopener&quot;&gt;Emscripten SDK&lt;/a&gt; and
passing it&#39;s path as a parameter to &lt;code&gt;cmake&lt;/code&gt; itself.
The command line below is what we use to generate the Makefiles:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cmake path/to/aom &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;br /&gt;  -DENABLE_CCACHE&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; -DAOM_TARGET_CPU&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;generic -DENABLE_DOCS&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;&lt;br /&gt;  -DCONFIG_ACCOUNTING&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; -DCONFIG_INSPECTION&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; -DCONFIG_MULTITHREAD&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;&lt;br /&gt;  -DCONFIG_RUNTIME_CPU_DETECT&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -DCONFIG_UNIT_TESTS&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;  -DCONFIG_WEBM_IO&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;&lt;br /&gt;  -DCMAKE_TOOLCHAIN_FILE&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;path/to/emsdk-portable/&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;./Emscripten.cmake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The parameter &lt;code&gt;path/to/aom&lt;/code&gt; should be set to the full path of
the location of the AV1 library source files. The
&lt;code&gt;path/to/emsdk-portable/…/Emscripten.cmake&lt;/code&gt; parameter needs
to be set to the path for the Emscripten.cmake toolchain description file.&lt;/p&gt;
&lt;p&gt;For convenience we use a shell script to locate that file:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;EMCC_LOC&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; emcc&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;EMSDK_LOC&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; $EMCC_LOC &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;s?/emscripten/[0-9.]*/emcc??&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;EMCMAKE_LOC&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; $EMSDK_LOC -name Emscripten.cmake -print&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$EMCMAKE_LOC&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you look at the top-level &lt;code&gt;Makefile&lt;/code&gt; for this project, you
can see how that script is used to configure the build.&lt;/p&gt;
&lt;p&gt;Now that all of the setup has been done, we simply call &lt;code&gt;make&lt;/code&gt;
which will build the entire source tree, including samples, but most
importantly generate &lt;code&gt;libaom.a&lt;/code&gt; which contains the
video decoder compiled and ready for us to incorporate into our project.&lt;/p&gt;
&lt;h3 id=&quot;designing-an-api-to-interface-to-the-library&quot;&gt;Designing an API to interface to the library &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#designing-an-api-to-interface-to-the-library&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once we&#39;ve built our library, we need to work out how to interface with it to
send compressed video data to it and then read back frames of video that we
can display in the browser.&lt;/p&gt;
&lt;p&gt;Taking a look inside the AV1 code tree, a good starting point is an example
video decoder which can be found in the file
&lt;code&gt;[simple_decoder.c](https://aomedia.googlesource.com/aom/+/master/examples/simple_decoder.c)&lt;/code&gt;.
That decoder reads in an &lt;a href=&quot;https://wiki.multimedia.cx/index.php/IVF&quot; rel=&quot;noopener&quot;&gt;IVF&lt;/a&gt; file
and decodes it into a series of images that represent the frames in the video.&lt;/p&gt;
&lt;p&gt;We implement our interface in the source file
&lt;code&gt;[decode-av1.c](https://github.com/GoogleChromeLabs/wasm-av1/blob/master/decode-av1.c)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since our browser can&#39;t read files from the file system, we need to design some
form of interface that lets us abstract away our I/O so that we can build
something similar to the example decoder to get data into our AV1 library.&lt;/p&gt;
&lt;p&gt;On the command line, file I/O is what&#39;s known as a stream interface, so we can
just define our own interface that looks like stream I/O and build whatever we
like in the underlying implementation.&lt;/p&gt;
&lt;p&gt;We define our interface as this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DS_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;what&lt;span 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 class-name&quot;&gt;size_t&lt;/span&gt;      &lt;span class=&quot;token function&quot;&gt;DS_read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; bytes&lt;span 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;int&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;DS_empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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;void&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;DS_close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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;// Helper function for blob support&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;DS_set_blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; len&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 &lt;code&gt;open/read/empty/close&lt;/code&gt; functions look a lot like normal
file I/O operations which allows us to map them easily onto file I/O for a
command line application, or implement them some other way when run inside
a browser. The &lt;code&gt;DATA_Source&lt;/code&gt; type is opaque from
the JavaScript side, and just serves to encapsulate the interface. Note, that
building an API that closely follows file semantics makes it easy to reuse in
many other code-bases that are intended to be  used from a command line
(e.g. diff, sed, etc.).&lt;/p&gt;
&lt;p&gt;We also need to define a helper function called &lt;code&gt;DS_set_blob&lt;/code&gt;
that binds raw binary data to our stream I/O functions. This lets the blob be
&#39;read&#39; as if it&#39;s a stream (i.e. looking like a sequentially read file).&lt;/p&gt;
&lt;p&gt;Our example implementation enables reading the passed in blob  as if it was a
sequentially read data source. The reference code can be found in the file
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1/blob/master/blob-api.c&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;blob-api.c&lt;/code&gt;&lt;/a&gt;,
and the entire implementation is just this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DATA_Source&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;void&lt;/span&gt;        &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds_Buf&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt;      ds_Len&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt;      ds_Pos&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;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;what&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    DATA_Source     &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    ds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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;ds &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&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;        &lt;span class=&quot;token function&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ds&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 keyword&quot;&gt;sizeof&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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 keyword&quot;&gt;return&lt;/span&gt; ds&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 class-name&quot;&gt;size_t&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DS_empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; buf &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&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;        &lt;span class=&quot;token keyword&quot;&gt;return&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;br /&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;bytes &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Len &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos&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;        bytes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Len &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos&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 function&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; bytes&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;int&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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; ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Len&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;void&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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;free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_set_blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Buf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    ds&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ds_Pos &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;&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;building-a-test-harness-to-test-outside-the-browser&quot;&gt;Building a test harness to test outside the browser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#building-a-test-harness-to-test-outside-the-browser&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the best practices in software engineering is to build unit tests for
code in conjunction with integration tests.&lt;/p&gt;
&lt;p&gt;When building with WebAssembly in the browser, it makes sense to build some
form of unit test for the interface to the code we&#39;re working with so we can
debug outside of the browser and also be able to test out the interface we&#39;ve
built.&lt;/p&gt;
&lt;p&gt;In this example we&#39;ve been emulating a stream based API as the interface to
the AV1 library. So, logically it makes sense to build a test harness that we
can use to build a version of our API that runs on the command line and does
actual file I/O under the hood by implementing the file I/O itself underneath
our &lt;code&gt;DATA_Source&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The stream I/O code for our test harness is straightforward, and looks like
this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;what&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &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 function&quot;&gt;fopen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;what&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rb&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 punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; bytes&lt;span 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 function&quot;&gt;fread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;,&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 punctuation&quot;&gt;)&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span 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 function&quot;&gt;feof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&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 punctuation&quot;&gt;)&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;DS_close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DATA_Source &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;fclose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&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 punctuation&quot;&gt;)&lt;/span&gt;ds&lt;span 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;By abstracting the stream interface we can build our WebAssembly module to
use binary data blobs when in the browser, and interface to real files when
we build the code to test from the command line. Our test harness code can be
found in the example source file
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1/blob/master/test.c&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;test.c&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;implementing-a-buffering-mechanism-for-multiple-video-frames&quot;&gt;Implementing a buffering mechanism for multiple video frames &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#implementing-a-buffering-mechanism-for-multiple-video-frames&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When playing back video, it&#39;s common practice to buffer a few frames to help
with smoother playback. For our purposes we&#39;ll just implement a buffer of 10
frames of video, so we&#39;ll buffer 10 frames before we start playback. Then each
time a frame is displayed, we&#39;ll try to decode another frame so we keep the
buffer full. This approach makes sure frames are available in advance to help
stop the video stuttering.&lt;/p&gt;
&lt;p&gt;With our simple example, the entire compressed video is available to read, so
the buffering isn&#39;t really needed. However, if we&#39;re to extend the source data
interface to support streaming input from a server, then we need to have the
buffering mechanism in place.&lt;/p&gt;
&lt;p&gt;The code in
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1/blob/master/decode-av1.c&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;decode-av1.c&lt;/code&gt;&lt;/a&gt;
for reading frames of video data from the AV1 library and storing in the buffer
as this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;AVX_Decoder_run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AVX_Decoder &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;ad&lt;span 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 comment&quot;&gt;// Try to decode an image from the compressed stream, and buffer&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ad&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ad_NumBuffered &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; NUM_FRAMES_BUFFERED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        ad&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ad_Image &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;aom_codec_get_frame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ad&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ad_Codec&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                                           &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;ad&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ad_Iterator&lt;span 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;ad&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;ad_Image &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&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;            &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 keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;buffer_frame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ad&lt;span 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;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;We&#39;ve chosen to make the buffer contain 10 frames of video, which is just an
arbitrary choice. Buffering more frames means more waiting time for the video
to begin playback, whilst buffering too few frames can cause stalling during
playback. In a native browser implementation, buffering of frames is far more
complex than this implementation.&lt;/p&gt;
&lt;h2 id=&quot;getting-the-video-frames-onto-the-page-with-webgl&quot;&gt;Getting the video frames onto the page with WebGL &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#getting-the-video-frames-onto-the-page-with-webgl&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The frames of video that we&#39;ve buffered need to be displayed on our page. Since
this is dynamic video content, we want to be able to do that as fast as
possible. For that, we turn to
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebGL_API&quot; rel=&quot;noopener&quot;&gt;WebGL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;WebGL lets us take an image, such as a frame of video, and use it as a texture
that gets painted on to some geometry. In the WebGL world, everything consists
of triangles. So, for our case we can use a convenient built in feature of
WebGL, called gl.TRIANGLE_FAN.&lt;/p&gt;
&lt;p&gt;However, there is a minor problem. WebGL textures are supposed to be RGB
images, one byte per color channel. The output from our AV1 decoder is images
in a so-called YUV format, where the default output has 16 bits per channel,
and also each U or V value corresponds to 4 pixels in the actual output image.
This all means we need to color convert the image before we can pass it to
WebGL for display.&lt;/p&gt;
&lt;p&gt;To do so, we implement a function &lt;code&gt;AVX_YUV_to_RGB()&lt;/code&gt; which you
can find in the source file
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1/blob/master/yuv-to-rgb.c&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;yuv-to-rgb.c&lt;/code&gt;&lt;/a&gt;.
That function converts the output from the AV1 decoder into something we can
pass to WebGL. Note, that when we call this function from JavaScript we need
to make sure that the memory we&#39;re writing the converted image into has been
allocated inside the WebAssembly module&#39;s memory - otherwise it can&#39;t get
access to it. The function to get an image out from the WebAssembly module and
paint it to the screen is this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;show_frame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;af&lt;/span&gt;&lt;span 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;rgb_image &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; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Convert The 16-bit YUV to 8-bit RGB&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; buf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_AVX_Video_Frame_get_buffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;af&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        Module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_AVX_YUV_to_RGB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rgb_image&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;WIDTH&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HEIGHT&lt;/span&gt;&lt;span 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;// Paint the image onto the canvas&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;drawImageToCanvas&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;Uint8Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HEAPU8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                rgb_image&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;WIDTH&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HEIGHT&lt;/span&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 constant&quot;&gt;WIDTH&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HEIGHT&lt;/span&gt;&lt;span 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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;drawImageToCanvas()&lt;/code&gt; function that implements the WebGL painting can be
found in the source file
&lt;a href=&quot;https://github.com/GoogleChromeLabs/wasm-av1/blob/master/draw-image.js&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;draw-image.js&lt;/code&gt;&lt;/a&gt;
for reference.&lt;/p&gt;
&lt;h2 id=&quot;future-work-and-takeaways&quot;&gt;Future work and takeaways &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#future-work-and-takeaways&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Trying our &lt;a href=&quot;http://alex-wasm.appspot.com/av1/index.html&quot; rel=&quot;noopener&quot;&gt;demo&lt;/a&gt; out on two test
&lt;a href=&quot;http://alex-wasm.appspot.com/av1/video/big_buck_bunny_360p24.ivf&quot; rel=&quot;noopener&quot;&gt;video&lt;/a&gt;
&lt;a href=&quot;http://alex-wasm.appspot.com/av1/video/elephants_dream_360p24.ivf&quot; rel=&quot;noopener&quot;&gt;files&lt;/a&gt;
(recorded as 24 f.p.s. video) teaches us a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&#39;s entirely feasible to build a complex code-base to run performantly in the browser using WebAssembly; and&lt;/li&gt;
&lt;li&gt;Something as CPU intensive as advanced video decoding is feasible via WebAssembly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are some limitations though: the implementation is all running on the
main thread and we interleave painting and video decoding on that single
thread. Offloading the decoding into a web worker could provide us with
smoother playback, as the time to decode frames is highly dependent on the
content of that frame and can sometimes take more time than we have budgeted.&lt;/p&gt;
&lt;p&gt;The compilation into WebAssembly uses the AV1 configuration for a generic CPU
type. If we compile natively on the command line for a generic CPU we see
similar CPU load to decode the video as with the WebAssembly version, however
the AV1 decoder library also includes
&lt;a href=&quot;https://en.wikipedia.org/wiki/SIMD&quot; rel=&quot;noopener&quot;&gt;SIMD&lt;/a&gt; implementations that run up to
5 times faster. The WebAssembly Community Group is currently working on
extending the standard to include
&lt;a href=&quot;https://github.com/WebAssembly/simd/blob/master/proposals/simd/SIMD.md&quot; rel=&quot;noopener&quot;&gt;SIMD primitives&lt;/a&gt;,
and when that comes along it promises to speed up decoding considerably.
When that happens, it&#39;ll be entirely feasible to decode 4k HD video in
real-time from a WebAssembly video decoder.&lt;/p&gt;
&lt;p&gt;In any case, the example code is useful as a guide to help port any existing
command line utility to run as a WebAssembly module and shows what&#39;s possible
on the web already today.&lt;/p&gt;
&lt;h2 id=&quot;credits&quot;&gt;Credits &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wasm-av1/#credits&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Thanks to Jeff Posnick, Eric Bidelman and Thomas Steiner for providing
valuable review and feedback.&lt;/p&gt;
</content>
    <author>
      <name>Alex Danilo</name>
    </author>
  </entry>
  
  <entry>
    <title>User timing API</title>
    <link href="https://web.dev/usertiming/"/>
    <updated>2014-01-21T00:00:00Z</updated>
    <id>https://web.dev/usertiming/</id>
    <content type="html" mode="escaped">&lt;p&gt;High performance web applications are crucial to a great user experience. As web applications become more and more complex, understanding performance impact is vital to creating a compelling experience. Over the past few years, a number of different APIs have appeared in the browser to help analyse performance of the network, load times, etc. but these don’t necessarily give fine-grained detail with sufficient flexibility to find what’s slowing down your application. Enter the &lt;a href=&quot;http://www.w3.org/TR/user-timing/&quot; rel=&quot;noopener&quot;&gt;User Timing API&lt;/a&gt; which provides a mechanism you can use to instrument your web application to identify where your application is spending its time. In this article we’ll cover the API plus examples of how to use it.&lt;/p&gt;
&lt;h2 id=&quot;you-cant-optimize-what-you-cant-measure&quot;&gt;You can’t optimize what you can’t measure &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#you-cant-optimize-what-you-cant-measure&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first step in speeding up a slow web application is working out where time is being spent. Measuring the time impact of areas of Javascript code is the ideal way to identify hot spots, which is the first step in finding how to improve performance. Fortunately the &lt;a href=&quot;http://www.w3.org/TR/user-timing/&quot; rel=&quot;noopener&quot;&gt;User Timing API&lt;/a&gt; provides a way that you can insert API calls at different parts of your Javascript and then extract detailed timing data that can be used to help you optimize.&lt;/p&gt;
&lt;h2 id=&quot;high-resolution-time-and-now&quot;&gt;High Resolution time and &lt;code&gt;now()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#high-resolution-time-and-now&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A fundamental part of accurate time measurement is precision. In the old days we had timing based around millisecond measurement which is OK, but building a jank-free 60 FPS site means each frame needs to be drawn in 16ms. So when you only have millisecond accuracy it lacks the precision needed for good analysis. Enter &lt;a href=&quot;http://www.w3.org/TR/hr-time/&quot; rel=&quot;noopener&quot;&gt;High Resolution Time&lt;/a&gt;, a new timing type that’s built into modern browsers. &lt;a href=&quot;http://www.w3.org/TR/hr-time/&quot; rel=&quot;noopener&quot;&gt;High Resolution Time&lt;/a&gt; gives us floating point time stamps that can be accurate to microsecond resolution - a thousand times better than before.&lt;/p&gt;
&lt;p&gt;To get the current time in your web application, call the &lt;a href=&quot;http://www.w3.org/TR/hr-time/#dom-performance-now&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;now()&lt;/code&gt;&lt;/a&gt; method which forms an &lt;a href=&quot;http://www.w3.org/TR/hr-time/#sec-extenstions-performance-interface&quot; rel=&quot;noopener&quot;&gt;extension&lt;/a&gt; of the &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#performance&quot; rel=&quot;noopener&quot;&gt;Performance&lt;/a&gt; interface. The following code shows how to do that:&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; myTime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;There is another interface called &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface&quot; rel=&quot;noopener&quot;&gt;PerformanceTiming&lt;/a&gt; which provides a number of different times related to how your web application is loaded. The &lt;code&gt;now()&lt;/code&gt; method returns the time elapsed from when the &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#dom-performancetiming-navigationstart&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigationStart&lt;/code&gt;&lt;/a&gt;time in &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface&quot; rel=&quot;noopener&quot;&gt;PerformanceTiming&lt;/a&gt; happened.&lt;/p&gt;
&lt;h3 id=&quot;the-domhighrestimestamp-type&quot;&gt;The DOMHighResTimeStamp type &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#the-domhighrestimestamp-type&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When trying to time web applications in the past you’d use something like &lt;code&gt;Date.now()&lt;/code&gt; which returns a &lt;a href=&quot;http://www.w3.org/TR/DOM-Level-3-Core/core.html#Core-DOMTimeStamp&quot; rel=&quot;noopener&quot;&gt;DOMTimeStamp&lt;/a&gt;. DOMTimeStamp returns an integer number of milliseconds as its value. In order to provide the higher accuracy needed for High Resolution time, a new type called &lt;a href=&quot;http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp&quot; rel=&quot;noopener&quot;&gt;DOMHighResTimeStamp&lt;/a&gt; was introduced. This type is a floating point value that also returns the time in milliseconds. But since it’s floating point, the value can represent fractional milliseconds, and so can yield an accuracy of one thousandth of a millisecond.&lt;/p&gt;
&lt;h2 id=&quot;the-user-timing-interface&quot;&gt;The User Timing Interface &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#the-user-timing-interface&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So now that we have high resolution time stamps, let’s use the &lt;a href=&quot;http://www.w3.org/TR/user-timing/&quot; rel=&quot;noopener&quot;&gt;User Timing&lt;/a&gt; interface to pull out timing information.&lt;/p&gt;
&lt;p&gt;The User Timing interface provides functions that let us call methods at different places in our application that can provide a Hansel and Gretel style breadcrumb trail to let us track where the time is being spent.&lt;/p&gt;
&lt;h3 id=&quot;using-mark&quot;&gt;Using &lt;code&gt;mark()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#using-mark&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.w3.org/TR/user-timing/#dom-performance-mark&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;mark()&lt;/code&gt;&lt;/a&gt; method is the main tool in our timing analysis toolkit. What &lt;code&gt;mark()&lt;/code&gt; does is store a time stamp for us. What’s super useful about &lt;code&gt;mark()&lt;/code&gt; is that we can name the time stamp, and the API will remember the name and the time stamp as a single unit.&lt;/p&gt;
&lt;p&gt;Calling &lt;code&gt;mark()&lt;/code&gt; at various places in your application lets you work out how much time it took you hit that ‘mark’ in your web application.&lt;/p&gt;
&lt;p&gt;The specification calls out a number of suggested names for marks that might be interesting and are fairly self explanatory, such as &lt;code&gt;mark_fully_loaded&lt;/code&gt;, &lt;code&gt;mark_fully_visible&lt;/code&gt;,&lt;code&gt;mark_above_the_fold&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;For example, we could set a mark for when the application is fully loaded by using the following code:&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;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark_fully_loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;By setting named marks throughout our web application we can gather a whole bunch of timing data and analyze it at our leisure to work out what the application is doing and when.&lt;/p&gt;
&lt;h3 id=&quot;calculating-measurements-with-measure&quot;&gt;Calculating measurements with &lt;code&gt;measure()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#calculating-measurements-with-measure&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once you’ve set a bunch of timing marks, you’ll want to find out the elapsed time between them. You use the &lt;a href=&quot;http://www.w3.org/TR/user-timing/#dom-performance-measure&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;measure()&lt;/code&gt;&lt;/a&gt; method to do that.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;measure()&lt;/code&gt; method calculates the elapsed time between marks, and can also measure the time between your mark and any of the well-known event names in the &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface&quot; rel=&quot;noopener&quot;&gt;PerformanceTiming&lt;/a&gt; interface.&lt;/p&gt;
&lt;p&gt;For example, you could work out the time from the DOM being complete until your application state is fully loaded by using code like:&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;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;measure_load_from_dom&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;domComplete&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mark_fully_loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In that example we are passing the well-known name &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#dom-performancetiming-domcomplete&quot;&gt;&lt;code&gt;domComplete&lt;/code&gt;&lt;/a&gt; from the &lt;a href=&quot;http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface&quot;&gt;PerformanceTiming&lt;/a&gt; interface. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;When you call &lt;code&gt;measure()&lt;/code&gt; it stores the result independent of the marks you set, so you can retrieve them later. By storing away times as your application runs, the application remains responsive, and you can dump all the data out after your application has finished some work so it can be analyzed later.&lt;/p&gt;
&lt;h3 id=&quot;discarding-marks-with-clearmarks&quot;&gt;Discarding marks with &lt;code&gt;clearMarks()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#discarding-marks-with-clearmarks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes it’s useful to be able to get rid of a bunch of marks that you’ve set up. For example, you might do batch runs on your web application and so you want to start fresh each run.&lt;/p&gt;
&lt;p&gt;It’s easy enough to get rid of any marks you’ve set up by calling &lt;a href=&quot;http://www.w3.org/TR/user-timing/#dom-performance-clearmarks&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;clearMarks()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So the example code below would blow away all the existing marks you have, so that you can set up a timing run again if you want.&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;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearMarks&lt;/span&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;Of course, there are some scenarios where you might not want to clear all of your marks. So if you want to get rid of specific marks, you can just pass the name of the mark you want to remove. For example, the code below:&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;peformance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearMarks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark_fully_loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;gets rid of the mark we set in the first example while leaving any other marks we set unchanged.&lt;/p&gt;
&lt;p&gt;You might want to get rid of any measures you’ve made as well, and there’s a corresponding method to do that called &lt;a href=&quot;http://www.w3.org/TR/user-timing/#dom-performance-clearmeasures&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;clearMeasures()&lt;/code&gt;&lt;/a&gt;. It works exactly the same as &lt;code&gt;clearMarks()&lt;/code&gt; does, but instead working on any measurements you’ve made. For example, the code:&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;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearMeasures&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;measure_load_from_dom&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;will remove the measure we made in the above &lt;code&gt;measure()&lt;/code&gt; example. If you want to remove all measures, it works just the same as &lt;code&gt;clearMarks()&lt;/code&gt; - in that you just call &lt;code&gt;clearMeasures()&lt;/code&gt; without arguments.&lt;/p&gt;
&lt;h2 id=&quot;getting-the-timing-data-out&quot;&gt;Getting the timing data out &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#getting-the-timing-data-out&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s all well and good to set marks and measure intervals, but at some point you want to get at that timing data to perform some analysis. This is really simple too, all you have to do is use the &lt;a href=&quot;http://www.w3.org/TR/performance-timeline/#sec-performance-timeline&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PerformanceTimeline&lt;/code&gt;&lt;/a&gt; interface.&lt;/p&gt;
&lt;p&gt;For example, the &lt;a href=&quot;http://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbytype&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getEntriesByType()&lt;/code&gt;&lt;/a&gt; method lets us get all our mark times, or all of our measure times out as a list so we can iterate over it and digest the data. What’s nice is that the list gets returned in chronological order, so you can see the marks in the order they were hit in your web application.&lt;/p&gt;
&lt;p&gt;The code below:&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; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEntriesByType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;returns us a list of all the marks that have been hit in our web application, whilst the code:&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; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEntriesByType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;measure&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;returns us a list of all the measures we’ve made.&lt;/p&gt;
&lt;p&gt;You can also get back a list of entries by using the &lt;a href=&quot;http://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbyname&quot; rel=&quot;noopener&quot;&gt;specific name&lt;/a&gt; you’ve given them. So for example, the code:&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; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEntriesByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark_fully_loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;would return us a list with one item in it containing the ‘mark_fully_loaded’ time stamp in the &lt;a href=&quot;http://www.w3.org/TR/performance-timeline/#dom-performanceentry-starttime&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;startTime&lt;/code&gt;&lt;/a&gt; property.&lt;/p&gt;
&lt;h2 id=&quot;timing-an-xhr-request-example&quot;&gt;Timing an XHR request (example) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#timing-an-xhr-request-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we have a decent picture of the User Timing API we can use it to analyze how long all our &lt;a href=&quot;http://www.w3.org/TR/XMLHttpRequest/&quot; rel=&quot;noopener&quot;&gt;XMLHttpRequests&lt;/a&gt; take in our web application.&lt;/p&gt;
&lt;p&gt;First we’ll modify all of our &lt;a href=&quot;http://www.w3.org/TR/XMLHttpRequest/#the-send()-method&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;send()&lt;/code&gt;&lt;/a&gt; requests to issue a function call that sets up the marks, and at the same time change our success callbacks with a function call that sets another mark and then generates a measure of how long the request took.&lt;/p&gt;
&lt;p&gt;So normally our XMLHttpRequest would look something like:&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; myReq &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;XMLHttpRequest&lt;/span&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;myReq&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 string&quot;&gt;&#39;GET&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;myReq&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 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 function&quot;&gt;do_something&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;responseText&lt;span 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;myReq&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&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;For our example we’ll add a global counter to track the number of requests and also to use it to store a measure for each request that’s made. The code to do this looks like:&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; reqCnt &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;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myReq &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;XMLHttpRequest&lt;/span&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;myReq&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 string&quot;&gt;&#39;GET&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;myReq&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 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;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark_end_xhr&#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;  reqCnt&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;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;measure_xhr_&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; reqCnt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mark_start_xhr&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mark_end_xhr&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;do_something&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;responseText&lt;span 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;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;mark_start_xhr&#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;myReq&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&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;The code above generates a measure with a unique name value for every XMLHttpRequest we send. We’re assuming the requests run in sequence - the code for parallel requests would need to be a bit more complex to handle requests that return out of order, we’ll leave that as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;Once the web application has done a bunch of requests we could dump them all to the console using the code below:&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; items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEntriesByType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;measure&#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;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;amp;&lt;/span&gt;lt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&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;var&lt;/span&gt; req &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&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;  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;XHR &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39; took &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;duration &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ms&#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;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/usertiming/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The User Timing API gives you a lot of great tools to apply to any aspect of your web application. Narrowing down the hot-spots in your application can be easily achieved by sprinkling API calls throughout your web application and post-processing the timing data generated to create a clear picture of where time is being spent. But what if your browser doesn’t support this API? No problem, you can find a &lt;a href=&quot;https://gist.github.com/pmeenan/5902672&quot; rel=&quot;noopener&quot;&gt;great polyfill here&lt;/a&gt; that emulates the API really well and plays nicely with &lt;a href=&quot;http://www.webpagetest.org/&quot; rel=&quot;noopener&quot;&gt;webpagetest.org&lt;/a&gt; as well. So what are you waiting for? Try out the User Timing API on your applications now, you’ll work out how to speed them up and your users will thank you for making their experience so much better.&lt;/p&gt;
</content>
    <author>
      <name>Alex Danilo</name>
    </author>
  </entry>
  
  <entry>
    <title>Splash vector graphics on your responsive site</title>
    <link href="https://web.dev/svg-mobile-fundamentals/"/>
    <updated>2012-10-15T00:00:00Z</updated>
    <id>https://web.dev/svg-mobile-fundamentals/</id>
    <content type="html" mode="escaped">&lt;p&gt;Creating mobile content that dazzles means balancing the amount of data downloaded against maximal visual impact.
Vector graphics are a great way to deliver stunning visual results using minimal bandwidth.&lt;/p&gt;
&lt;p&gt;Many people think of canvas as the only way to draw a mixture of vectors and rasters on the web, but there are alternatives that have some advantages.
A great way to achieve vector drawing is through the use of &lt;a href=&quot;http://www.w3.org/TR/SVG/&quot; rel=&quot;noopener&quot;&gt;Scalable Vector Graphics (SVG)&lt;/a&gt; which is a key part of &lt;a href=&quot;http://dev.w3.org/html5/spec/single-page.html&quot; rel=&quot;noopener&quot;&gt;HTML5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We all know responsive design is a big part of handling varying screen sizes, and SVG is ideal for handling different size screens with ease.&lt;/p&gt;
&lt;p&gt;SVG is a great way to present vector based line drawings and is a great complement to bitmaps,  the latter being better suited for continuous tone images.&lt;/p&gt;
&lt;p&gt;One of the most useful things about SVG is that it’s resolution independent, meaning that you don’t need to think about how many pixels you have on your device, the result will always scale and be optimized by the browser to look great.&lt;/p&gt;
&lt;p&gt;Popular authoring tools like the Drawing application in Google Drive, Inkscape, Illustrator, Corel Draw and lots of others generate SVG so there are lots of ways to generate content.
We&#39;ll dive into some ways to use SVG assets, plus some optimization tips to get you going.&lt;/p&gt;
&lt;h2 id=&quot;scaling-fundamentals&quot;&gt;Scaling fundamentals &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#scaling-fundamentals&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s start with a simple scenario - you want a full page graphic to be the background of your web page.
It&#39;d be really useful to have your company logo, or anything like that full-screen in the background at all
times, but of course that&#39;s super hard to do nicely with all the different screen sizes out there.
So to illustrate, we&#39;ll start with the humble HTML5 logo.&lt;/p&gt;
&lt;p&gt;The HTML5 logo is shown below - and you guessed it, it originates as an SVG file.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;HTML5 logo&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PHOLckhUWFre4i5MMKA7.svg&quot; width=&quot;150&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Click on the logo and take a look at it in any modern browser and you&#39;ll see that it scales beautifully to any size window.
Try opening it up in your favorite browser, resize the window and observe that the image is crisp at any magnification.
If we were to try that with a bitmap image, we&#39;d either have to serve many different sizes for each screen we could encounter,
or be forced to put up with horribly pixelated scaled images.&lt;/p&gt;
&lt;p&gt;So what&#39;s the big deal?
Well if you hadn&#39;t noticed, this is the only format that scales independently of the device we&#39;re using to look at it with.
So we only need to serve one asset to our users, without ever needing to know what their screen or window size is - neat!&lt;/p&gt;
&lt;p&gt;But wait, there&#39;s more - the HTML5 logo is just 1427 bytes! Yikes, that&#39;s so small that it will hardly dent any mobile
data plan when loading it, which makes it fast to load and that makes it cheap and fast for your users!&lt;/p&gt;
&lt;p&gt;Another nice thing about SVG files is that they can be GZIP compressed to further shrink them.
When you compress SVG that way, the file extension has to be changed to ‘.svgz’.
In the case of the HTML5 logo, it shrinks to just 663 bytes when compressed - and most modern browsers handle it with ease!&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; Note, some browsers can load the GZIP files OK but fail on loading via the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag. Luckily HTTP can use GZIP compression so setting up the web server properly may be a better way to take advantage of GZIP compression. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;With our example file on some of the latest devices we see something like a 60x advantage using compressed vector data!
Also, note that these comparisons are being made between the JPEG and the SVG, rather than PNG.
However, the JPEG is a lossy format which results in lower quality than either the SVG or PNG. If we were to use PNG, the advantage would be over 80x which is astounding!&lt;/p&gt;
&lt;p&gt;But of course PNG and JPEG are not created equal. A number of optimization tips tell you to use JPEG instead of PNG, but that&#39;s not always such a great idea.
Take a look at the images below. The image on the left is a PNG image of the top right part of the HTML5 logo enlarged 6x.
The image on the right is the same thing but encoded with JPEG.&lt;/p&gt;
&lt;div&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;PNG image&quot; decoding=&quot;async&quot; height=&quot;396&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 222px) 222px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/24hKDdM72OrvlnXaeSh7.jpg?auto=format&amp;w=444 444w&quot; width=&quot;222&quot; /&gt;
    &lt;figcaption&gt;PNG image&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;JPEG image&amp;lt;&quot; decoding=&quot;async&quot; height=&quot;395&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 222px) 222px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/UtI3HHIRcc9Q9bwIvWcU.jpg?auto=format&amp;w=444 444w&quot; width=&quot;222&quot; /&gt;
    &lt;figcaption&gt;JPEG image&lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;It&#39;s easy to see that the file size saving in JPEG comes at a cost, with color artifacts at the sharp edges - probably making your retina think it needs glasses:-)
To be fair, JPEG is optimized for photos, and that&#39;s why it&#39;s not as good for vector art.
In any case, the SVG version is the same as the PNG in quality so wins on all accounts - both file size and clarity.&lt;/p&gt;
&lt;h2 id=&quot;making-vector-backgrounds&quot;&gt;Making Vector Backgrounds &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#making-vector-backgrounds&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Lets take a look at how you could use a vector file as the background of a page.
One easy way is to declare your background file using CSS fixed positioning:&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;#bg&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;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;fixed&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/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;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;HTML5-logo.svgz&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;bg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&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;HTML5 logo&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;pre&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;You&#39;ll notice that no matter what the size of the display, the image is sized nicely with crisp clean
edges.&lt;/p&gt;
&lt;p&gt;Then of course, we&#39;d like to put some content over the background.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Logo with background&quot; decoding=&quot;async&quot; height=&quot;472&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 389px) 389px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/s3jQUknkm4nuNUs7YYmV.jpg?auto=format&amp;w=778 778w&quot; width=&quot;389&quot; /&gt; 
&lt;/figure&gt;
&lt;p&gt;But as you can see, the result is less than ideal since we can&#39;t read the text. So what do we do?&lt;/p&gt;
&lt;h3 id=&quot;adjusting-the-background-to-look-nicer&quot;&gt;Adjusting the background to look nicer &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#adjusting-the-background-to-look-nicer&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The obvious thing we need to do is make all the color in the background image be lighter.
This is easily achieved by use of the CSS opacity property - or using opacity in the SVG file itself.
You could make this work by simply adding this code to your CSS content:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#bg&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;opacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.2&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;That would give you a result like so:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Adjusting the background to look nicer&quot; decoding=&quot;async&quot; height=&quot;479&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 389px) 389px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/avJfWjXTTabg2Na6npTv.jpg?auto=format&amp;w=778 778w&quot; width=&quot;389&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;This solution whilst easy, is likely to be a performance pain point on a mobile device.
For most existing mobile browsers, use of the opacity property can be a lot slower to draw with compared with opaque objects.&lt;/p&gt;
&lt;h3 id=&quot;a-better-solution&quot;&gt;A better solution &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#a-better-solution&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Modifying the color in the original SVG content is far better than setting opacity with CSS.
Here is our HTML5 logo modified to look faded out by changing the colors used, and in the process avoiding the opacity property altogether. So the background image below looks identical to the result from changing the opacity, but will actually paint a lot
faster and save us CPU time and save precious battery life in the process.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Logo faded&quot; decoding=&quot;async&quot; height=&quot;506&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 407px) 407px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WM48VBQG4c6Fu7YMYSGw.jpg?auto=format&amp;w=814 814w&quot; width=&quot;407&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;So now we have a decent grasp of some fundamentals, let&#39;s move on to some other features.&lt;/p&gt;
&lt;h2 id=&quot;using-gradients-efficiently&quot;&gt;Using Gradients Efficiently &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#using-gradients-efficiently&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s say we want to build a button.
We could start by creating a rectangle with nice rounded corners.
Then we could add a nice linear gradient to give the button some nice texture. The code to do so could look something like:&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;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&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.w3.org/2000/svg&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;defs&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;linearGradient&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;blueshiny&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#a0caf6&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#1579df&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.5&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#1675d6&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.5&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#115ca9&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;1&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;linearGradient&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;defs&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;g&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;button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&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 javascript language-javascript&quot;&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;&#39;ouch!&#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&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;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;rect&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&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;url(#blueshiny)&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;198&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;83&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;x&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;3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y&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;4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rx&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;15&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;text&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;x&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;100&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y&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;55&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&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;white&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;font-size&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;18pt&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;text-anchor&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;middle&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;Press 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;text&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;g&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;svg&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 resultant button would end up with something like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Glossy button&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iUW3UQQ68xBRBnuDpoy7.svg&quot; width=&quot;300&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Notice how the gradient we&#39;ve added goes from left to right. This is the default gradient direction in SVG.
But we can do better, for a couple of different reasons: aesthetics and performance.
Let&#39;s try to change the gradient direction to make it look a bit nicer.
Setting the &#39;x1&#39;, &#39;y1&#39;, &#39;x2&#39;, and &#39;y2&#39; attributes on the linear gradient controls the direction of the fill color.&lt;/p&gt;
&lt;p&gt;Setting just the &#39;y2&#39; attribute lets us change the gradient to be diagonal. So this small code change:&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;linearGradient&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;blueshiny&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y2&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;1&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;gives us a different look for our button, it ends up looking like the image below.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Glossy button slanted&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/OVXIEosmvAlrlYjnHLMn.svg&quot; width=&quot;300&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;We can also easily change the gradient to go from top to bottom with this small code change:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&amp;lt;linearGradient id=&lt;span class=&quot;token string&quot;&gt;&quot;blueshiny&quot;&lt;/span&gt; x2=&lt;span class=&quot;token string&quot;&gt;&quot;0&quot;&lt;/span&gt; y2=&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;and that ends up looking like the image below.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Glossy button vertical&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/Gyr2cmK5eAA4776Zdbjb.svg&quot; width=&quot;300&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;So what&#39;s with all the discussion about different angles of the gradient I hear you ask?&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; Tip: use top to bottom gradients for better performance. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Well it turns out that the last example - the one with the gradient running from top to bottom is the fastest to draw on most devices.
It&#39;s a very little known secret amongst the graphic geeks who write browser code that vertical (top to bottom) gradients paint almost as fast as a solid color. (The reason is that painting an object is done in horizontal lines down the page - and the guts of the
drawing code understand that the color doesn&#39;t change across each line, and so they optimize it).&lt;/p&gt;
&lt;p&gt;So when you choose to use gradients in your page design, vertical gradients will be faster and use less battery as a side effect.
This speedup applies to CSS gradients as well, so it&#39;s not just an SVG thing.&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; Note, that radial gradients should be avoided unless you know they&#39;ll be hardware accelerated - in software they are painfully slow. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;If we feel really adventurous with this new gradient knowledge, then we can perhaps add a cool gradient behind our HTML5 logo by adding the code below:&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;defs&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;linearGradient&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;grad1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;x2&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;0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y2&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;1&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FBE6FB&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#CCCCFF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.2&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#CCFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.4&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.6&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFEDCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.8&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFCCCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;1&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;linearGradient&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;defs&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;rect&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;x&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;-200&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y&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;-160&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;910&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;830&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&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;url(#grad1)&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;pre&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 code above adds a faded vertical linear gradient to the backgound of our HTML5 logo to give a subtle multi-color tinge that runs fast - as fast as a solid color background.&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; Note, also that the choice of the size of the background rectangle guarantees the color fills the screens on all of our mobile devices listed at the start of this article (their screen aspect ratios range from 10/16 through 18/10). &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;If you load the content in a desktop browser and resize to extreme aspect ratios, you&#39;ll see white bars appear at the top/bottom or left/right sides.
Anyway, after the code changes made above the resultant background will look like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Logo faded with gradient&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/E8XOmVLuBskwOwa4E7Hm.svg&quot; width=&quot;150&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;animate-with-ease&quot;&gt;Animate With Ease &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#animate-with-ease&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By now you might be wondering what&#39;s the point of using an SVG gradient as the backdrop for your page.
Indeed it might make sense to do that with CSS gradients, but one advantage of SVG is that the gradient itself lives in the DOM.
This means that you can modify it with script, but more importantly you can take advantage of SVG&#39;s built in animation capability to add subtle changes to your content.&lt;/p&gt;
&lt;p&gt;As an example, we&#39;ll modify our colorful HTML5 logo by changing the linear gradient definition to the code below:&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;linearGradient&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;grad1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;x2&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;0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;y2&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;1&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FBE6FB&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#FBE6FB;#CCCCFF;#CCFFCC;#FFFFCC;#FFEDCC;#FFCCCC;#FBE6FB&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#CCCCFF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.2&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#CCCCFF;#CCFFCC;#FFFFCC;#FFEDCC;#FFCCCC;#FBE6FB;#CCCCFF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#CCFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.4&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#CCFFCC;#FFFFCC;#FFEDCC;#FFCCCC;#FBE6FB;#CCCCFF;#CCFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.6&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#FFFFCC;#FFEDCC;#FFCCCC;#FBE6FB;#CCCCFF;#CCFFCC;#FFFFCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFEDCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;0.8&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#FFEDCC;#FFCCCC;#FBE6FB;#CCCCFF;#CCFFCC;#FFFFCC;#FFEDCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;stop&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stop-color&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;#FFCCCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&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;1&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;animate&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;attributeName&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-color&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;values&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;#FFCCCC;#FBE6FB;#CCCCFF;#CCFFCC;#FFFFCC;#FFEDCC;#FFCCCC&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token attr-name&quot;&gt;begin&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;0s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;dur&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;20s&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;repeatCount&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;indefinite&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;stop&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;linearGradient&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;Take a look at the image below to see the result of these changes above.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Linear gradient&quot; decoding=&quot;async&quot; height=&quot;150&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/z5zMKZqHVIkfz3JyVJFi.svg&quot; width=&quot;150&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The code is changing the colors of our linear gradient through all the different color stops we&#39;ve defined
in a continuous cycle that takes 20 seconds to run. The effect of that is that the gradient looks like it&#39;s moving up
the page in a continuous motion that never stops.&lt;/p&gt;
&lt;p&gt;The beauty of this is that there&#39;s no script required!
That&#39;s why it runs as a referenced image from this page, but also it reduces workload on a mobile CPU by removing the need for script.&lt;/p&gt;
&lt;p&gt;Also, the browser itself can take advantage of its knowledge of the painting to ensure minimal CPU overhead is used to do the fancy animation.&lt;/p&gt;
&lt;p&gt;There is one caveat: some browsers don&#39;t handle this style of animation at all, but in that case you&#39;ll still get a nice
colored background but it just won&#39;t change - this could be worked around by using script (and &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/speed/animations/&quot; rel=&quot;noopener&quot;&gt;requestAnimationFrame&lt;/a&gt;) but that&#39;s a bit beyond this article.&lt;/p&gt;
&lt;p&gt;One more thing to note, is that this uncompressed SVG file is only 2922 bytes - incredibly small to supply such a rich graphics effect, keeping your users and those data plans happy in the process.&lt;/p&gt;
&lt;h2 id=&quot;where-to-from-here&quot;&gt;Where to from here? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#where-to-from-here&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many cases where SVG is less than ideal, photos and videos being better represented in other formats.
Text is another one, where native HTML and CSS work much better in general.
However, as a tool in the arsenal for line drawn artwork it can be the ideal choice.&lt;/p&gt;
&lt;p&gt;We&#39;ve touched on a few basic fundamental uses for SVG graphics, showing how easy it is to generate tiny content that provides
full screen vivid graphics with a minimal amount of download. Small enhancements to the content can create amazing
graphical results easily with trivial amounts of markup. In the next article we&#39;ll explore some more details about how the animation
built into SVG can be used for more simple and powerful effects and compare the use of canvas with SVG to choose the right
tool for authoring your mobile graphics site.&lt;/p&gt;
&lt;h2 id=&quot;other-good-resources&quot;&gt;Other good resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/svg-mobile-fundamentals/#other-good-resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://inkscape.org/&quot; rel=&quot;noopener&quot;&gt;Inkscape&lt;/a&gt; an open source drawing application that uses SVG as its file format.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://openclipart.org/&quot; rel=&quot;noopener&quot;&gt;Open Clip Art&lt;/a&gt; a huge open source clip art library containing thousands of SVG images.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3.org/Graphics/SVG/&quot; rel=&quot;noopener&quot;&gt;W3C SVG Page&lt;/a&gt; containing links to specifications, resources, etc.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raphaeljs.com/&quot; rel=&quot;noopener&quot;&gt;Raphaël&lt;/a&gt; a Javascript library that provides a convenient API to draw and animate SVG content with great fallback for older browsers.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://srufaculty.sru.edu/david.dailey/svg/&quot; rel=&quot;noopener&quot;&gt;SVG Resources&lt;/a&gt; from Slippery Rock University - includes a link to a great &lt;a href=&quot;http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html&quot; rel=&quot;noopener&quot;&gt;SVG Primer&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Alex Danilo</name>
    </author>
  </entry>
  
  <entry>
    <title>Understanding CSS filter effects</title>
    <link href="https://web.dev/understanding-css/"/>
    <updated>2012-05-25T00:00:00Z</updated>
    <id>https://web.dev/understanding-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/understanding-css/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Filters are a powerful tool that web authors can use to achieve interesting visual effects. In this article we’ll cover the history of filter effects, what they do and how to use them. We’ll cover examples of all the predefined filters defined for CSS with some examples. We’ll also cover performance considerations for using them on desktop and mobile devices since knowing the speed impact of filters is important for a good user experience. Finally we’ll review the current state of implementation in modern browsers.&lt;/p&gt;
&lt;h2 id=&quot;the-past,-present-and-future-of-filter-effects&quot;&gt;The past, present and future of filter effects &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#the-past,-present-and-future-of-filter-effects&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Filter effects originated as part of the Scalable Vector Graphics (SVG) specification. They were created to apply a number of different pixel based image effects to a vector drawing. Over time as browser vendors added SVG capabilities into their browsers, the usefulness of filters became evident. Robert O’Callahan from Mozilla came up with
&lt;a href=&quot;http://robert.ocallahan.org/2008/06/applying-svg-effects-to-html-content_04.html&quot; rel=&quot;noopener&quot;&gt;the brilliant idea&lt;/a&gt; of using SVG filters through the application of CSS to ‘normal’ HTML content. Robert prototyped an early version that showed how powerful the combination of filters and CSS styling could be. The CSS and SVG working groups in the W3C decided to harmonize the use of filters for both HTML and SVG via CSS styling, and thus the ‘filter’ property for CSS was born. Right now a joint task force of people working on CSS and SVG is doing a ton of work to make filters universally useful. You can find the current specification for all this stuff &lt;a href=&quot;http://dev.w3.org/fxtf/filters&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-new-life-for-the-filter-css-property&quot;&gt;A new life for the ‘filter’ CSS property &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#a-new-life-for-the-filter-css-property&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Deja Vu sometimes strikes a web developer when seeing ‘filter’ in CSS styles. This is due to the fact that old versions of Internet Explorer had a ‘filter’ property exposed via CSS to perform some platform specific functionality. This has been &lt;a href=&quot;http://www.fred.net/dhark/demos/css/css_filter_examples.html&quot; rel=&quot;noopener&quot;&gt;deprecated&lt;/a&gt;
in favor of the standard ‘filter’ property which is now part of CSS3. So when you see ‘filter’ out in the wild on some old web pages, there’s no need to be confused. The new ‘filter’ property is where all the action is, and new versions of IE are implementing it just the same as all modern browsers.&lt;/p&gt;
&lt;h2 id=&quot;how-filters-work&quot;&gt;How filters work &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#how-filters-work&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what does a filter do exactly? The easiest way to think of a filter is as a post processing step that does something magical after all your page content has been laid out and drawn.&lt;/p&gt;
&lt;p&gt;When a browser loads a web page it needs to apply styles, perform layout and then render the page so there&#39;s something to look at. Filters kick in after all those steps and just before the page is copied to the screen. What they do is take a snapshot of the rendered page as a bitmap image, then perform some graphics magic on the pixels in the snapshot and then draw the result over the top of the original page image. One way to think of them is like a filter placed on the front of a camera lens. What you’re seeing through the lens is the outside world modified by the effect of the filter.&lt;/p&gt;
&lt;p&gt;This of course means that there&#39;s time consumed when drawing a page with filters on it, but using them properly will have minimal impact on the speed of your site.&lt;/p&gt;
&lt;p&gt;Also, just as you can stack a number of filters in front of each other on your camera lens, you can apply an arbitrary number of filters one after the other to achieve all sorts of effects.&lt;/p&gt;
&lt;h2 id=&quot;filters-defined-using-svg-and-css&quot;&gt;Filters defined using SVG and CSS &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#filters-defined-using-svg-and-css&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since filters originally came from SVG there are different ways to define and use them. SVG itself has a &lt;code&gt;&amp;lt;filter&amp;gt;&lt;/code&gt; element that wraps up definitions of various filter effects using XML syntax. The set of filters defined by CSS take advantage of the same graphics model, but they are much simpler definitions that are easy to use in a style sheet.&lt;/p&gt;
&lt;p&gt;Most of the CSS filters can be expressed in terms of SVG filters, and CSS also allows you to reference a filter specified in SVG if you want. The CSS filter designers have taken great pains to make the application of a filter easier for web authors, and so this article will just cover the filters available directly from CSS, ignoring the SVG definitions for the time being.&lt;/p&gt;
&lt;h2 id=&quot;how-to-apply-a-css-filter&quot;&gt;How to apply a CSS filter &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#how-to-apply-a-css-filter&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The description and examples below use the official W3C syntax that will be available in all modern browsers eventually. To use filters now, you need to use the vendor prefixed version of the ‘filter’ property. But don’t worry there’s an easy way to handle that at the end of this article. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Using filters from CSS is done by using the ‘filter’ property applied to any visible element on your web page. For a very simple example you could write something like&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; % mixin &lt;span class=&quot;token property&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grayscale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; % &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;and that would make the content inside all &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;elements on the page turn gray. Great for making your page look like a TV image from the 1940s.&lt;/p&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original image.&quot; decoding=&quot;async&quot; height=&quot;300&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 400px) 400px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/52cn4DVhxFyI0Lf1vijP.jpg?auto=format&amp;w=800 800w&quot; width=&quot;400&quot; /&gt;
    &lt;figcaption&gt;Original image.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Grayscale filtered image.&quot; decoding=&quot;async&quot; height=&quot;300&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 400px) 400px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/qRYtPG7YHOUXmRzdHoql.jpg?auto=format&amp;w=800 800w&quot; width=&quot;400&quot; /&gt;
    &lt;figcaption&gt;Grayscale filtered image.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Most filters take some form of parameter to control how much filtering is done. So for example if you wanted to style your content to be half way between the original color and a grayscale version you’d do it like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; % mixin &lt;span class=&quot;token property&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grayscale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;50%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; % &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
    &lt;img alt=&quot;Original image above but 50% gray filtered.&quot; decoding=&quot;async&quot; height=&quot;300&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 400px) 400px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/KFNkg4zlAfOKvO6nIRcZ.jpg?auto=format&amp;w=800 800w&quot; width=&quot;400&quot; /&gt;
    &lt;figcaption&gt;Original image above but 50% gray filtered.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you want to apply a number of different filters one after another, it’s easy - just place them in order in your CSS like so:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; % mixin &lt;span class=&quot;token property&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grayscale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sepia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; % &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;That example will first make all the original color grayscale and then apply a sepia effect, and would end up looking like:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Sepia effect&quot; decoding=&quot;async&quot; height=&quot;300&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 400px) 400px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/8afK306QeaZheetc1aIn.jpg?auto=format&amp;w=800 800w&quot; width=&quot;400&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;With the flexibility available for applying filters one after the other, all sorts of effects can be achieved - it’s totally up to your imagination to experiment with creating amazing results.&lt;/p&gt;
&lt;h2 id=&quot;what-filters-effects-are-available-using-css&quot;&gt;What filters effects are available using CSS &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#what-filters-effects-are-available-using-css&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So the original SVG filter mechanism is both powerful but at the same time can be daunting to use. Because of that, CSS introduces a bunch of standard filter effects that make using them really easy.&lt;/p&gt;
&lt;p&gt;Let’s take a look at each of them and see what they do.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;grayscale(amount)&lt;/dt&gt;
&lt;dd&gt;This converts color in our input image to a shade of gray. The ‘amount’ applied controls how much gray conversion is applied. If it’s 100% then everything will be a shade of gray, if it’s 0% the colors are unchanged. You can use a floating point number here if you prefer it over percentages, i.e. 0 works the same as 0% whilst 1.0 works the same as 100%.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;grayscale(100%)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/EKzLnmlLwnk8LZsuTbS7.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;grayscale(100%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;sepia(amount)&lt;/dt&gt;
&lt;dd&gt;This gives the colors passed in a sepia tinge like in old photographs. The ‘amount’ applied works in the same way as for the ‘grayscale’ filter - namely 100% makes all the colors completely sepia toned and smaller values allow the effect to be applied in smaller proportions.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/VZlx4SxF4FEq2hAIiqLE.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;sepia(100%)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/jxM5zsr5uXQKUwBOYy0T.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;sepia(100%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;saturate(amount)&lt;/dt&gt;
&lt;dd&gt;This applies a color saturation effect to the colors which makes them look more vivid. It’s a cool effect that can make photos look like posters or cartoons.This effect also allows you to use a value greater than 100% to really emphasize the saturation. Definitely an effect that can make things look pretty funky!&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/322WihbKQ14yPtzCAS5O.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;saturate(10)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ILgiZ7EPYhDoRpCqkTF4.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;saturate(10)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In Chrome version 19, the saturate() function takes an integer (without the percentage sign) instead of the decimal or percentage, as per the W3C spec. Not to worry, this known bug will be fixed. &lt;/div&gt;&lt;/aside&gt;
&lt;dl&gt;
&lt;dt&gt;hue-rotate(angle)&lt;/dt&gt;
&lt;dd&gt;This one is a bit of a color geek effect that can be used for interesting results. What it does is shift the colors around to make an input image look completely different. If you can imagine a color spectrum going from red to violet around a &lt;a href=&quot;http://colorschemedesigner.com/&quot;&gt;color wheel&lt;/a&gt;, then this effect takes the original color on the wheel as input and rotates it by the ‘angle’ parameter to produce the color on the wheel to which it rotated as the output color value. So all the colors in the image are shifted by the same &#39;angle&#39; on the wheel. This is of course a simplification of what it does, but hopefully close enough that it makes sense.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/pRWQh1MyJxr8vfvcGYCl.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;hue-rotate(90deg)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/WLTmZG4w3scZR1NIxojH.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;hue-rotate(90deg)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;invert(amount)&lt;/dt&gt;
&lt;dd&gt;This effect flips the colors - so that if the ‘amount’ applied is 100% the output looks like a photo negative back from the old film days of cameras! Just like before, using values smaller than 100% will progressively apply the invert effect.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;invert(100%)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5ItjUJLW8Mkb0fdCIeAI.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;invert(100%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;opacity(amount)&lt;/dt&gt;
&lt;dd&gt;If you want the content being filtered to look semi-transparent, this is the one for you. The ‘amount’ value defines how opaque the output will be. So a value of 100% is completely opaque so the output will be exactly the same as the input. As the value drops below 100% the output image will become less opaque (more transparent) and you’ll see less and less of it. This of course means if it overlaps something else on the page, the stuff underneath will start to become visible. An ‘amount’ of 0% means it will completely disappear - but note, you can still get events like mouse clicks etc. to happen on completely transparent objects so this is handy if you want to create clickable areas without displaying anything.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This works the same as the ‘opacity’ property you already know. In general the CSS ‘opacity’ property isn’t hardware accelerated, but some browsers that implement filters using hardware acceleration will accelerate the filter version of opacity for much better performance.&lt;/p&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/e9uUj0kePvbX6hmOCASL.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;opacity(50%)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/4dMzoGDHY5rxyJc2p59N.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;opacity(50%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;brightness(amount)&lt;/dt&gt;
&lt;dd&gt;This is just like the brightness control on your TV. It adjusts the colors between completely black and the original color in proportion to the ‘amount’ parameter. If you set this one to 0% you’ll see nothing but black, but as the value goes up towards 100% you see more and more of the original image brightening up, until you hit 100% where it’s the same as the input image. Of course you can just keep going - so setting something like 200% will make the image twice as bright as the original - great for adjusting those low light shots!&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/FuY5ANyW0IHgBTQeYNn8.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;brightness(140%)&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ATJ62CPM2OfkWnmzAfSa.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;brightness(140%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;contrast(amount)&lt;/dt&gt;
&lt;dd&gt;More controls from your TV set! This will adjust the difference between the darkest and lightest parts of the input image. If you use 0% you end up with black just like with ‘brightness’, so not too interesting. However as you increase the value towards 100% the difference in darkness changes until you hit 100% and it’s the original image again. You can also go beyond 100% for this effect too, which increases the difference between light and dark colors even more.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;256&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 256px) 256px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/utpM4PER8NOB7U7xh7GL.jpg?auto=format&amp;w=512 512w&quot; width=&quot;256&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;contrast(200%)&quot; decoding=&quot;async&quot; height=&quot;256&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 258px) 258px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ZDlhsG7yEXfidAuGRBO2.jpg?auto=format&amp;w=516 516w&quot; width=&quot;258&quot; /&gt;
    &lt;figcaption&gt;contrast(200%)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;blur(radius)&lt;/dt&gt;
&lt;dd&gt;If you want a soft edge for your content, you can add a blur. This one looks like the classic Vaseline on a sheet of glass look that used to be a popular movie making technique. It smudges all the colors together and spreads their effect out - kind of like when your eyes are out of focus. The ‘radius’ parameter affects how many pixels on the screen blend into each other, so a larger value will create more blur. Zero of course leaves the image unchanged.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Original&quot; decoding=&quot;async&quot; height=&quot;512&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/AWUdr5qU0Rcj20rXrr1g.jpg?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Original&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;blur(10px)&quot; decoding=&quot;async&quot; height=&quot;532&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 529px) 529px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/znBK7cC7kgdpN3gmlejA.jpg?auto=format&amp;w=1058 1058w&quot; width=&quot;529&quot; /&gt;
    &lt;figcaption&gt;blur(10px)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;dl&gt;
&lt;dt&gt;drop-shadow(shadow)&lt;/dt&gt;
&lt;dd&gt;It’s so nice to be able to make your content look like it’s outside in the sun with a shadow on the ground behind it, and that of course is what ‘drop-shadow’ does. It takes a snapshot of the image, makes it a single color, blurs it, then offsets the result a bit so it looks like a shadow of the original content. The ‘shadow’ parameter passed in is a bit more complicated than just a single value. It is a series of values separated by a space - and some values are optional too! The ‘shadow’ values control where the shadow is placed, how much blur is applied, the color of the shadow, etc. For full details of what the ‘shadow’ values do, the &lt;a href=&quot;http://www.w3.org/TR/css3-background/#the-box-shadow&quot; rel=&quot;noopener&quot;&gt;CSS3 Backgrounds&lt;/a&gt; specification defines ‘box-shadow’ in great detail. A few examples below should give you a decent idea of what the various possibilities are.&lt;/dd&gt;
&lt;/dl&gt;
&lt;figure&gt;
    &lt;img alt=&quot;drop-shadow(16px 16px 20px black&quot; decoding=&quot;async&quot; height=&quot;542&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 542px) 542px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5350PABIKdjx78Pu2Ovq.jpg?auto=format&amp;w=1084 1084w&quot; width=&quot;542&quot; /&gt;
    &lt;figcaption&gt;drop-shadow(16px 16px 20px black)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img alt=&quot;drop-shadow(10px -16px 30px purple)&quot; decoding=&quot;async&quot; height=&quot;552&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 542px) 542px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/5WTAF7ckSULYc6rJSVqu.jpg?auto=format&amp;w=1084 1084w&quot; width=&quot;542&quot; /&gt;
    &lt;figcaption&gt;drop-shadow(10px -16px 30px purple)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This is another filter operation that is similar to existing CSS functionality available via the ‘box-shadow’ property. Using the filter approach means that it may get hardware accelerated by some browsers as we described for the ‘opacity’ operation above.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;url referencing SVG filters&lt;/dt&gt;
&lt;dd&gt;Since filters originated as part of SVG, it’s only logical that you should be able to style your content using an SVG filter. This is easy with the current ‘filter’ property proposal. All filters in SVG are defined with an ‘id’ attribute that can be used to reference the filter effect. So, to use any SVG filter from CSS all you need to do is reference it using the ‘url’ syntax.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example, the SVG markup for a filter could be something like:&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;filter&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;foo&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;filter&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;then from CSS you could do something as simple as:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; % mixin &lt;span class=&quot;token property&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#foo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; % &lt;span class=&quot;token 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;and voila! All the &lt;code&gt;&amp;lt;div&lt;/code&gt;&amp;gt;s in your document will be styled with the SVG filter definitions.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;custom (coming soon)&lt;/dt&gt;
&lt;dd&gt;Coming soon on the horizon are custom filters. These tap into the power of your graphics GPU to use a &lt;a href=&quot;http://www.adobe.com/devnet/html5/articles/css-shaders.html&quot; rel=&quot;noopener&quot;&gt;special shading&lt;/a&gt; language to perform amazing effects bounded only by your own imagination. This part of the ‘filter’ specification is still under discussion and in flux, but as soon as this starts to come to a browser near you, we’ll be sure to write more about what is possible.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id=&quot;performance-considerations&quot;&gt;Performance considerations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#performance-considerations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One thing that every web developer cares about is performance of their web page or application. CSS filters are a powerful tool for visual effects, but at the same time might have an impact on the performance of your site.&lt;/p&gt;
&lt;p&gt;Understanding what they do and how this affects performance matters, especially if you want your site to work well on mobile devices if they support CSS filters.&lt;/p&gt;
&lt;p&gt;Firstly, not all filters are created equal! In fact, most filters will run really quickly on any platform and have very minor performance impact. However, filters that do any kind of blurring tend to be slower than the others. This of course means ‘blur’ and ‘drop-shadow’. This doesn’t mean you shouldn’t use them but understanding how they work might help.&lt;/p&gt;
&lt;p&gt;When you do a &lt;code&gt;blur&lt;/code&gt;, it mixes the colors from pixels all around the output pixel to generate a blurred result. So, say if your &lt;code&gt;radius&lt;/code&gt; parameter is 2, then the filter needs to look at 2 pixels in every direction around each output pixel to generate the mixed color. This happens for each output pixel, so that means a lot of calculations that just get bigger when you increase the &lt;code&gt;radius&lt;/code&gt;. Since &lt;code&gt;blur&lt;/code&gt; looks in every direction, doubling the ‘radius’ means you need to look at 4 times as many pixels so in fact it’s 4 times slower for each doubling of the &lt;code&gt;radius&lt;/code&gt;. The &lt;code&gt;drop-shadow&lt;/code&gt; filter contains a &lt;code&gt;blur&lt;/code&gt; as part of its effect, so it too behaves just like &lt;code&gt;blur&lt;/code&gt; when you change the &lt;code&gt;radius&lt;/code&gt; and &lt;code&gt;spread&lt;/code&gt; parts of the &lt;code&gt;shadow&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;All is not lost with &lt;code&gt;blur&lt;/code&gt; since on some platforms it’s possible to use the GPU to accelerate it, but that’s not necessarily going to be available in every browser. When in doubt the best thing is to experiment with the ‘radius’ that gives you the effect you want, then try to reduce it as much as possible while still maintaining an acceptable visual effect. Tuning this way will make your users happier especially if they use your site from a phone.&lt;/p&gt;
&lt;p&gt;If you’re using &lt;code&gt;url&lt;/code&gt; based filters that reference SVG filters, they can contain any arbitrary filter effect so be aware that they too could be slow, so try to make sure you know what the filter effect does and experiment on a mobile device to make sure the performance is OK.&lt;/p&gt;
&lt;h2 id=&quot;availability-in-modern-browsers&quot;&gt;Availability in modern browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#availability-in-modern-browsers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Right now a number of the CSS &lt;code&gt;filter&lt;/code&gt; effects are being made available in WebKit based browsers and Mozilla. We expect to see them soon in Opera as well as IE10. As the specification is still under development, some browser vendors have implemented this stuff using vendor prefixes. So in WebKit you need to use &lt;code&gt;-webkit-filter&lt;/code&gt;, in Mozilla you will need to use
&lt;code&gt;-moz-filter&lt;/code&gt; and keep your eye out for other browser implementations as they appear.&lt;/p&gt;
&lt;p&gt;Not all browsers will support all filter effects right away, so your mileage will vary. Presently, the Mozilla browser supports only the &lt;code&gt;filter: url()&lt;/code&gt; function - without the vendor prefix, as that implementation pre-dates the other effects functions.&lt;/p&gt;
&lt;p&gt;We’ve summarized the CSS filter effects available in the various browsers below with rough performance indicators for when they’re implemented in software. Note, that a number of modern browsers are beginning to implement these in hardware (GPU accelerated). When these are built with GPU support, performance will be greatly improved for the slower effects. As usual, testing on different browsers is the best way to evaluate the performance.&lt;/p&gt;
&lt;table border=&quot;1px&quot;&gt;
&lt;thead&gt;
    &lt;tr&gt;
        &lt;th&gt;Filter effect&lt;/th&gt;
        &lt;th&gt;Browser support&lt;/th&gt;
        &lt;th&gt;Performance&lt;/th&gt;
    &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;grayscale&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;very fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;sepia&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;very fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;saturate&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;very fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;hue-rotate&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;invert&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;very fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;opacity&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;can be slow&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;brightness&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;contrast&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;fast&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;blur&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;slow unless accelerated&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;drop-shadow&lt;/td&gt;&lt;td&gt;Chrome&lt;/td&gt;&lt;td&gt;can be slow&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;url()&lt;/td&gt;&lt;td&gt;Chrome, Mozilla&lt;/td&gt;&lt;td&gt;Varies, fast to slow&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;other-good-resources&quot;&gt;Other good resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/understanding-css/#other-good-resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An awesome &lt;a href=&quot;http://cssfilters.appspot.com/&quot; rel=&quot;noopener&quot;&gt;interactive abstract painting with filters&lt;/a&gt; application which lets you experiment and share your artwork
Be sure to check out Eric Bidelman’s excellent &lt;a href=&quot;http://html5-demos.appspot.com/static/css/filters/index.html&quot; rel=&quot;noopener&quot;&gt;interactive filter&lt;/a&gt; page
A great &lt;a href=&quot;http://net.tutsplus.com/tutorials/html-css-techniques/say-hello-to-css3-filters/&quot; rel=&quot;noopener&quot;&gt;tutorial about filters&lt;/a&gt; with examples
The official W3C Filter Effects 1.0 draft specification &lt;a href=&quot;http://dev.w3.org/fxtf/filters/&quot; rel=&quot;noopener&quot;&gt;http://dev.w3.org/fxtf/filters/&lt;/a&gt;
Example &lt;a href=&quot;http://simurai.com/lab/2010/09/14/stars/&quot; rel=&quot;noopener&quot;&gt;UI created using filters&lt;/a&gt;&lt;/p&gt;
</content>
    <author>
      <name>Alex Danilo</name>
    </author>
  </entry>
</feed>
