<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom Dohnal</title>
    <description>The latest articles on DEV Community by Tom Dohnal (@tomdohnal).</description>
    <link>https://dev.to/tomdohnal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F192197%2Fc8a4da24-2419-4082-a112-1ad78e910570.png</url>
      <title>DEV Community: Tom Dohnal</title>
      <link>https://dev.to/tomdohnal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tomdohnal"/>
    <language>en</language>
    <item>
      <title>TypeScript `Satisfies` keyword—New TypeScript 4.9 feature</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Fri, 11 Nov 2022 17:32:30 +0000</pubDate>
      <link>https://dev.to/tomdohnal/typescript-satifies-keyword-new-typescript-49-feature-42nb</link>
      <guid>https://dev.to/tomdohnal/typescript-satifies-keyword-new-typescript-49-feature-42nb</guid>
      <description>&lt;p&gt;(You can find a video version of this article on &lt;a href="https://www.youtube.com/watch?v=7vHKeFrwvYk"&gt;YouTube&lt;/a&gt;! 📺)&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7vHKeFrwvYk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Imagine you're faced with the following problem:&lt;/p&gt;

&lt;p&gt;You have a type &lt;code&gt;City&lt;/code&gt; that can be either &lt;code&gt;CityName&lt;/code&gt; or &lt;code&gt;CityCoordinates&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;City&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CityName&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;CityCoordinates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CityName&lt;/code&gt; is a string representing one of the specified cities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CityName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mumbai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lagos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CityCoordinates&lt;/code&gt; is an object with &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; properties denoting the coordinates of your city:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CityCoordinates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;User&lt;/code&gt; type has &lt;code&gt;birthCity&lt;/code&gt; and &lt;code&gt;currentCity&lt;/code&gt;, both of which are you type &lt;code&gt;City&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;City&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;City&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you want to create a new variable &lt;code&gt;user&lt;/code&gt; that adheres to the &lt;code&gt;User&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;You want to assign &lt;code&gt;"Mumbai"&lt;/code&gt; to the &lt;code&gt;birthCity&lt;/code&gt; property (that's of the type &lt;code&gt;CityName&lt;/code&gt;) and &lt;code&gt;{ x: 6, y: 3 }&lt;/code&gt; to the &lt;code&gt;currentCity&lt;/code&gt; property (that's of the type &lt;code&gt;CityCoordinates&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;What you would normally do is something like this 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mumbai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all well and good and, as of TypeScript 4.8 of less, the only way to make sure that the &lt;code&gt;user&lt;/code&gt; variable matches the shape of the &lt;code&gt;User&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;Now, say you want to make the &lt;code&gt;birthCity&lt;/code&gt; property of the &lt;code&gt;user&lt;/code&gt; variable uppercase.&lt;/p&gt;

&lt;p&gt;If you were to do that, however, you'd make TypeScript upset and get an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// yields this TypeScript error 👇&lt;/span&gt;
&lt;span class="c1"&gt;// Property 'toUpperCase' does not exist on type 'City'.&lt;/span&gt;
&lt;span class="c1"&gt;//   Property 'toUpperCase' does not exist on type 'CityCoordinates'.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The way that TypeScript sees the &lt;code&gt;birthCity&lt;/code&gt; property is that it can be &lt;em&gt;either&lt;/em&gt; &lt;code&gt;CityName&lt;/code&gt; or &lt;code&gt;CityCoordinates&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It doesn't "know" that you want the &lt;code&gt;user&lt;/code&gt; variable to have the &lt;code&gt;CityName&lt;/code&gt; type for the &lt;code&gt;birthCity&lt;/code&gt; and the &lt;code&gt;CityCoordinates&lt;/code&gt; for the &lt;code&gt;currentCity&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;satisfies&lt;/code&gt; to the rescue
&lt;/h2&gt;

&lt;p&gt;Before the &lt;code&gt;satisfies&lt;/code&gt; keyword was introduced, there wasn't a good way to achieve this.&lt;/p&gt;

&lt;p&gt;More specifically, it wasn't possible to both&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ensure that a variable matches the specified type&lt;/li&gt;
&lt;li&gt;make TypeScript infer a more specific type based on the values provided to this variable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we've got the &lt;code&gt;satisfies&lt;/code&gt; keyword, this very thing is now possible!&lt;/p&gt;

&lt;p&gt;The syntax is as follows 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mumbai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inferred type of the &lt;code&gt;user&lt;/code&gt; variable is going to be 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mumbai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will enable us to access &lt;code&gt;string&lt;/code&gt;-specific methods (like &lt;code&gt;.toUpperCase()&lt;/code&gt;) on the &lt;code&gt;birthCity&lt;/code&gt; property and access the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; number properties on the &lt;code&gt;currentCity&lt;/code&gt; variable 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// we can call `toUpperCase`&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ...and we can access the `x` (or `y`) properties&lt;/span&gt;
&lt;span class="c1"&gt;// and call `number`-specific methods on them&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, on top of that, if we were to assign a value that doesn't match the &lt;code&gt;User&lt;/code&gt; type to the &lt;code&gt;user&lt;/code&gt; variable, we would get protected from type errors 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// assigning "Beijing" yields this error 👇&lt;/span&gt;
  &lt;span class="c1"&gt;//   Type '"Beijing"' is not assignable to type 'City'&lt;/span&gt;
  &lt;span class="na"&gt;birthCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Beijing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currentCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, with &lt;code&gt;satisfies&lt;/code&gt; we can get the best of both worlds. Type safety saves us from runtime errors and powerful type inference gives us most specific types for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;You can find the source code for this tutorial on &lt;a href="https://www.typescriptlang.org/play?ts=4.9.0-dev.20221020#code/PTAEE8HsFdQCwIYDcCmoGgC7gA5oAYDCAltvlopqAMYIB2oARigFAigqlwoBOoRpcADkEAWxTlIfAdkKQpAE2J0EmFAGd8LbHlAlsoALx7BI8aAA+J2fJ5KVa9QG4WbMDOFiJoYuvSh1TB5lAHNQHhQcCPUUOkxQt1BIOjRIADMKDTRqUmINbVw0fU9zYwAiIRQAd1AATSkAazLLUDKAWWhRRgRiZqsygBkEEMh1MpdEjzlFZVUNcl90BkhGACsUaioqrkmAD3J6BX5wcijIPB54jVAFWMh4uhDEzG4aW3s5v3SIGD4AG0gtAeBV0xWmdlmjiMoAA3ixQKBdgAuUB0TrMHguBHgFForq8FwAXwmiQAdOTDpl+ABVGI8cg6NCIdSTRjES5wAaA1TEZIHOhHfDUaA8CJxLlA3l0fAAGkSjHucCSGSqcGI1CVCAiP1gjP4Ep5fJBaFpvGhcIRbI5xRRxSxNBFYswNus4CJE2oyUCoGgdJRpr4xgtTHZLxd7XRPTKcoRwtFsWdghRMMRKIAbDKICiAMygQly4muT10b1WsOCak4C60GLQ328UlluDFUmYSCVi6EBAxAAUAEoScXvfWeAAmc3wkPWpOtDpdKMxh3xuIulPI0AZrOgXP5liEgI89RpPJ+ANFr1UJvFDu8GsocfGEejxuh5uCVvtqu8Lu9gcsIA"&gt;Typescript Playground&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this tutorial, you can also check out and subscribe to my &lt;a href="https://www.youtube.com/channel/UCE7h4of6ywpAG87KXHV6UrQ"&gt;YouTube channel&lt;/a&gt;. Or/and subscribe to my newsletter to get notified when I publish new articles &lt;a href="https://tomdohnal.com/posts/typescript-satisfies-keyword"&gt;on my website&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>Creating Animated Gradient Texts (pure HTML and CSS!)</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Wed, 02 Nov 2022 22:29:53 +0000</pubDate>
      <link>https://dev.to/tomdohnal/animated-gradient-texts-4hoa</link>
      <guid>https://dev.to/tomdohnal/animated-gradient-texts-4hoa</guid>
      <description>&lt;p&gt;(You can find a video version of this article on &lt;a href="https://www.youtube.com/watch?v=aWVEYYz90-A" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;! 📺)&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/aWVEYYz90-A"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out an &lt;a href="https://tomdohnal.com/posts/animated-gradient-headings" rel="noopener noreferrer"&gt;interactive version of this blog&lt;/a&gt; post on my own blog! (Includes custom widgets created to help you understand the key concepts faster!)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's learn how to create animated gradient texts (the ones you might know from &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;vercel.com&lt;/a&gt;). This is what we'll build! 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" alt="animated heading saying animated. gradient. text."&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We'll use plain HTML and CSS but feel free to use your favorite UI or styling&lt;br&gt;
library as you follow along!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Creating gradient text (w/o animation)
&lt;/h2&gt;

&lt;p&gt;First, we'll create a text with a gradient background but &lt;em&gt;no&lt;/em&gt; animation.&lt;/p&gt;

&lt;p&gt;For starters, let's put some HTML markup to work with together and apply some boilerplate CSS styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;64px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c"&gt;/* make the rendered glyphs a bit smoother around the edges */&lt;/span&gt;
      &lt;span class="nl"&gt;-webkit-font-smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;antialiased&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;-moz-osx-font-smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grayscale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;800&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-0.03em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.heading-line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-first"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Animated.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-second"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Gradient.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-third"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Text.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you'd like, you could use the fancy pants &lt;code&gt;nth-child(...)&lt;/code&gt; selectors instead of &lt;code&gt;heading-line-first&lt;/code&gt; etc. 😇&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To add the gradients, we'll set the &lt;code&gt;color&lt;/code&gt; to &lt;code&gt;transparent&lt;/code&gt;, the &lt;code&gt;background-image&lt;/code&gt; to &lt;code&gt;linear-gradient(...)&lt;/code&gt; with our favorite colors, and &lt;code&gt;background-clip&lt;/code&gt; to &lt;code&gt;text&lt;/code&gt; to only render the gradient within the boundaries of the text. 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.heading-line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;

  &lt;span class="c"&gt;/* set the color of the text to transparent */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* we need to clip the gradient background so that
  so only the text bit will have the gradient background
  (otherwise the entire rectangle the text is in would have it) */&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-first&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed8936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed64a6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-second&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#38b2ac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#0bc5ea&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-third&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ecc94b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#48bb78&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what you should end up with 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv15g8fae92m2zjt0w1p9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv15g8fae92m2zjt0w1p9.png" alt="heading saying animated. gradient. text. with gradient background and no animation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Animating the gradient
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;In this section, we're only going to animate the &lt;em&gt;gradient&lt;/em&gt; background. To add some more spice to the animation, we're also going to animate &lt;em&gt;white&lt;/em&gt; background of each heading. That's gonna be covered in the next section though!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We now have a solid foundation to implement the animation!&lt;/p&gt;

&lt;p&gt;Let's think about how the animation should look from a visual standpoint.&lt;/p&gt;

&lt;p&gt;When the page loads, what colors should all the headings be? It should probably look like this, where the first heading has the gradient background and the rest have white backgrounds 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzackrj9qpqwnfhp2zrrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzackrj9qpqwnfhp2zrrf.png" alt="heading saying animated. gradient. text. the first line has a gradient background and the rest has white backgrounds"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Then, after a little while, the first gradient should start fading away and the second one should start fading in. 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiphrbqpodfmn1xfvzhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiphrbqpodfmn1xfvzhv.png" alt="heading saying animated. gradient. text. the first two lines has half gradient half white backgrounds and the third one has fully white background"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Finally, the first line should be white and the second should have the gradient. 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9juduynrwee8n10w4lwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9juduynrwee8n10w4lwp.png" alt="heading saying animated. gradient. text. the first and the third lines have gradient background while the second line has white background"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;The same applies to the third line. Once that's finished, the first line's gradient appears again and the cycle restarts.&lt;/p&gt;

&lt;p&gt;You can see how the gradients are fading in and out as we move the slider 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2irtf5h0amln2mfyu6f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2irtf5h0amln2mfyu6f.gif" alt="headings changing background colors from gradient to white as the slider moves"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To access the &lt;em&gt;interactive widget&lt;/em&gt; you can play with, &lt;a href="https://tomdohnal.com/posts/animated-gradient-headings" rel="noopener noreferrer"&gt;view this article on my blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;To make the animation, we want to divide it into 6 parts. In each part, either&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one heading will have the gradient background (the rest will have white background)&lt;/li&gt;
&lt;li&gt;two headings will be fading in/out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use the table below to know what exact behavior we want to model in CSS:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Heading 1&lt;/th&gt;
&lt;th&gt;Heading 2&lt;/th&gt;
&lt;th&gt;Heading 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Gradient&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Fading out&lt;/td&gt;
&lt;td&gt;Fading in&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;Gradient&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;Fading out&lt;/td&gt;
&lt;td&gt;Fading in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;Gradient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Fading in&lt;/td&gt;
&lt;td&gt;No gradient&lt;/td&gt;
&lt;td&gt;Fading out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;We have now done most of the hard work. Now it's time to translate the table above into CSS.&lt;/p&gt;

&lt;p&gt;The key thing we'll be animating is the &lt;code&gt;opacity&lt;/code&gt; of the gradient background.&lt;/p&gt;

&lt;p&gt;When we want the gradient to be visible, we'll set it to &lt;code&gt;1&lt;/code&gt; and when we want it to be invisible, we'll set it to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we can do that, however, we need to make sure that there is a white background underneath the gradient.&lt;/p&gt;

&lt;p&gt;To do that, we'll need to wrap the heading lines in &lt;code&gt;span&lt;/code&gt; elements, add class &lt;code&gt;heading-line-gradient&lt;/code&gt; to them and leverage the &lt;code&gt;::before&lt;/code&gt; pseudo-element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-first"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line-gradient"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Animated.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-second"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line-gradient"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Gradient.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line heading-line-third"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"heading-line-gradient"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Text.&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.heading-line-gradient&lt;/code&gt; will have the gradient background and &lt;code&gt;.heading-line::before&lt;/code&gt; will have the white background.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* move these style from .heading-line 
   to .heading-line-gradient */&lt;/span&gt;
&lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed8936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed64a6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* move this from .heading-line-first */&lt;/span&gt;
&lt;span class="nc"&gt;.heading-line-first&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed8936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ed64a6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* move this from .heading-line-second */&lt;/span&gt;
&lt;span class="nc"&gt;.heading-line-second&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#38b2ac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#0bc5ea&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* move this from .heading-line-third */&lt;/span&gt;
&lt;span class="nc"&gt;.heading-line-third&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#ecc94b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#48bb78&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* white text underneath the gradient text */&lt;/span&gt;
&lt;span class="nc"&gt;.heading-line&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-first&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Animated."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-second&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Gradient."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-third&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Text."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's focus on the animation! We'll start with the first heading. We'll be animating the &lt;code&gt;opacity&lt;/code&gt; of the &lt;code&gt;heading-line-gradient&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;To define the animation, we'll use the &lt;code&gt;@keyframes&lt;/code&gt; rule and we'll use the &lt;code&gt;animation&lt;/code&gt; property to apply it.&lt;/p&gt;

&lt;p&gt;We'll set the animation duration to &lt;code&gt;8s&lt;/code&gt; and set &lt;code&gt;infinite&lt;/code&gt; as the number of iterations. 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;first_heading_gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="c"&gt;/* 16.667 = 1/6 */&lt;/span&gt;
  &lt;span class="err"&gt;16&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;/* 33.333% = 2/6 */&lt;/span&gt;
  &lt;span class="err"&gt;33&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="c"&gt;/* 83.333% = 5/6 */&lt;/span&gt;
  &lt;span class="err"&gt;83&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-first&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;first_heading_gradient&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll do the same for the second and third headings. 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;second_heading_gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;16&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;33&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;66&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;third_heading_gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;66&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;83&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-second&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;second_heading_gradient&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-third&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.heading-line-gradient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;third_heading_gradient&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what you should end up with 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33hn2c2q1amiorwpbe8y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33hn2c2q1amiorwpbe8y.gif" alt="heading saying animated. gradient. text. being animated."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Animating white background
&lt;/h2&gt;

&lt;p&gt;To make the animation stand out, we'll have to animate the white background of the heading as well.&lt;/p&gt;

&lt;p&gt;Take one more look the what we want to achieve 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" alt="animated heading saying animated. gradient. text."&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;You can notice that the white background is sort of fading in when the gradient is fading out and vice versa.&lt;/p&gt;

&lt;p&gt;The effect is subtle, but it gives the animation a little bit more spice.&lt;/p&gt;

&lt;p&gt;We can't, however, animate the white background for the whole duration of the gradient animation. That would look odd as the text would be almost invisible at one point.&lt;/p&gt;

&lt;p&gt;Instead, we'll only start fading the white background away when the gradient is halfway through its fade-in animation and vice versa.&lt;/p&gt;

&lt;p&gt;Play around with this widget to see how the opacity of the gradient and white background should behave 👇🏻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9cuxr0d2bgg2vkbqubg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9cuxr0d2bgg2vkbqubg.gif" alt="one line of the heading being animated as the slider moves. as you move the slider, you can see how the white background and gradient opacity is changing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a better understanding of when to animate the white background, let's create a table that we'll later translate to CSS.&lt;/p&gt;

&lt;p&gt;This table only deals with the first heading but the same logic applies to the second and third heading as well.&lt;/p&gt;

&lt;p&gt;Now that we're animating the white background as well, we'll need to split the animation into 12 steps (instead of 6).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Gradient opacity&lt;/th&gt;
&lt;th&gt;White background opacity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1 (start to fade out)&lt;/td&gt;
&lt;td&gt;0 (start to fade in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.5 (still fading out)&lt;/td&gt;
&lt;td&gt;1 (already faded in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0 (faded out)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;0 (start fading in)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;0.5 (halfway faded in)&lt;/td&gt;
&lt;td&gt;1 (start fading out)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;1 (faded in)&lt;/td&gt;
&lt;td&gt;0 (faded out)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;I know that this table seems to be a bit overwhelming and a bit tedious to put together&lt;/p&gt;

&lt;p&gt;You can (and I highly encourage you to) create analogical tables for animating the second and third headings.&lt;/p&gt;

&lt;p&gt;Anyways, we have done a lot of hard work, the last bit remaining is to express this table in CSS.&lt;/p&gt;

&lt;p&gt;Let's start with the first heading. 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;first_heading_white_text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="c"&gt;/* 16.667 = 2/12 */&lt;/span&gt;
  &lt;span class="err"&gt;16&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;/* 25% = 3/12 */&lt;/span&gt;
  &lt;span class="err"&gt;25&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="c"&gt;/* 16.667 = 9/12 */&lt;/span&gt;
  &lt;span class="err"&gt;91&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-first&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;first_heading_white_text&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Analogically, we want to animate the second and third headings' white backgrounds. 👇🏻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;second_heading_white_text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;25&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;33&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;58&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;third_heading_white_text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;58&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;66&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;83&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;333&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;91&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;667&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-second&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;second_heading_white_text&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.heading-line-third&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;third_heading_white_text&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎉🥳 We are DONE!!! 🥳🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbqxb7hkxp9sw4uv92e2.gif" alt="animated heading saying animated. gradient. text."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;You can find the source code for this tutorial on &lt;a href="https://codesandbox.io/s/animated-gradient-text-8kefo6" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this tutorial, you can also check out and subscribe to my &lt;a href="https://www.youtube.com/channel/UCE7h4of6ywpAG87KXHV6UrQ" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt; and &lt;a href="https://tomdohnal.com/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>css</category>
      <category>animation</category>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>TypeScript ANY vs UNKNOWN—A Deep Dive</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Sun, 14 Nov 2021 21:23:30 +0000</pubDate>
      <link>https://dev.to/tomdohnal/typescript-any-vs-unknown-a-deep-dive-3iem</link>
      <guid>https://dev.to/tomdohnal/typescript-any-vs-unknown-a-deep-dive-3iem</guid>
      <description>&lt;p&gt;In this blog post, we'll dive deep into what &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; types are, what are their similarities and differences, and when (not) to use them.&lt;/p&gt;

&lt;p&gt;(You can find a video version of this article on YouTube! 📺)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/O6UUEeq0oSg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  TLDR;
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ANY&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatever&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// OK in TypeScript (error in runtime!) 👇&lt;/span&gt;
&lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stupid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 


&lt;span class="c1"&gt;// UNKNOWN&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unknownValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatever, too&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Fails TypeScript check (prevents runtime error) 👇&lt;/span&gt;
&lt;span class="nx"&gt;unknownValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stupid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mnemonics to help you remember the difference 👇&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;any&lt;/code&gt;&lt;/strong&gt; -&amp;gt; first letter is an "A" -&amp;gt; &lt;em&gt;Avoid&lt;/em&gt; TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;unknown&lt;/code&gt;&lt;/strong&gt; -&amp;gt; first letter is a "U" -&amp;gt; &lt;em&gt;Use&lt;/em&gt; TypeScript&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;any&lt;/code&gt; Type&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;unknown&lt;/code&gt; Type&lt;/li&gt;
&lt;li&gt;Use Cases&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The &lt;code&gt;any&lt;/code&gt; Type
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;any&lt;/code&gt; type is something like an escape hatch from TypeScript. &lt;/p&gt;

&lt;p&gt;What does that mean?&lt;/p&gt;

&lt;p&gt;If your variable is of type &lt;code&gt;any&lt;/code&gt;, you can:&lt;br&gt;
&lt;strong&gt;1. Assign whatever you want to it 👇&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;

&lt;span class="nx"&gt;anyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi, how is you? :)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;anyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. "Do" whatever you want with it 👇&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;// OK in TypeScript but error in runtime&lt;/span&gt;
&lt;span class="c1"&gt;// ("...is not a function")&lt;/span&gt;
&lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// OK in TypeScript but error in runtime&lt;/span&gt;
&lt;span class="c1"&gt;// ("...Cannot read properties of undefined")&lt;/span&gt;
&lt;span class="nx"&gt;anyValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generally speaking, using &lt;code&gt;any&lt;/code&gt; allows you to use variables &lt;em&gt;without&lt;/em&gt; type checking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsndm73objhbmpssml6gx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsndm73objhbmpssml6gx.jpg" alt="soldier being shot by an arrow saying "&gt;&lt;/a&gt;&lt;br&gt;
(&lt;a href="https://devrant.com/rants/3015646/i-dont-usually-post-memes-but-this-one-is-just-a-little-too-on-the-nose" rel="noopener noreferrer"&gt;https://devrant.com/rants/3015646/i-dont-usually-post-memes-but-this-one-is-just-a-little-too-on-the-nose&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This means that you lose the main benefit TypeScript has to offer–preventing runtime errors due to accessing non-existing properties.&lt;/p&gt;

&lt;p&gt;You might now wonder &lt;strong&gt;why the heck would I even use &lt;code&gt;any&lt;/code&gt;&lt;/strong&gt; if it means giving up type checking altogether?&lt;/p&gt;

&lt;p&gt;Generally speaking, you should strive to avoid it. To do that, I'd advise you to:&lt;br&gt;
&lt;strong&gt;1) Use &lt;code&gt;"strict": true&lt;/code&gt; in your &lt;code&gt;tsconfig.json&lt;/code&gt; file to disable &lt;em&gt;implicit&lt;/em&gt; &lt;code&gt;any&lt;/code&gt; types&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Implicit any&lt;/em&gt; means that if you don't annotate a variable or a function parameter in TypeScript, it'll be &lt;code&gt;any&lt;/code&gt; by default. With &lt;code&gt;"strict": true&lt;/code&gt;, the TypeScript compiler will throw an error if you've got an unannotated variable of type &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2) Use the &lt;a href="https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md" rel="noopener noreferrer"&gt;&lt;code&gt;no-explicit-any&lt;/code&gt;&lt;/a&gt; rule in &lt;a href="https://github.com/typescript-eslint/typescript-eslint" rel="noopener noreferrer"&gt;TypeScript ESLint&lt;/a&gt;.&lt;/strong&gt; This will give you an ESLint warning whenever you use &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, there are some situations where &lt;code&gt;any&lt;/code&gt; is helpful. We'll cover the main use cases in the final section in depth. Nonetheless, it can be useful when migrating JavaScript code to TypeScript or when dealing with untyped external libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Careful! Some built-in TypeScript types use &lt;code&gt;any&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
When using functions like &lt;code&gt;JSON.parse(...)&lt;/code&gt; or &lt;code&gt;fetch(...).then(res =&amp;gt; res.json())&lt;/code&gt;, the type of the result is &lt;code&gt;any&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;You can use something like &lt;code&gt;JSON.parse(...) as { message: string }&lt;/code&gt; to give it a proper type. Nonetheless, it's useful to know about these as it's very easy to accidentally use &lt;code&gt;any&lt;/code&gt; without even knowing about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can use rules such as &lt;a href="https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md" rel="noopener noreferrer"&gt;&lt;code&gt;no-unsafe-assingment&lt;/code&gt;&lt;/a&gt; in &lt;a href="https://github.com/typescript-eslint/typescript-eslint" rel="noopener noreferrer"&gt;TypeScript ESLint&lt;/a&gt; to get warnings in such scenarios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why does TypeScript behave in this &lt;em&gt;not&lt;/em&gt; type-safe manner? Well, one of the possible explanations is that there was no other way to type these built-in JavaScript functions as there was no &lt;code&gt;unknown&lt;/code&gt; type that would be better suited for this job. Let's have a look at what it does and how it differs from the &lt;code&gt;any&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The &lt;code&gt;unknown&lt;/code&gt; Type
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;unknown&lt;/code&gt; type was added to TypeScript in 2018 with its version &lt;code&gt;3.0&lt;/code&gt; release. Its purpose was to provide a type-safe alternative to &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From the official docs:&lt;br&gt;
TypeScript 3.0 introduces a new top type &lt;code&gt;unknown&lt;/code&gt;. &lt;code&gt;unknown&lt;/code&gt; is the type-safe counterpart of &lt;code&gt;any&lt;/code&gt;. (&lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type" rel="noopener noreferrer"&gt;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What does that mean?&lt;/strong&gt;&lt;br&gt;
As the phrase "type-safe counterpart of &lt;code&gt;any&lt;/code&gt;" suggests, the &lt;code&gt;unknown&lt;/code&gt; type is similar to the &lt;code&gt;any&lt;/code&gt; type in some way but different in others (namely, unlike &lt;code&gt;any&lt;/code&gt;, it's type-safe).&lt;/p&gt;

&lt;p&gt;Let's first examine the similarities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You &lt;em&gt;can&lt;/em&gt; assign whatever you want to an &lt;code&gt;unknown&lt;/code&gt; type&lt;/strong&gt;&lt;br&gt;
This works pretty much the same way as the &lt;code&gt;any&lt;/code&gt; type 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unknownValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;

&lt;span class="nx"&gt;unknownValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hey, how&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;re you doing? :)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;unknownValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With variables of type &lt;code&gt;any&lt;/code&gt; you could do anything with such variables (call them, access random properties on them, etc.). This is &lt;em&gt;not&lt;/em&gt; the case with &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;unknown&lt;/code&gt;, TypeScript &lt;strong&gt;makes &lt;em&gt;no&lt;/em&gt; assumptions about your variables&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;

&lt;span class="c1"&gt;// Error in TypeScript 👇&lt;/span&gt;
&lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Error in TypeScript 👇&lt;/span&gt;
&lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;how&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;are&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;you&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;today?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Error in TypeScript 👇&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very helpful as it prevents you from accidentally accessing non-existent properties, treating strings like functions etc.&lt;/p&gt;

&lt;p&gt;You can &lt;em&gt;think&lt;/em&gt; of the &lt;code&gt;unknown&lt;/code&gt; type as of something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Disclaimer: this is &lt;em&gt;not&lt;/em&gt; the actual definition of the &lt;code&gt;unknown&lt;/code&gt; type. It's just a simplified model to give you a better intuition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Type narrowing with &lt;code&gt;unknown&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As we saw in the code snippet above, TypeScript doesn't allow you to do almost anything with the &lt;code&gt;unknown&lt;/code&gt; type. &lt;/p&gt;

&lt;p&gt;On one hand, it's very useful as it keeps your code type-safe and prevents you from the dreaded runtime JavaScript TypeErrors.&lt;/p&gt;

&lt;p&gt;On the other hand, it's quite limiting as we'd like to be able to manipulate our variables, call properties on them, etc.&lt;/p&gt;

&lt;p&gt;We've got 2 options for how to do that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Type Guards&lt;/strong&gt;&lt;br&gt;
We can use type guards to narrow down the possible types. You can use &lt;code&gt;if&lt;/code&gt; statements or custom &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates" rel="noopener noreferrer"&gt;type predicates&lt;/a&gt; to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logSecretMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// in this if-block we know `message` is of type string&lt;/span&gt;
    &lt;span class="c1"&gt;// so we can call the `toLowerCase()` method on it&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2) Type Assertions (&lt;em&gt;not&lt;/em&gt; type-safe)&lt;/strong&gt;&lt;br&gt;
Alternatively, we can always use type assertions. This is way easier but we lose the type-safety as we use whatever type we want and TypeScript will just "trust" us that we made no mistake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// OK 👇&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unknownVariable&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// OK in TypeScript but it *fails* in runtime 👇&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unknownVariable&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Use Cases for &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; Types
&lt;/h1&gt;

&lt;p&gt;Now that we've got understanding of what the &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; types mean, let's have a look at when (not) to use each of them.&lt;/p&gt;

&lt;p&gt;The rule of thumb is that &lt;code&gt;any&lt;/code&gt; should be avoided since using it makes you lose most of the TypeScript benefits. If you don't know what type a certain variable or a function parameter is, always prefer &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that being said, there are some valid use cases for &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating to TypeScript (from JavaScript)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;any&lt;/code&gt; is very useful when migrating JavaScript codebase into TypeScript. &lt;/p&gt;

&lt;p&gt;Let's say you've got a large JavaScript file which exports many functions and you want to convert it to TypeScript. Without using &lt;code&gt;any&lt;/code&gt;, you'd need to type every single function in this file.&lt;/p&gt;

&lt;p&gt;That's a lot of work and you might just be interested in typing one of the exported functions.&lt;/p&gt;

&lt;p&gt;In this case, you can use &lt;code&gt;any&lt;/code&gt; to quickly type the functions you're not interested in and only give proper types to the one function you're currently working with.&lt;/p&gt;

&lt;p&gt;It might be also useful to create an alias for &lt;code&gt;any&lt;/code&gt; (such as &lt;code&gt;type TODO = any&lt;/code&gt;) so that you can later come back to your temporarily typed functions and give them proper types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// auth.ts (migrating from auth.js)&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;

&lt;span class="c1"&gt;// We can just type the `signUp` function&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use `TODO` to quickly type the `resetPassword` function&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;resetPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use `TODO` to quickly type the `logIn` function&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Functions with unknown arguments
&lt;/h2&gt;

&lt;p&gt;As previously stated, the &lt;code&gt;unknown&lt;/code&gt; type should be preferred when dealing with variables which types we can't determine.&lt;/p&gt;

&lt;p&gt;An example could be a generic logger function 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sendMessageToAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Had we used &lt;code&gt;any&lt;/code&gt; instead, we could have accidentally tried to use properties such as &lt;code&gt;.toLowerCase()&lt;/code&gt; (wrongly) assuming that &lt;code&gt;message&lt;/code&gt; is of type &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thus, using &lt;code&gt;unknown&lt;/code&gt; instead keeps things safe for us 😇&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Custom Checkbox in React (Animated and Accessible)</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Thu, 21 Oct 2021 18:06:48 +0000</pubDate>
      <link>https://dev.to/tomdohnal/custom-checkbox-in-react-animated-and-accessible-3jk9</link>
      <guid>https://dev.to/tomdohnal/custom-checkbox-in-react-animated-and-accessible-3jk9</guid>
      <description>&lt;p&gt;In this article, you're going to learn how to create a custom animated (yet accessible) checkbox. The technique that you'll learn is also applicable for styling radio inputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hj7jxfy5erbfwkqac0o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hj7jxfy5erbfwkqac0o.gif" alt="Kapture 2021-10-05 at 22.30.00"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(You can find the video version of this article on YouTube)&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2Sf8E9CUavA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  How NOT to create a custom checkbox?
&lt;/h1&gt;

&lt;p&gt;Let's first have a look at some possible (but wrong) approaches to creating custom checkboxes and explore their drawbacks.&lt;/p&gt;

&lt;p&gt;As you can't really use CSS (as you'd normally do for styling form elements like buttons or text inputs) to style your checkboxes, you might be tempted to do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Do NOT do this. (Bad a11y + hard to integrate with form libraries)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsChecked&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`checkbox &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checkbox--active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;setIsChecked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// + provide styles for .checkbox .checkbox--active classes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are several problems with this approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) It's bad for for the accessibility&lt;/strong&gt;&lt;br&gt;
If your user happens to be using a screen reader, there is no way that the screen reader can recognise that your &lt;code&gt;div&lt;/code&gt; is actually a checkbox (let alone recognise if the checkbox is checked or not).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) It breaks the native form behaviour&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;div&lt;/code&gt; element doesn't emit &lt;code&gt;change&lt;/code&gt; events so it's harder to integrate it with form libraries. Moreover, the "form data" on the &lt;code&gt;div&lt;/code&gt; element aren't sent to the server upon form submission.&lt;/p&gt;

&lt;p&gt;You could fix this by using &lt;code&gt;aria-role="checkbox"&lt;/code&gt; on the &lt;code&gt;div&lt;/code&gt; element, other &lt;code&gt;aria-*&lt;/code&gt; attributes and a lot of JavaScript.&lt;/p&gt;

&lt;p&gt;However, there is a simpler way...&lt;/p&gt;
&lt;h1&gt;
  
  
  How to create a custom checkbox?
&lt;/h1&gt;

&lt;p&gt;First, we'll have a look at how we'll approach it conceptually so that we have a "big picture" of the implementation.&lt;/p&gt;

&lt;p&gt;We're going to use three different HTML elements for creating a custom checkbox. A &lt;code&gt;label&lt;/code&gt;, an &lt;code&gt;input[type="checkbox"]&lt;/code&gt;, and &lt;code&gt;span&lt;/code&gt; (or &lt;code&gt;svg&lt;/code&gt; or whatever you'd like 😉).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;input[type"checkbox"]&lt;/code&gt; is going to be &lt;em&gt;visually&lt;/em&gt; hidden (but still accessible for screen readers), and we're gonna use the &lt;code&gt;label&lt;/code&gt; element as a parent element so that clicking anywhere in the checkbox triggers the &lt;code&gt;change&lt;/code&gt; event on the &lt;code&gt;input[type="checkbox"]&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using label as a parent element is valid HTML as per &lt;a href="https://www.w3.org/TR/html401/interact/forms.html#edef-LABEL" rel="noopener noreferrer"&gt;https://www.w3.org/TR/html401/interact/forms.html#edef-LABEL&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll use &lt;code&gt;aria-hidden="true"&lt;/code&gt; on the custom (&lt;code&gt;span&lt;/code&gt; or &lt;code&gt;svg&lt;/code&gt;) checkbox so that it's hidden for screen readers as its purpose is only "decorative". We're also going to toggle &lt;code&gt;checkbox--active&lt;/code&gt; class on it so that we can style it differently for "checked" and "unchecked" states.&lt;/p&gt;

&lt;p&gt;With that said, let's write some JSX&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsChecked&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setIsChecked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`checkbox &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox--active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// This element is purely decorative so&lt;/span&gt;
        &lt;span class="c1"&gt;// we hide it for screen readers&lt;/span&gt;
        &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      Don't you dare to check me!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To visually hide the native checkbox, create (and import) a new CSS file with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* taken from https://css-tricks.com/inclusively-hidden/ */&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"checkbox"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;To learn more about visually hiding things in CSS, &lt;a href="https://css-tricks.com/inclusively-hidden/" rel="noopener noreferrer"&gt;visit this blog post on CSS Tricks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you now hit save and open the browser, you'll see something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8xnysd01qpyuh737qxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8xnysd01qpyuh737qxh.png" alt="Screenshot 2021-10-05 at 00.12.14"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The native checkbox &lt;em&gt;is&lt;/em&gt; hidden but we still need to style our custom one.&lt;/p&gt;

&lt;p&gt;Let's do it in the next section!&lt;/p&gt;
&lt;h2&gt;
  
  
  Styling Our Custom Checkbox
&lt;/h2&gt;

&lt;p&gt;Let's first include some styles for our custom checkbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.checkbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;set&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;`inline-block`&lt;/span&gt; &lt;span class="err"&gt;as&lt;/span&gt; &lt;span class="err"&gt;`inline&lt;/span&gt; &lt;span class="err"&gt;elements&lt;/span&gt; &lt;span class="err"&gt;ignore&lt;/span&gt; &lt;span class="err"&gt;`height`&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;`width`&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkbox--active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to result in something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncjsg2m0dl6nvdt9j7n0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncjsg2m0dl6nvdt9j7n0.gif" alt="Kapture 2021-10-05 at 00.34.41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While it reacts to our input, it's missing something–a checkmark indicating if the checkbox is checked or not. Let's turn our &lt;code&gt;span&lt;/code&gt; into an &lt;code&gt;svg&lt;/code&gt; and add a checkmark.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`checkbox &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox--active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// This element is purely decorative so&lt;/span&gt;
        &lt;span class="c1"&gt;// we hide it for screen readers&lt;/span&gt;
        &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
        &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 15 11"&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M1 4.5L5 9L14 1"&lt;/span&gt;
          &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
          &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// only show the checkmark when `isCheck` is `true`&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Don't you dare to check me!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You can find the source code for this section on &lt;a href="https://codesandbox.io/s/react-checkbox-2-xbdje?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  Animating Checkbox using React Spring
&lt;/h1&gt;

&lt;p&gt;In this section, we'll make the checkbox even prettier while maintaining its accessibility.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro39rgngtrepklmoouyh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro39rgngtrepklmoouyh.gif" alt="Kapture 2021-10-05 at 22.30.00"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll be using React Spring library for the animations. You might be able to pull this animation off just with plain CSS but as we'll be animating the SVG Path and we'll need JavaScript to measure its length to make the animation possible, library like React Spring will come in handy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've created a whole &lt;a href="https://dev.to/tomdohnal/series/10252"&gt;series on animating SVGs with React Spring&lt;/a&gt;. Be sure to check it out if you want to learn about it in more detail!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, let's tackle the easier bit–animating the background and border colours.&lt;/p&gt;

&lt;p&gt;After adding &lt;code&gt;react-spring&lt;/code&gt; as a dependency using your favourite package manager, let's import &lt;code&gt;animated&lt;/code&gt; and &lt;code&gt;useSpring&lt;/code&gt; from the library and turn &lt;code&gt;svg&lt;/code&gt; into &lt;code&gt;animated.svg&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; into &lt;code&gt;animated.path&lt;/code&gt; so that they're set and ready to be animated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSpring&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we're done, we'll use the &lt;code&gt;useSpring&lt;/code&gt; hook to animate &lt;code&gt;backgroundColor&lt;/code&gt; and &lt;code&gt;borderColor&lt;/code&gt; attributes. This is going to be analogical to toggling the values of those properties by using the &lt;code&gt;checkbox--active&lt;/code&gt; CSS class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#808&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#808&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ddd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkboxAnimationStyle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we'll remove the &lt;code&gt;checkbox--active&lt;/code&gt; class from our CSS file as it's no longer needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Animating the Checkmark
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;We'll be using a famous technique for animating SVG Paths  (using &lt;code&gt;strokeDashoffset&lt;/code&gt; and &lt;code&gt;strokeDasharray&lt;/code&gt;) in this tutorial.  I created a &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-3-3c91"&gt;whole blog post explaining this subject in much more detail&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To animate the checkmark, we first need to measure (and store) its length. We'll use &lt;code&gt;useState(...)&lt;/code&gt; to store its length, pass a callback to the &lt;code&gt;ref&lt;/code&gt; property of our SVG Path, and call &lt;code&gt;ref.getTotalLength()&lt;/code&gt; to measure its length.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;checkmarkLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCheckmarkLength&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nf"&gt;setCheckmarkLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTotalLength&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've got the length of the path, we can set the &lt;code&gt;strokeDasharray&lt;/code&gt; to &lt;code&gt;checkmarkLength&lt;/code&gt; and use &lt;code&gt;useSpring&lt;/code&gt; to animate the &lt;code&gt;strokeDashoffset&lt;/code&gt; between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;checkmarkLength&lt;/code&gt;. And we'll set the stroke to &lt;code&gt;#fff&lt;/code&gt; no matter of the &lt;code&gt;isActive&lt;/code&gt; state value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're not use how this works, see &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-3-3c91"&gt;my blog post&lt;/a&gt; where I explain this very technique in detail.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isChecked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;checkmarkLength&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="c1"&gt;// ...&lt;/span&gt;
          &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#fff"&lt;/span&gt;
          &lt;span class="na"&gt;strokeDasharray&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkmarkLength&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;strokeDashoffset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;checkmarkAnimationStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Don't you dare to check me!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now try your code out, you'll see that it's working quite okay!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxybog4zg4lwhp0ids1zi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxybog4zg4lwhp0ids1zi.gif" alt="Kapture 2021-10-05 at 22.31.34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While our animation is working quite smoothly, I think we can still add a little bit of spice to take it to the next level.&lt;/p&gt;

&lt;p&gt;First, let's tweak the &lt;code&gt;config&lt;/code&gt; of the &lt;code&gt;useSpring&lt;/code&gt; hook. Let's import the &lt;code&gt;config&lt;/code&gt; variable from React Spring which includes some predefined configs and use &lt;code&gt;config: config.gentle&lt;/code&gt; in our &lt;code&gt;useSpring(...)&lt;/code&gt; calls. This is going to give our animations a little bit more of a playful feel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gentle&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gentle&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, if you look at the animation really closely, you'll notice that the checkmark animation only appears for a brief moment. That's because the checkmark is white for the whole duration of the animation while the background is animating from white to purple. So during the time when the background is white, the checkmark is barely visible (as it's white on a white background).&lt;/p&gt;

&lt;p&gt;We can tackle this by using the &lt;code&gt;useChain&lt;/code&gt; hook from React Spring. This hook enables us to trigger the &lt;code&gt;useSpring(...)&lt;/code&gt; animations one after another. In our case, we'll use it to delay the checkmark animation a bit so that it only starts animating when the background of the checkbox is already mostly purple. We'll do the opposite when animating in the other direction.&lt;/p&gt;

&lt;p&gt;Let's import &lt;code&gt;useChain&lt;/code&gt; along with &lt;code&gt;useSpringRef&lt;/code&gt; from &lt;code&gt;react-spring&lt;/code&gt;. Then, we'll use the &lt;code&gt;useSpringRef&lt;/code&gt; hook to create references to our &lt;code&gt;useSpring&lt;/code&gt; calls which we'll then pass into the &lt;code&gt;useChain&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nx"&gt;useSpringRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useChain&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpringRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationRef&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpringRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationRef&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;useChain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;isChecked&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;checkboxAnimationRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkmarkAnimationRef&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;checkmarkAnimationRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkboxAnimationRef&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; delay by 0.1 seconds&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now play the animation, it looks bonkers!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyzr5s25l021niz30wlm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyzr5s25l021niz30wlm.gif" alt="Kapture 2021-10-05 at 22.30.00"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the source code for the whole tutorial on &lt;a href="https://codesandbox.io/s/react-checkbox-3-xz9ol?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>a11y</category>
      <category>css</category>
      <category>html</category>
    </item>
    <item>
      <title>React SVG Animation (with React Spring) #4</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Tue, 05 Oct 2021 19:02:31 +0000</pubDate>
      <link>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-4-2kba</link>
      <guid>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-4-2kba</guid>
      <description>&lt;p&gt;In the fourth edition of the &lt;a href="https://dev.to/tomdohnal/series/10252"&gt;React SVG Animation series&lt;/a&gt;, we'll learn how to create this 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhe6a4ygwod31xffvplw3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhe6a4ygwod31xffvplw3.gif" alt="a face animating from disappointed to neutral and then to excited"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(You can find a video version of this article on YouTube! 📺)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/i17z_GE592g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We're going to implement it by animating morphing SVG paths. (It sounds fancier than it should.) The code itself is going to be pretty straightforward but we'll need to spend some time in a graphic editor (like &lt;a href="https://figma.com" rel="noopener noreferrer"&gt;Figma&lt;/a&gt;) to get our SVG ready.&lt;/p&gt;

&lt;p&gt;(Full source code available on &lt;a href="https://codesandbox.io/s/react-spring-svg-4-4-kv2qm" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;How Does the Animation Work in Theory?&lt;/li&gt;
&lt;li&gt;How to Prepare the SVG for the Animation? (optional)&lt;/li&gt;
&lt;li&gt;How to morph SVG paths using React Spring?&lt;/li&gt;
&lt;li&gt;Bonus: How to Morph SVG Paths with a Different Number of Points?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How Does the Animation Work in Theory?
&lt;/h1&gt;

&lt;p&gt;Let's say we've got this SVG (it look kinda like a frowning mouth) 👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx35cm57ga0s08ey3s7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx35cm57ga0s08ey3s7s.png" alt="SVG path which looks like a frowning mouth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we want to animate it into this smiling mouth&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel5dkxma9fcebk3n8e4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel5dkxma9fcebk3n8e4e.png" alt="SVG path which looks like a smiling mouth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both the frowning and smiling mouths are represented as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path" rel="noopener noreferrer"&gt;SVG &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt;&lt;/a&gt; elements.&lt;/p&gt;

&lt;p&gt;The shape of the path is determined by the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d" rel="noopener noreferrer"&gt;&lt;code&gt;d&lt;/code&gt;&lt;/a&gt; attributes. It looks like this: &lt;code&gt;d="M2 2 C18 26 68 62 126 62 C188 62 238 26 254 2"&lt;/code&gt; and you can think of it as a series of points (denoted by the numbers) which are connected via different types of lines/curves (denoted by the letters).&lt;/p&gt;

&lt;p&gt;In order to animate from one shape to another, we need to animate all the "numbers" in the path definition (the &lt;code&gt;d&lt;/code&gt; attribute). Luckily, this is quite easy with a library like React Spring.&lt;/p&gt;

&lt;p&gt;If we have a path definition of a smile and of a frown, we can do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;smilePathDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M2 2 C18 26 68 62 126 62 C188 62 238 26 254 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frownPathDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M2 2 C18 -26 68 -62 126 -62 C188 -62 238 -26 254 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shouldSmile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="c1"&gt;// `shouldSmile` can be accepted as props or held in local state&lt;/span&gt;
    &lt;span class="nx"&gt;smilePathDefinition&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;frownPathDefinition&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animatedProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have a look at this video to get a better understanding of what's going on:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ho5xm2ay9e57mld50zi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ho5xm2ay9e57mld50zi.gif" alt="a smile animating to a frown back and forth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In order for the animation to work properly, the path definitions (the &lt;code&gt;d&lt;/code&gt; attributes) must have &lt;strong&gt;the same amount of points&lt;/strong&gt; ("numbers"). (There are some workarounds but let's keep it simple now)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Prepare the SVG for the Animation? (optional)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're only interested in the coding part of the tutorial, you can skip this section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As described in the previous section, the animation itself is pretty straightforward in terms of coding. What's a bit more difficult is putting together the SVG Paths in a way that they all have the same amount of points so that they can animate from one to the other.&lt;/p&gt;

&lt;p&gt;In order to ensure the same number of points, we'll have to spend some time in a graphics editor of our choice–&lt;a href="https://www.figma.com/" rel="noopener noreferrer"&gt;Figma&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, we'll need to find the images of the emojis that we'll be animating. We can do that on &lt;a href="https://emojipedia.org/" rel="noopener noreferrer"&gt;Emojipedia&lt;/a&gt; where you can search for different types of emojis in different "flavours". I generally find the &lt;a href="https://github.com/twitter/twemoji" rel="noopener noreferrer"&gt;Twitter emojis&lt;/a&gt; to be the most simple (thus the most suitable for animations).&lt;/p&gt;

&lt;p&gt;You can now download the emojis that we'll be using: &lt;a href="https://github.com/tomdohnal/random-files/raw/main/disappointed-face_1f61e%201.png" rel="noopener noreferrer"&gt;disappointed 😞&lt;/a&gt;, &lt;a href="https://github.com/tomdohnal/random-files/raw/main/neutral-face_1f610%201.png" rel="noopener noreferrer"&gt;neutral 😐&lt;/a&gt;, and &lt;a href="https://github.com/tomdohnal/random-files/raw/main/smiling-face-with-heart-eyes_1f60d%201.png" rel="noopener noreferrer"&gt;excited 😍&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've downloaded the images, open &lt;a href="https://www.figma.com" rel="noopener noreferrer"&gt;Figma&lt;/a&gt; and place all the images next to each other:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn2p35ehzr5aofvcr8cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn2p35ehzr5aofvcr8cw.png" alt="emoji images placed next to each other in Figma"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next comes the hardest part of the tutorial. We'll need to use the pen tool in Figma and manually trace the paths of our emoji images in a way that every part which morphs into another part has the same number of points. This means that the eyes in all three emojis should all have the same number of points and the mouths should all have the same number of points as well.&lt;/p&gt;

&lt;p&gt;In order to achieve that, let's first copy all three images, decrease their opacity and lock them:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3z5k1m5xzdgzmpg5w28b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3z5k1m5xzdgzmpg5w28b.png" alt="figma screenshot with the steps described above"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, you should trace the edges of the eyes and mouth of the emojis using the pen tool in Figma. Try to use as few points as possible–it will be easier that way. (Four points worked for me.)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgyxhae0l3qtg8vsgxy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgyxhae0l3qtg8vsgxy9.png" alt="tracing edges of the eyes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of tracing both eyes, do it just once and then copy your path and flip it horizontally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do the same for the mouth:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgyxhae0l3qtg8vsgxy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgyxhae0l3qtg8vsgxy9.png" alt="tracing edges of the eyes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you're done, copy both the eyes and the mouth, place them over the other two images and adjust the bezier curve handles accordingly while trying to keep the points as close to their original location as possible.&lt;/p&gt;

&lt;p&gt;You should end up with something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmaatl86z8bvjlkrhbpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmaatl86z8bvjlkrhbpg.png" alt="image with paths traced"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've already done the hardest part! Now we need to prepare the emojis for SVG exports.&lt;/p&gt;

&lt;p&gt;Let's add a circle according to the template for each of them:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfq670f0kb64o6chttxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfq670f0kb64o6chttxj.png" alt="emojis with circle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, let's fill the eyes and mouths with colours according to the template and remove the stroke:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmscetvvvfyt9qdwzqmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmscetvvvfyt9qdwzqmz.png" alt="emojis with stroke removed and filled colour"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Group the emojis so that they're ready for export&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa96m1k6f0bf3q5ei1p4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa96m1k6f0bf3q5ei1p4k.png" alt="emoji grouped"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, finally, export the images as SVGs!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauhxdnnntukfa7r7upvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauhxdnnntukfa7r7upvb.png" alt="exporting images as SVGs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Morph SVG Paths Using React Spring?
&lt;/h1&gt;

&lt;p&gt;Now that we've got the SVG images, let's dive into the code!&lt;/p&gt;

&lt;p&gt;First, we'll bootstrap a new react project (e. g. using &lt;code&gt;create-react-app&lt;/code&gt;) and add the &lt;code&gt;react-spring&lt;/code&gt; library using a dependency manager of our choice.&lt;/p&gt;

&lt;p&gt;Next, let's add the &lt;a href="https://github.com/tomdohnal/random-files/blob/main/dissapointed.svg" rel="noopener noreferrer"&gt;SVG of the disappointed face&lt;/a&gt; into the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"240"&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"240"&lt;/span&gt;
      &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 240 240"&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;circle&lt;/span&gt; &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt; &lt;span class="na"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#FFCD4C"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M192 135.5C188 135.5 178.5 126 164.5 123C150.5 120 141 125.5 137 123C133 120.5 152 99.0001 172 104.5C192 110 196 135.5 192 135.5Z"&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#664300"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M48.3939 135.897C52.3939 135.897 61.8939 126.397 75.8939 123.397C89.8939 120.397 99.394 125.896 103.394 123.397C107.394 120.897 88.3939 99.3966 68.3939 104.897C48.3939 110.397 44.3939 135.897 48.3939 135.897Z"&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#664300"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M119.5 162.5C145 162.5 159.5 189.5 155 194.5C150.5 199.5 153 188.5 119.5 188.5C86 188.5 87.5002 197 84.0001 194.5C80.5001 192 94.0001 162.5 119.5 162.5Z"&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#664300"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the SVG comprises of four different elements.&lt;br&gt;
1) The &lt;code&gt;circle&lt;/code&gt; element: The head of the emoji&lt;br&gt;
2) The first &lt;code&gt;path&lt;/code&gt; element: The left eye of the emoji&lt;br&gt;
3) The second &lt;code&gt;path&lt;/code&gt; element: The right eye of the emoji&lt;br&gt;
4) The third &lt;code&gt;path&lt;/code&gt; element: The mouth of the emoji&lt;/p&gt;

&lt;p&gt;If we take a look at the &lt;a href="https://raw.githubusercontent.com/tomdohnal/random-files/main/neutral.svg" rel="noopener noreferrer"&gt;neutral SVG&lt;/a&gt; and the &lt;a href="https://raw.githubusercontent.com/tomdohnal/random-files/main/cheerful.svg" rel="noopener noreferrer"&gt;cheerful SVG&lt;/a&gt;, we can see that they follow the same pattern–one &lt;code&gt;circle&lt;/code&gt; element for the head and three &lt;code&gt;path&lt;/code&gt; elements for the mouth and eyes respectively.&lt;/p&gt;

&lt;p&gt;Moreover, the &lt;code&gt;circle&lt;/code&gt; element is completely the same for all three emojis as their heads don't change among themselves.&lt;/p&gt;

&lt;p&gt;If you take a closer look at the &lt;code&gt;path&lt;/code&gt; elements, they all are very similar. The only difference is the &lt;code&gt;d&lt;/code&gt; attribute which defines the shape of the path. And that is the attribute we're going to focus on and animate.&lt;/p&gt;
&lt;h2&gt;
  
  
  Animating the Emoji Mouth
&lt;/h2&gt;

&lt;p&gt;Let's first focus on animating the emoji mouth. First, let's extract all the path definitions (the &lt;code&gt;d&lt;/code&gt; attributes) defining the mouths in the above-mentioned SVG files into an array. The first array item should be the frowning mouth, the second one the neutral mouth, and the last one the cheerful mouth&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mouths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M119.5 162.5C145 162.5 159.5 189.5 155 194.5C150.5 199.5 153 188.5 119.5 188.5C86 188.5 87.5002 197 84.0001 194.5C80.5001 192 94.0001 162.5 119.5 162.5Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M122.501 160C148.001 160 173.001 159.5 173.001 167.5C173.001 175.5 156.001 173 122.501 173C89.0008 173 66.5 175 66.5 167.5C66.5 160 97.0006 160 122.501 160Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M120.999 145C158.499 145 171.5 138 176 142.5C187.5 154 164.499 198.5 120.999 198.5C77.4995 198.5 54.929 161.5 62 145C66.2855 135 83.5 145 120.999 145Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For some reason, Figma added an unnecessary &lt;code&gt;H122.501&lt;/code&gt; at the end of the second path definition in the original SVG. I removed it in the code above as it would introduce and extra point to the path thus breaking the animation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, we'll need to import &lt;code&gt;animated&lt;/code&gt; and &lt;code&gt;useSpring&lt;/code&gt; from the &lt;code&gt;react-spring&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSpring&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's change all &lt;code&gt;path&lt;/code&gt; elements to &lt;code&gt;animated.path&lt;/code&gt; so that they're compatible with React Spring animations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll also need to keep track of which emoji should be displayed–let's import and use a &lt;code&gt;useState(...)&lt;/code&gt; hook to do that. We'll use numbers &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, and &lt;code&gt;2&lt;/code&gt; to indicate which emoji should be shown. This is going to correspond to the index of the active item in the &lt;code&gt;mouths&lt;/code&gt; array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll need buttons to make switching between the different emojis possible. The buttons are just going to call &lt;code&gt;setActiveIndex(...)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disappointed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nf"&gt;setActiveIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;activeIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;purple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;activeIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the animation itself! Let's first add a &lt;code&gt;useSpring&lt;/code&gt; call. We'll the current mouth path as &lt;code&gt;{ mouth: mouths[activeIndex] }&lt;/code&gt;. React Spring can handle animating between path definitions the same way it can handle animating properties like &lt;code&gt;translate(...)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mouth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mouths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's replace the hard-coded path definition with the one we get as &lt;code&gt;animationProps.mouth&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now click the buttons, the mouth will be animating. Yay! 🙌&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl5hy5za9vum3z7vuo9s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl5hy5za9vum3z7vuo9s.gif" alt="mouth animating between sad, neutral, and happy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the code for this section on &lt;a href="https://codesandbox.io/s/react-spring-svg-4-2-bt3eh?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Animating the Emoji Eyes
&lt;/h2&gt;

&lt;p&gt;Now that we know how to animate the emoji mouths, we'll use the very same approach for animating the emoji eyes as well.&lt;/p&gt;

&lt;p&gt;We'll use two array to hold the path definitions of the left and right emoji eyes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftEyes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M48.3939 135.897C52.3939 135.897 61.8939 126.397 75.8939 123.397C89.8939 120.397 99.394 125.896 103.394 123.397C107.394 120.897 88.3939 99.3966 68.3939 104.897C48.3939 110.397 44.3939 135.897 48.3939 135.897Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M60.4997 109.5C60.5744 123 64.9997 132.5 76.9996 132.5C88.9996 132.5 92.4998 124.5 92.4997 112C92.4996 99.5 86.9998 87 76.9996 87C66.9995 87 60.4249 96 60.4997 109.5Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M10.3812 33.1735C-0.61879 51.1735 4.38095 95.6736 81.3809 107.174C125.381 63.1733 117.381 18.1732 97.3811 7.67327C77.3814 -2.82666 57.8813 11.1733 53.3809 24.6736C47.3812 20.6735 21.3812 15.1736 10.3812 33.1735Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightEyes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M192 135.5C188 135.5 178.5 126 164.5 123C150.5 120 141 125.5 137 123C133 120.5 152 99.0001 172 104.5C192 110 196 135.5 192 135.5Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M179.5 109.5C179.575 123 174.963 133.5 164 133.5C153.037 133.5 147 122 147 109.5C147 97 153.5 87 164 87C174.5 87 179.425 96 179.5 109.5Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M230 32.5002C241 50.5002 236 95.0003 159 106.5C115 62.5 123 17.4999 143 6.99994C163 -3.5 182.5 10.5 187 24.0002C193 20.0002 219 14.5002 230 32.5002Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of animating the path definitions, we'll also be animating the colour of the eyes as the cheerful emoji has got red eyes. Let's grab the colour hex codes from the SVGs and store them in an array as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eyeColours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#664300&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#664300&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#DE2A42&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now leverage our newly created arrays in the &lt;code&gt;useSpring(...)&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;leftEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;leftEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;rightEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;eyeColour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eyeColours&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, pass the newly created &lt;code&gt;animationProps&lt;/code&gt; onto the respective SVG paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rightEye&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eyeColour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leftEye&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eyeColour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now hit save, it's safe to say, I think, that we're done! ✅&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gb2kbc22bgmx9qggzkr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gb2kbc22bgmx9qggzkr.gif" alt="emoji animating between sad, neutral, and cheerful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the code for this section on &lt;a href="https://codesandbox.io/s/react-spring-svg-4-3-y51lv?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Bonus: Animating SVG Paths with a Different Number of Points
&lt;/h1&gt;

&lt;p&gt;So far, we've focused on how to animate SVG paths with the same number of points. Although the animation itself was quite straightforward, it required a non-trivial effort to put the SVGs together in our vector editor (Figma).&lt;/p&gt;

&lt;p&gt;In this section, we'll learn how to create the same emoji animation that we've created in the section above &lt;em&gt;without&lt;/em&gt; the need to use of any vector editing software. &lt;/p&gt;

&lt;p&gt;It won't come without a cost, though. It's going to require a bit more of a programming effort.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Do Custom Interpolators Work?
&lt;/h2&gt;

&lt;p&gt;Let's first define what we mean be the interpolator.&lt;/p&gt;

&lt;p&gt;For our purposes, an interpolator is a function that can be called with a value from 0 to 1. If you call it with 0, you get back the path definition of the original element. If you call it with 1, you get back the path definition of the element you're trying to morph into. If you call it with 0.5, you get back the path definition of a shape that's halfway through its animation journey. And so on. 🙂&lt;/p&gt;

&lt;p&gt;We'll use the &lt;code&gt;flubber&lt;/code&gt; library in order to create these interpolator functions. This library enables us to create these function if we provide it the path definitions of the shapes from and to we want to animate. &lt;/p&gt;

&lt;p&gt;The "magic" part is that the library doesn't require the path definitions to have the same number of points as it's going to do its magic (maths 🙂) and return an interpolator which we can use to create a smooth animation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's Dive Into the Code
&lt;/h2&gt;

&lt;p&gt;We're going to begin where we left off and install &lt;code&gt;flubber&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we need to replace our carefully crafted SVG for the ones from the &lt;a href="https://github.com/twitter/twemoji" rel="noopener noreferrer"&gt;Twemoji Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Open the &lt;a href="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f61e.svg" rel="noopener noreferrer"&gt;disappointed emoji&lt;/a&gt;, the &lt;a href="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f610.svg" rel="noopener noreferrer"&gt;neutral emoji&lt;/a&gt;, and the &lt;a href="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f60d.svg" rel="noopener noreferrer"&gt;excited&lt;/a&gt; emoji.&lt;/p&gt;

&lt;p&gt;Next, replace the path definitions in the &lt;code&gt;mouths&lt;/code&gt;, &lt;code&gt;leftEyes&lt;/code&gt;, and &lt;code&gt;rightEyes&lt;/code&gt; array for the ones you find in the above-mentioned emojis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use tools like &lt;a href="https://yqnn.github.io/svg-path-editor/" rel="noopener noreferrer"&gt;SVG Path Editor&lt;/a&gt; to convert relative paths to absolute ones or &lt;a href="http://complexdan.com/svg-circleellipse-to-path-converter/" rel="noopener noreferrer"&gt;Ellipse to Path Converter&lt;/a&gt; to turn ellipses into paths. Also, you'll need to split some of the path definitions into parts by finding where each segment of the path ends (marked by the letter &lt;code&gt;Z&lt;/code&gt; in the path).&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mouths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 23.485 28.879 C 23.474 28.835 22.34 24.5 18 24.5 S 12.526 28.835 12.515 28.879 C 12.462 29.092 12.559 29.31 12.747 29.423 C 12.935 29.535 13.18 29.509 13.343 29.363 C 13.352 29.355 14.356 28.5 18 28.5 C 21.59 28.5 22.617 29.33 22.656 29.363 C 22.751 29.453 22.875 29.5 23 29.5 C 23.084 29.5 23.169 29.479 23.246 29.436 C 23.442 29.324 23.54 29.097 23.485 28.879 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M25 26H11c-.552 0-1-.447-1-1s.448-1 1-1h14c.553 0 1 .447 1 1s-.447 1-1 1z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M18 21.849c-2.966 0-4.935-.346-7.369-.819-.557-.106-1.638 0-1.638 1.638 0 3.275 3.763 7.369 9.007 7.369s9.007-4.094 9.007-7.369c0-1.638-1.082-1.745-1.638-1.638-2.434.473-4.402.819-7.369.819&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftEyes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 11.226 15.512 C 10.909 15.512 10.59 15.551 10.279 15.628 C 7.409 16.335 6.766 19.749 6.74 19.895 C 6.7 20.118 6.816 20.338 7.021 20.435 C 7.088 20.466 7.161 20.482 7.232 20.482 C 7.377 20.482 7.519 20.419 7.617 20.302 C 7.627 20.29 8.627 19.124 10.996 18.541 C 11.71 18.365 12.408 18.276 13.069 18.276 C 14.173 18.276 14.801 18.529 14.804 18.53 C 14.871 18.558 14.935 18.57 15.011 18.57 C 15.283 18.582 15.52 18.349 15.52 18.07 C 15.52 17.905 15.44 17.759 15.317 17.668 C 14.95 17.233 13.364 15.512 11.226 15.512 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M9,16.5a2.5,3.5 0 1,0 5,0a2.5,3.5 0 1,0 -5,0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 16.65 3.281 C 15.791 0.85 13.126 -0.426 10.694 0.431 C 9.218 0.951 8.173 2.142 7.766 3.535 C 6.575 2.706 5.015 2.435 3.541 2.955 C 1.111 3.813 -0.167 6.48 0.692 8.911 C 0.814 9.255 0.976 9.574 1.164 9.869 C 3.115 13.451 8.752 15.969 12.165 16 C 14.802 13.833 17.611 8.335 16.883 4.323 C 16.845 3.975 16.77 3.625 16.65 3.281 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightEyes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 24.774 15.512 C 25.091 15.512 25.41 15.551 25.721 15.628 C 28.591 16.335 29.234 19.749 29.26 19.895 C 29.3 20.118 29.184 20.338 28.979 20.435 C 28.912 20.466 28.839 20.482 28.768 20.482 C 28.623 20.482 28.481 20.419 28.383 20.302 C 28.373 20.29 27.373 19.124 25.004 18.541 C 24.29 18.365 23.592 18.276 22.931 18.276 C 21.827 18.276 21.2 18.529 21.196 18.53 C 21.129 18.558 21.065 18.57 20.99 18.57 C 20.718 18.582 20.481 18.349 20.481 18.07 C 20.481 17.905 20.561 17.759 20.684 17.668 C 21.05 17.233 22.636 15.512 24.774 15.512 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M22,16.5a2.5,3.5 0 1,0 5,0a2.5,3.5 0 1,0 -5,0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 19.35 3.281 C 20.209 0.85 22.875 -0.426 25.306 0.431 C 26.782 0.951 27.827 2.142 28.235 3.535 C 29.426 2.706 30.986 2.435 32.46 2.955 C 34.89 3.813 36.167 6.48 35.31 8.911 C 35.187 9.255 35.026 9.574 34.837 9.869 C 32.886 13.451 27.249 15.969 23.835 16 C 21.198 13.833 18.39 8.335 19.118 4.323 C 19.155 3.975 19.23 3.625 19.35 3.281 Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;eyeColours&lt;/code&gt; array stays the same.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might now see something like this and wonder if it's broken:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe30k3vbkwr1kf04d49k5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe30k3vbkwr1kf04d49k5.png" alt="broken image on an emoji"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this, change the &lt;code&gt;viewBox&lt;/code&gt; to &lt;code&gt;0 0 36 36&lt;/code&gt; which is the viewbox used in the original emoji. Also, we'll need to change the parameters of the circle used for the emoji head.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 36 36"&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;circle&lt;/span&gt; &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt; &lt;span class="na"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#FFCD4C"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's dive into the nitty-gritty of the interpolators.&lt;/p&gt;

&lt;p&gt;We'll keep track of the interpolators in the local state (using &lt;code&gt;useState(...)&lt;/code&gt;). We'll use three interpolators–one for animating the mouth and one for each of the eyes.&lt;/p&gt;

&lt;p&gt;When we click the button to trigger the animation, we'll update the interpolator state to hold the specific interpolators for the animations. For example–if the current state of the emoji is "dissapointed" and we want it to animate to "neutral", we'll update the interpolator state to this exact interpolators. We'll then use the &lt;code&gt;useSpring(...)&lt;/code&gt; to animate from 0 to 1 to trigger the animation.&lt;/p&gt;

&lt;p&gt;First, initialise the interpolator state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;interpolators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInterpolators&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mouth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;mouths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;leftEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;leftEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;rightEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rightEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Their initial state is set to "trivial" interpolators–they return the same paths no matter what number we supply to the function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, we need to make some adjustments to the &lt;code&gt;useSpring(...)&lt;/code&gt; function. We'll always be animating from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;, which needs to be reflected in the &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;to&lt;/code&gt; options. We'll also set the &lt;code&gt;clamp&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; which will prevent the animated number from overreaching &lt;code&gt;1&lt;/code&gt; which would break our interpolators. Finally, we'll set the &lt;code&gt;reset&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; to make the animated value always go back to &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;eyeColour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eyeColours&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// this stays the same as it doesn't need a custom interpolator&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// interpolation function can't go above 1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll then adjust the &lt;code&gt;animated.path&lt;/code&gt; elements to make use of the interpolators. We'll leverage to &lt;code&gt;.to(...)&lt;/code&gt; function which enables us to pass an interpolator function to interpolate an animated value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interpolators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rightEye&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interpolators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leftEye&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interpolators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to adjust the &lt;code&gt;onClick&lt;/code&gt; button handler. The gist of is that we want to create new interpolators from the previous value of &lt;code&gt;activeIndex&lt;/code&gt; to the new value of &lt;code&gt;activeIndex&lt;/code&gt; on the button click.&lt;/p&gt;

&lt;p&gt;In order to do that, we'll pass a callback to the &lt;code&gt;setActiveIndex&lt;/code&gt; function in which we'll update the interpolators using the &lt;code&gt;interpolate(...)&lt;/code&gt; function from the &lt;code&gt;flubber&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;interpolate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flubber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disappointed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nf"&gt;setActiveIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;setInterpolators&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                  &lt;span class="na"&gt;mouth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mouths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prevIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;mouths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;maxSegmentLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
                  &lt;span class="p"&gt;}),&lt;/span&gt;
                  &lt;span class="na"&gt;rightEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;rightEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prevIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="nx"&gt;rightEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="na"&gt;maxSegmentLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;),&lt;/span&gt;
                  &lt;span class="na"&gt;leftEye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prevIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;leftEyes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;maxSegmentLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
                  &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;maxLengthSegment&lt;/code&gt; ensure the smoothness of the animation. The lower the number, the smoother it is. But be careful–it comes at a cost of performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We're done! 🥂 Here's the final result:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ygtmc2yhu8bz0dfdh30.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ygtmc2yhu8bz0dfdh30.gif" alt="emoji animating from disappointed to neutral to cheerful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the code for this section on &lt;a href="https://codesandbox.io/s/react-spring-svg-4-4-kv2qm?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React SVG Animation (with React Spring) #3</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Mon, 01 Mar 2021 20:21:05 +0000</pubDate>
      <link>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-3-3c91</link>
      <guid>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-3-3c91</guid>
      <description>&lt;p&gt;In the third edition of the &lt;a href="https://dev.to/tomdohnal/series/10252"&gt;React SVG Animation series&lt;/a&gt;, we're going to create this 👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(You can find a video version of this article on YouTube! 📺)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hQ2VJGPYsV0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We're going to implement it by animating lines in SVG (the &lt;code&gt;path&lt;/code&gt; element) and we'll learn how to extract animation logic into re-usable custom hooks.&lt;/p&gt;

&lt;p&gt;(Full source code available on &lt;a href="https://codesandbox.io/s/animated-shield-rqp6y?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;How to prepare the SVG for the animation?&lt;/li&gt;
&lt;li&gt;How we're going to build the animation?&lt;/li&gt;
&lt;li&gt;How to animate lines in SVG?&lt;/li&gt;
&lt;li&gt;How to create a re-usable animation hook?&lt;/li&gt;
&lt;li&gt;Final touches&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to prepare the SVG for the animation?
&lt;/h1&gt;

&lt;p&gt;Before we start talking about the animation, we need to have something to animate.&lt;/p&gt;

&lt;p&gt;After creating a new React app using your favourite tool (e. g. &lt;code&gt;create-react-app&lt;/code&gt;) and installing &lt;code&gt;react-spring@next&lt;/code&gt; using your favourite package manager, copy and paste this SVG. 👇&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that we're using the &lt;code&gt;next&lt;/code&gt; version of the &lt;code&gt;react-spring&lt;/code&gt; library as the newest version (v9) is still in the &lt;code&gt;rc&lt;/code&gt; stage.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;
      &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;286&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;334&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 286 334&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
        &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#A78BFA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#A78BFA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 143, 333 C 31.09 261.823 1 73.61 1 73.61 L 143 1 v 332 z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
        &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#8B5CF6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#8B5CF6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 143, 333 C 254.911 261.823 285 73.61 285 73.61 L 143 1 v 332 z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
        &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#4ADE80&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M75 153.5l68.081 77.5L235 97&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the SVG is comprised of three &lt;code&gt;path&lt;/code&gt; elements which correspond to the two left and right part of the "shield" and the checkmark.&lt;/p&gt;

&lt;p&gt;Let's extract them into separate components so that it's easier for us to work with them independently.&lt;/p&gt;

&lt;p&gt;First, grab the &lt;em&gt;last&lt;/em&gt; &lt;code&gt;path&lt;/code&gt; element and create a &lt;code&gt;Checkmark&lt;/code&gt; Component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkmark&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#4ADE80&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M75 153.5l68.081 77.5L235 97&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'd like to extract the left and right part of the shield. As the animation is identical for both parts of the shield, it's a good idea to create a &lt;code&gt;ShieldPart&lt;/code&gt; component which will accept a &lt;code&gt;color&lt;/code&gt; and a &lt;code&gt;d&lt;/code&gt; (&lt;code&gt;path&lt;/code&gt; definition) as props. We'll then pass the corresponding colour and &lt;code&gt;path&lt;/code&gt; definition to the &lt;code&gt;ShieldPart&lt;/code&gt; components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShieldPart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've created those components, put the inside the &lt;code&gt;svg&lt;/code&gt; instead of the &lt;code&gt;path&lt;/code&gt; elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Left shield part */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ShieldPart&lt;/span&gt;
    &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 143, 333 C 31.09 261.823 1 73.61 1 73.61 L 143 1 v 332 z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#A78BFA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Right shield part */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ShieldPart&lt;/span&gt;
    &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M 143, 333 C 254.911 261.823 285 73.61 285 73.61 L 143 1 v 332 z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#8B5CF6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Checkmark&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're now good to go and can start talking about the animation itself.&lt;/p&gt;

&lt;p&gt;(You can see the source code for this section on &lt;a href="https://codesandbox.io/s/react-svg-animation-3-1-9q576?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How we're going to build the animation?
&lt;/h1&gt;

&lt;p&gt;Let's have a proper look at the animations we're going to build. 👀👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look really carefully, you can see that the animation consists of three parts.&lt;/p&gt;

&lt;p&gt;First, the edges of the shield animate:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1f20lay1kxy76dbpbtbl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1f20lay1kxy76dbpbtbl.gif" alt="edges of the shield animating"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, the shield gets filled with colour:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fahtj2790n3s9t0fw5wiu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fahtj2790n3s9t0fw5wiu.gif" alt="shield fill colour animating"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, the checkmark animates:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F68p7r362ira3anhjex2r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F68p7r362ira3anhjex2r.gif" alt="shield checkmark animating"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Animating the shield "background" colour is quite straightforwards–we're justing going to animate the &lt;code&gt;fill&lt;/code&gt; property (an SVG equivalent of &lt;code&gt;background&lt;/code&gt; property) from &lt;code&gt;#fff&lt;/code&gt; (white) to the desired colour.&lt;/p&gt;

&lt;p&gt;However, how do we go about animating the shield edges and checkmark? Well, we need a bit of "SVG trickery" to do that. Let's learn out it in the next section.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to animates lines in SVG?
&lt;/h1&gt;

&lt;p&gt;What do we even mean by "lines" in SVG? We do &lt;strong&gt;not&lt;/strong&gt; mean the &lt;code&gt;line&lt;/code&gt; element but a &lt;code&gt;path&lt;/code&gt; element with a &lt;code&gt;stroke&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's use our "checkmark" path element as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
  &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#4ADE80&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// defines the colour of the "line"&lt;/span&gt;
  &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// defines the width of the "line"&lt;/span&gt;
  &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M75 153.5l68.081 77.5L235 97&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strokes in SVGs are similar to borders in HTML. The &lt;code&gt;stroke&lt;/code&gt; property defines the colour of the "line" (roughly equivalent to &lt;code&gt;border-color&lt;/code&gt; in HTML) and &lt;code&gt;stroke-width&lt;/code&gt; defines the "thickness" of the "line" (roughly equivalent to &lt;code&gt;border-width&lt;/code&gt; in HTML). &lt;/p&gt;

&lt;p&gt;"What the heck does &lt;code&gt;stroke&lt;/code&gt; and &lt;code&gt;stroke-width&lt;/code&gt; have to do with animating the SVG," you might think. And you're right (partially 😉). We're going to animate neither of those properties but they &lt;em&gt;do&lt;/em&gt; need to be present on the &lt;code&gt;path&lt;/code&gt; for the animation to make sense. If the path would only have the &lt;code&gt;fill&lt;/code&gt; property (something like &lt;code&gt;background&lt;/code&gt; in HTML) and &lt;em&gt;not&lt;/em&gt; &lt;code&gt;stroke&lt;/code&gt;, we wouldn't be able to animate it.&lt;/p&gt;

&lt;p&gt;Now that we've learnt about the &lt;em&gt;prerequisites&lt;/em&gt; for the animation, let's move on and learn about another two properties (and these &lt;em&gt;will&lt;/em&gt; actually be directly involved in the animation)–&lt;code&gt;stroke-dasharray&lt;/code&gt; and &lt;code&gt;stroke-dashoffset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;stroke-dasharray&lt;/code&gt; property is used to turn your "solid" line into a "dashed" line and defines how wide one "dash" is.&lt;/p&gt;

&lt;p&gt;See the demonstration below. 👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwppf722w1u2dj9bulsn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwppf722w1u2dj9bulsn.gif" alt="changing dash width"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can notice that if we set the range to its max value (which is equal to the length of the checkmark), the one "dash" covers the whole checkmark. This will be the key to the animation!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;stroke-dashoffset&lt;/code&gt; property defines how much "shifted" the "dashes" are. &lt;/p&gt;

&lt;p&gt;Have a look. 👀👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgeuf9cg6zx3t94ts91sh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgeuf9cg6zx3t94ts91sh.gif" alt="changing dash offset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might have noticed that if you set the &lt;code&gt;stroke-dasharray&lt;/code&gt; property equal to the length of the path (which you can get using &lt;code&gt;.getTotalLength()&lt;/code&gt;), it appears as if there were no &lt;code&gt;stroke-dasharray&lt;/code&gt; set at all. &lt;/p&gt;

&lt;p&gt;But is it really the case? Well, it certainly &lt;em&gt;appears&lt;/em&gt; so, but it doesn't mean that it's the case. Actually, the line &lt;em&gt;is&lt;/em&gt; still dashed, but the gap in the dashes is not visible as it's "after" the end of the checkmark. &lt;/p&gt;

&lt;p&gt;What if we, though, combined &lt;code&gt;stroke-dasharray&lt;/code&gt; set to the length of the path with &lt;code&gt;stroke-dashoffset&lt;/code&gt;? What would it look like? 🤔 Let's have a look:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F10t40upd1mcyy9f7xapn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F10t40upd1mcyy9f7xapn.gif" alt="checkmark animating as we're changing stroke dashoffset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What?! How's that possible? It looks like what we've wanted to achieve! The checkmark is animating!&lt;/p&gt;

&lt;p&gt;As the &lt;code&gt;stroke-dashoffset&lt;/code&gt; changes from 0 to the length of the checkmark, the checkmark is disappearing. That's because the "gap" (which's length is also equal to the length of the checkmark) gets "before" the "dash". If the &lt;code&gt;stroke-dashoffset&lt;/code&gt; is set to 0, only the "dash" part is visible. If it's set to the length of the checkmark, only the "gap" part is visible.&lt;/p&gt;

&lt;p&gt;Therefore, to animate the checkmark, you have to:&lt;br&gt;
1) Set its &lt;code&gt;stroke-dasharray&lt;/code&gt; to its length (you can get it by &lt;code&gt;.getTotalLength()&lt;/code&gt;&lt;br&gt;
2) Animate its &lt;code&gt;stroke-offset&lt;/code&gt; from the length (obtained by &lt;code&gt;.getTotalLength()&lt;/code&gt;) to 0.&lt;/p&gt;

&lt;p&gt;Let's do that in the next section!&lt;/p&gt;
&lt;h1&gt;
  
  
  Animating &lt;code&gt;path&lt;/code&gt; in React Spring
&lt;/h1&gt;

&lt;p&gt;First, we need to find out the length of the path. You can either call the &lt;code&gt;.getTotalLength()&lt;/code&gt; function on the &lt;code&gt;path&lt;/code&gt; element and hard-code the value, or you can use &lt;code&gt;useState&lt;/code&gt; from React, and set the length of the path by passing a callback to the &lt;code&gt;ref&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkmark&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// The ref is `null` on component unmount&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTotalLength&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll make the &lt;code&gt;Checkmark&lt;/code&gt; accept a &lt;code&gt;toggle&lt;/code&gt; property which will trigger the animation.&lt;/p&gt;

&lt;p&gt;We'll also set its &lt;code&gt;stroke-dasharray&lt;/code&gt; equal to the &lt;code&gt;length&lt;/code&gt; that we keep track of.&lt;/p&gt;

&lt;p&gt;Finally, we're going to animate the &lt;code&gt;stroke-dashoffset&lt;/code&gt;. We'll use the &lt;code&gt;useSpring&lt;/code&gt; hook for that. If the toggle is truthy, we'll set its value to &lt;code&gt;0&lt;/code&gt; (the checkmark will appear). If it's falsy, we'll set it to the value of &lt;code&gt;length&lt;/code&gt; (the total length of the checkmark) and it'll disappear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkmark&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// we do *not* animating this property, we just set it up&lt;/span&gt;
    &lt;span class="na"&gt;strokeDasharray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;strokeDashoffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animatedStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// The ref is `null` on component unmount&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTotalLength&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you're not familiar with using &lt;code&gt;useSpring&lt;/code&gt;, &lt;code&gt;animated&lt;/code&gt;, and React Spring in general, &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh"&gt;check out my previous posts about animating SVGs using React!&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, we need to pass the &lt;code&gt;toggle&lt;/code&gt; variable from our main &lt;code&gt;Image&lt;/code&gt; component down to the &lt;code&gt;Checkmark&lt;/code&gt; component.&lt;br&gt;
We'll set it to &lt;code&gt;false&lt;/code&gt; initially and use the &lt;code&gt;useEffect&lt;/code&gt; hook together with &lt;code&gt;setImmediate&lt;/code&gt; to set it to &lt;code&gt;true&lt;/code&gt; once the component mounts and the checkmark length is measured (using the &lt;code&gt;.getTotalLength()&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// `setImmediate` is roughly equal to `setTimeout(() =&amp;gt; { ... }, 0)&lt;/span&gt;
    &lt;span class="c1"&gt;// Using `setToggle` without `setImmediate` breaks the animation&lt;/span&gt;
    &lt;span class="c1"&gt;// as we first need to allow for the measurement of the `path`&lt;/span&gt;
    &lt;span class="c1"&gt;// lengths using `.getTotalLength()`&lt;/span&gt;
    &lt;span class="nf"&gt;setImmediate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Checkmark&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You can find the full source-code for this section on &lt;a href="https://codesandbox.io/s/react-svg-animation-3-2-2ev1i" rel="noopener noreferrer"&gt;Codesandbox&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to create a re-usable animation hook?
&lt;/h1&gt;

&lt;p&gt;Thus far, we've only applied what we've learnt to the checkmark animation. However, a very similar animation could be applied to animate the edges of the shield.&lt;/p&gt;

&lt;p&gt;That's why it might be a good idea to extract the logic of animating a "line" in SVG into a separate hook.&lt;/p&gt;

&lt;p&gt;The hook is going to be responsible for measuring the path length and animating the path based on the &lt;code&gt;toggle&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;So it's going to accept &lt;code&gt;toggle&lt;/code&gt; as an argument and return a &lt;code&gt;style&lt;/code&gt; variable (for the animation) and a &lt;code&gt;ref&lt;/code&gt; variable (for the path length measurement).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useAnimatedPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;strokeDashoffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;strokeDasharray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;animatedStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// The ref is `null` on component unmount&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTotalLength&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're the going the use this hook in the &lt;code&gt;Checkmark&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkmark&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAnimatedPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now refresh the page, the animation should look exactly the same as before this refactor.&lt;/p&gt;

&lt;p&gt;Next, let's use the very same &lt;code&gt;useAnimatedPath&lt;/code&gt; hook for animating the edge of the shield in the &lt;code&gt;ShieldPart&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// do *not* forget to make the `ShieldPart`&lt;/span&gt;
&lt;span class="c1"&gt;// component accept the `toggle` prop&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShieldPart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAnimatedPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="c1"&gt;// `path` -&amp;gt; `animated.path`&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;animationProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, pass the &lt;code&gt;toggle&lt;/code&gt; prop onto the &lt;code&gt;ShieldPart&lt;/code&gt; components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Left shield part */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ShieldPart&lt;/span&gt;
        &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Right shield part */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ShieldPart&lt;/span&gt;
        &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now refresh the page, you won't really be satisfied as you'll barely see the shield edges being animated.&lt;/p&gt;

&lt;p&gt;That's because we're not animating the &lt;code&gt;fill&lt;/code&gt; (something like &lt;code&gt;background&lt;/code&gt; in HTML) of the shield and the colour of the shield edges match the colour of the shield background. Let's do it and finish the animation in the next section.&lt;/p&gt;

&lt;p&gt;(You can find the full source code of the section on &lt;a href="https://codesandbox.io/s/react-svg-animation-3-3-y2475?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Final touches
&lt;/h1&gt;

&lt;p&gt;First, let's tackle animating the &lt;code&gt;fill&lt;/code&gt; (something like &lt;code&gt;background&lt;/code&gt; in HTML) of the &lt;code&gt;ShieldPart&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;We'll use a &lt;code&gt;useSpring&lt;/code&gt; hook for the animation and will animate from &lt;code&gt;#000&lt;/code&gt; (white colour) when the &lt;code&gt;toggle&lt;/code&gt; is falsy to the &lt;code&gt;color&lt;/code&gt; property that the &lt;code&gt;ShieldPart&lt;/code&gt; component accepts when the &lt;code&gt;toggle&lt;/code&gt; property is truthy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShieldPart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// rename: `animationProps` -&amp;gt; `animationStrokeProps`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationStrokeProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationFillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;animationStrokeProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// as the `animationStrokeProps` have a `style` property &lt;/span&gt;
      &lt;span class="c1"&gt;// on it, it would be overriden by just passing&lt;/span&gt;
      &lt;span class="c1"&gt;// `style={animationFillStyle}`&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;animationStrokeProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;animationFillStyle&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="c1"&gt;// *remove* the `fill={color}`&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now refresh the page, the animation will look better. Just a little bit better, though. That's because everything is animating all at once. Instead, we want to animate the edges of the shield first, then fill the shield with colour and only then animate the checkmark. &lt;/p&gt;

&lt;p&gt;In order to do that, let's leverage the &lt;code&gt;delay&lt;/code&gt; property which we can pass to the &lt;code&gt;useSpring&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;First, let's make our custom &lt;code&gt;useAnimatedPath&lt;/code&gt; accept a &lt;code&gt;delay&lt;/code&gt; as an argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useAnimatedPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nx"&gt;delay&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's set a &lt;code&gt;delay&lt;/code&gt; of &lt;code&gt;250&lt;/code&gt; ms for the animation of &lt;code&gt;fill&lt;/code&gt; in the &lt;code&gt;ShieldPart&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ShieldPart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationFillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, put a &lt;code&gt;delay&lt;/code&gt; of &lt;code&gt;500&lt;/code&gt; to the &lt;code&gt;useAnimatedPath&lt;/code&gt; hook in the &lt;code&gt;Checkmark&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Checkmark&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAnimatedPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that the exact numbers we put to the &lt;code&gt;delay&lt;/code&gt; property are somewhat arbitrary. There is no right or wrong way number, just watch the animation and fine-tune the exact numbers to your liking&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hit refresh in your browser and the animation should look like this 🎉👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd7j9odsnexqdyfte3sr.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the full source-code for this article on &lt;a href="https://codesandbox.io/s/react-svg-animation-3-4-y5v2n?file=/src/App.js:522-787" rel="noopener noreferrer"&gt;CodeSandbox!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>svg</category>
      <category>animation</category>
      <category>reactspring</category>
    </item>
    <item>
      <title>React SVG Animation (with React Spring) #2</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Sun, 20 Dec 2020 18:40:40 +0000</pubDate>
      <link>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-2-5d2j</link>
      <guid>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-2-5d2j</guid>
      <description>&lt;p&gt;Are you a video learner? This blog post is also available in a video form on YouTube:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/GZYy5t16ucs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Look at the animation below 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fac21250e0by4kr05m3sk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fac21250e0by4kr05m3sk.gif" alt="private data related icons rotating and scaling up and down next to a woman standing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll learn how to create this SVG animation in React Spring and what's tricky about animating &lt;code&gt;transform: scale(...)&lt;/code&gt; and &lt;code&gt;transform: rotate(...)&lt;/code&gt; in SVG.&lt;/p&gt;

&lt;p&gt;(Full source code available on &lt;a href="https://codesandbox.io/s/quizzical-platform-qc8gz?file=/src/App.js" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;How to Prepare the SVG for Animation?&lt;/li&gt;
&lt;li&gt;Why the "Naive" Approach Does NOT Work?&lt;/li&gt;
&lt;li&gt;How Does transform-origin Work in SVG?&lt;/li&gt;
&lt;li&gt;Final touches&lt;/li&gt;
&lt;li&gt;Bonus: How to do this in Framer motion and GSAP?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Prepare the SVG for Animation?
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;I assume you already know how to include SVGs in React. If not, check out &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh"&gt;my previous post&lt;/a&gt; (or &lt;a href="https://youtu.be/fnzlniSEFN4" rel="noopener noreferrer"&gt;YouTube video&lt;/a&gt;) where I explain everything from scratch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this animation, we're using &lt;a href="https://raw.githubusercontent.com/CerebralFart/UndrawMirror/master/images/Private%20data.svg" rel="noopener noreferrer"&gt;an SVG&lt;/a&gt; I found on the &lt;a href="https://undraw.co/search" rel="noopener noreferrer"&gt;unDraw website&lt;/a&gt;. After you download the SVG and convert the &lt;a href="https://svg2jsx.com/" rel="noopener noreferrer"&gt;SVG to JSX&lt;/a&gt;, go ahead and locate the three icons in the SVG code and create separate React components out of them. (So that it's easier to work with.)&lt;/p&gt;

&lt;p&gt;You should end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon1&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon2&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon3&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add a toggle button which will trigger the enter/leave animation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
                &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Toggle animation
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're now ready to start animating!&lt;/p&gt;

&lt;p&gt;You can see the code for this section on CodeSandbox:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/part-1-d577c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Why the "&lt;em&gt;Naive&lt;/em&gt;" Approach Does NOT Work?
&lt;/h1&gt;

&lt;p&gt;If you're familiar with animating HTML elements (or you've read the &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh"&gt;previous tutorial&lt;/a&gt;), you might think: "Oh, this animation is kinda easy, I'm just gonna use &lt;code&gt;transform: rotate(...) scale(...)&lt;/code&gt;  on the icon components and I'll be good to go".&lt;/p&gt;

&lt;p&gt;Honestly, it seems like the perfectly reasonable thing to do. So pull up React Spring (or your favourite animation tool) and give it a try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSprings&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSprings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rotate(0deg) scale(1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rotate(360deg) scale(0)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedIcons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animatedIcons&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* `animatedIcons` instead of `icons` */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code looks quite okay in my opinion. Nonetheless, if you trigger the animation you'll be unpleasantly surprised as you'll see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8cs8p0bv94geah804mkz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8cs8p0bv94geah804mkz.gif" alt="icons rotating around the top-left corner rather than around their own centres"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While the icons &lt;em&gt;are&lt;/em&gt; being animated, they all seem to be rotating around a single point rather than each being rotated individually around their own centre points.&lt;/p&gt;

&lt;p&gt;That's weird, you think. You might even have used &lt;code&gt;transform: rotate(...)&lt;/code&gt; or &lt;code&gt;transform: scale(...)&lt;/code&gt; for animating HTML elements and you're sure that it worked just fine. Yes, you're right, this &lt;em&gt;would&lt;/em&gt; work just fine if we were animating HTML elements. But animating SVG elements is a bit trickier...&lt;/p&gt;

&lt;p&gt;You can see the source code for this section on Codesandbox:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/part-2-o443z"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How Does &lt;code&gt;transform-origin&lt;/code&gt; Work in SVG?
&lt;/h1&gt;

&lt;p&gt;If you look at the (somewhat broken) animation above, you'll notice that the items are rotating around a point somewhere in the top-left corner of the screen. That's not what you want, you want the icons to be rotating around their own centre points. Is there a way to do that? The thing you're looking for is called &lt;code&gt;transform-origin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin" rel="noopener noreferrer"&gt;MDN web docs&lt;/a&gt;, the &lt;code&gt;transform-origin&lt;/code&gt; property "sets the origin for an element's transformations". Well, what does it really do? I think it's best demonstrated in a combination with &lt;code&gt;transform: rotate(...)&lt;/code&gt; where it specifies the point which the element you're animating should revolve around. &lt;/p&gt;

&lt;p&gt;How come you've never needed &lt;code&gt;transform-origin&lt;/code&gt; for animating HTML elements? It's because its default value is &lt;code&gt;50% 50%&lt;/code&gt; (could be written as &lt;code&gt;center&lt;/code&gt;) for HTML elements which corresponds to their middle points. For SVG elements, however, the default value is &lt;code&gt;0, 0&lt;/code&gt; which corresponds to the top-right point in the SVG's viewbox.  &lt;/p&gt;

&lt;p&gt;Look at animation below to see how animating &lt;code&gt;transform: rotate(...)&lt;/code&gt; with &lt;strong&gt;default&lt;/strong&gt; &lt;code&gt;transform-origin&lt;/code&gt; works in SVG. 👇&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fae2f1hfto7wopp6glvhr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fae2f1hfto7wopp6glvhr.gif" alt="an animation of what happens when you apply the default transform-origin for SVG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first idea on how to fix you might have could be this: If the default value of &lt;code&gt;transform-origin&lt;/code&gt; is &lt;code&gt;0, 0&lt;/code&gt; for SVGs and &lt;code&gt;50% 50%&lt;/code&gt; (could be written as &lt;code&gt;center&lt;/code&gt;) for HTML elements, let's manually set the &lt;code&gt;transform-origin&lt;/code&gt; to &lt;code&gt;center&lt;/code&gt; for the SVG and it's gonna behave how I want (rotate around the centres of the elements).&lt;/p&gt;

&lt;p&gt;If you were to try it, however, you wouldn't like the result. That's because setting &lt;code&gt;transform-origin: center&lt;/code&gt; works differently for HTML and SVG elements. For HTML elements, it sets the origin point to the &lt;em&gt;centre of the&lt;/em&gt; &lt;em&gt;actual element you're animating&lt;/em&gt;. For SVG element it sets the origin point to the &lt;em&gt;centre of the&lt;/em&gt; &lt;em&gt;viewbox which contains your SVG element.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have a look at the animation below to get a visual intuition for what's going on. 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh7my33l126quqfxx64rn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh7my33l126quqfxx64rn.gif" alt="an animation of what happens when you apply transform-origin: center for SVG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After all the struggle it seems like there is not an easy solution for making SVG elements rotate around their own centre points. If you think that, I've got good news for you. It can be fixed by adding one extra line of CSS. Add &lt;code&gt;transform-box: fill-box&lt;/code&gt; in addition to &lt;code&gt;transform-origin: center&lt;/code&gt; and watch the animation behave just like you wanted!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;transform-box&lt;/code&gt; property specifies what the &lt;code&gt;transform-origin&lt;/code&gt; property should relate to. Its default value is &lt;code&gt;transform-box: view-box&lt;/code&gt; which makes the &lt;code&gt;transform-origin&lt;/code&gt; relate to the SVG viewbox. If you set it to &lt;code&gt;transform-box: fill-box&lt;/code&gt;, it's going to relate to the element it's applied to. So the centre of the rotation is going to be the centre of the element you're rotating rather than the centre of the viewbox.&lt;/p&gt;

&lt;p&gt;Have a look at the animation below for a more visual explanation. 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqx37734q0z8885pc5225.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqx37734q0z8885pc5225.gif" alt="an animation of what happens when you apply transform-box: fill-box for SVG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we've dived deep into the SVG transform intricacies, it's time to apply what we've learnt to our SVG animation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedIcons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
            &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;transformOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- make it centre&lt;/span&gt;
                &lt;span class="na"&gt;transformBox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill-box&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- of the element&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the source code of this section on CodeSandbox&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/part-3-ip21x"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(One downside to using &lt;code&gt;transform-box: fill-box&lt;/code&gt; is that it is &lt;em&gt;not&lt;/em&gt; supported in legacy browsers (IE11). You could still achieve setting the &lt;code&gt;transform-origin&lt;/code&gt; to the centre of the element by using exact pixel values like this: &lt;code&gt;transform-origin: 120px 160px&lt;/code&gt; where &lt;code&gt;120px 160px&lt;/code&gt; would be the centre of the SVG element.)&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Final touches
&lt;/h1&gt;

&lt;p&gt;Compare the animation we've got at this point with what we'd like it to look like:&lt;/p&gt;

&lt;p&gt;What we've got 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9un3w3rlq09u2ijwndi6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9un3w3rlq09u2ijwndi6.gif" alt="the animation that we've programmed so far"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What we'd like it to look like 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg3rhyd0lugs6fqk5axzu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg3rhyd0lugs6fqk5axzu.gif" alt="the animation that we want to have"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The latter animation has got more of a playful feel to it. It boils down to two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Staggered effect (icons animating one after another)&lt;/li&gt;
&lt;li&gt;Wobbly effect (adding "bounciness")&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Add staggered effect
&lt;/h2&gt;

&lt;p&gt;To add the staggered effect, let's use the &lt;code&gt;delay&lt;/code&gt; option passed to the &lt;code&gt;useSpring&lt;/code&gt; function. (We used this approach in the &lt;a href="https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh"&gt;previous tutorial&lt;/a&gt;, too.)&lt;/p&gt;

&lt;p&gt;We leverage the fact that an &lt;code&gt;index&lt;/code&gt; is passed to the &lt;code&gt;.map(...)&lt;/code&gt; function and add a different delay for each of the icons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSprings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 1st icon -&amp;gt; 0ms, 2nd icon -&amp;gt; 50ms, 3rd icon -&amp;gt; 100ms&lt;/span&gt;
        &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add wobbly effect
&lt;/h2&gt;

&lt;p&gt;Adding the wobbly effect comes down to configuring the spring animation. More specifically, decreasing the &lt;code&gt;friction&lt;/code&gt;. Friction controls the spring "resistance". The higher the friction, the &lt;em&gt;less&lt;/em&gt; "bouncy" animation. The lower the friction, the &lt;em&gt;more&lt;/em&gt; "bounciness".&lt;/p&gt;

&lt;p&gt;It's usually best to fine-tune the exact numbers of the animation configuration manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSprings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;friction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the default value is 26 (we *decrease* it to add bounciness)&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the code for this section on CodeSandbox:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/part-4-fnj5l"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Bonus: How to do this in Framer motion and GSAP?
&lt;/h1&gt;

&lt;p&gt;Everyone uses a different animation library. Nonetheless, the animation principles are pretty much the same. Some libraries do more of the manual work for you (e. g. Framer Motion which applies makes the "rotate" and "scale" animations work with SVG out-of-the-box), some are more bare-bones like React spring. Some libraries are framework specific (React Spring and Framer Motion) and some are more general (GSAP where you have to orchestrate your animation using &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useRef&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;If you're interested, have a look at the implementation of the same animation in React Spring, Framer Motion, and GSAP on Codesandbox &lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/exciting-mayer-ew5wk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactspring</category>
      <category>reactanimation</category>
      <category>svganimation</category>
    </item>
    <item>
      <title>TwitterFOMO—Open-Source Website Showing Most Liked Tweets in WebDev</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Sun, 22 Nov 2020 15:13:27 +0000</pubDate>
      <link>https://dev.to/tomdohnal/twitterfomo-open-source-website-showing-most-liked-tweets-in-webdev-4678</link>
      <guid>https://dev.to/tomdohnal/twitterfomo-open-source-website-showing-most-liked-tweets-in-webdev-4678</guid>
      <description>&lt;p&gt;You can find the source on &lt;a href="https://github.com/tomdohnal/twitter-fomo"&gt;https://github.com/tomdohnal/twitter-fomo&lt;/a&gt;. The website is on &lt;a href="https://twitterfomo.dev"&gt;https://twitterfomo.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app is built in Next.js. Components are created using ChakraUI. I used react-spring for the animations. The SVG images are from undraw.co.&lt;/p&gt;

&lt;p&gt;(Also started a YouTube channel where I explain how I did the SVG animations! You can check it out on &lt;a href="https://www.youtube.com/channel/UCE7h4of6ywpAG87KXHV6UrQ"&gt;https://www.youtube.com/channel/UCE7h4of6ywpAG87KXHV6UrQ&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I use a simple cron job on Heroku which is run every hour to fetch the most-liked tweets and upload them to a Postgres DB using Prisma. The app itself is hosted on Vercel.com.&lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback! Especially, I'd like to hear what you'd suggest doing to filter out "off-topic" tweets so that only the webdev related ones are shown.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>showdev</category>
      <category>react</category>
      <category>discuss</category>
    </item>
    <item>
      <title>React SVG Animation (with React Spring) #1</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Sat, 21 Nov 2020 23:05:45 +0000</pubDate>
      <link>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh</link>
      <guid>https://dev.to/tomdohnal/react-svg-animation-with-react-spring-1-4koh</guid>
      <description>&lt;p&gt;Are you a video learner? This blog post is also available in a video form on YouTube:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/fnzlniSEFN4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Look at the animation below 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudsww2fx0d8ipnk62pr3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudsww2fx0d8ipnk62pr3.gif" alt="animation we are going to build"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll learn how to build it using React and &lt;code&gt;react-spring&lt;/code&gt; library.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;How to Find an SVG to Animate?&lt;/li&gt;
&lt;li&gt;How to Include an SVG in React?&lt;/li&gt;
&lt;li&gt;How to Prepare the SVG for Animation?&lt;/li&gt;
&lt;li&gt;How to Animate the SVG Elements?&lt;/li&gt;
&lt;li&gt;How to Make the Animation Look Good?&lt;/li&gt;
&lt;li&gt;How to Create More Advanced Animations?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Find an SVG to Animate?
&lt;/h1&gt;

&lt;p&gt;The first step you should take to create an animated SVG is to pick an SVG image you want to animate. If you're a skilled illustrator, you can create your own. But if you're like me, websites like &lt;a href="http://undraw.co" rel="noopener noreferrer"&gt;undraw.co&lt;/a&gt; will do the trick. However, the SVG we're animating is no longer there at the time of writing this article but you can still &lt;a href="https://raw.githubusercontent.com/CerebralFart/UndrawMirror/47cc82983bedebf12eaa0d0ab5a6cc607cd599cf/images/Mailbox.svg" rel="noopener noreferrer"&gt;find it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Include an SVG in React?
&lt;/h1&gt;

&lt;p&gt;There are two ways of including an SVG in React code. &lt;/p&gt;

&lt;p&gt;The first one is using &lt;code&gt;&amp;lt;img src="kitten.svg" alt="kitten" /&amp;gt;&lt;/code&gt; just like with .jpg or .png images. However, this approach is &lt;strong&gt;not&lt;/strong&gt; suitable for animations as you lose control over the individual parts of the SVG you want to animate.&lt;/p&gt;

&lt;p&gt;The second approach is using "inline SVG". This means putting the SVG code right into React (JSX)! &lt;/p&gt;

&lt;p&gt;To do that, view the source code of &lt;a href="https://raw.githubusercontent.com/CerebralFart/UndrawMirror/47cc82983bedebf12eaa0d0ab5a6cc607cd599cf/images/Mailbox.svg" rel="noopener noreferrer"&gt;this image&lt;/a&gt;, and copy it. Then, head over to &lt;a href="https://svg2jsx.com/" rel="noopener noreferrer"&gt;https://svg2jsx.com&lt;/a&gt; and paste the copied SVG code into the editor on the left. This tool will convert the SVG to JSX. (It will close every unclosed SVG elements and convert attributes such as  &lt;code&gt;stop-color&lt;/code&gt; to &lt;code&gt;stopColor&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Now copy the code from the editor on the right-hand side and paste it into your editor. The SVG will appear in your browser! &lt;/p&gt;

&lt;p&gt;You can view the code for this section in the embedded CodeSandbox below. 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/elegant-leftpad-m6g1m"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(I decreased the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; of the original &lt;code&gt;svg&lt;/code&gt; so that it fits in the CodeSandbox embed)&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Prepare the SVG for Animation?
&lt;/h1&gt;

&lt;p&gt;To be able to animate specific parts of the SVG image, you should extract them to individual React components so that it's a bit easier to work with. (Remember, you can treat the SVGs just like HTML and split it into many components.)&lt;/p&gt;

&lt;p&gt;Because we want to animate the envelopes let's create a component for each envelope. Now comes the hard—finding out which of almost 300 lines of SVG code create the envelopes. &lt;/p&gt;

&lt;p&gt;Open the browser devtools and try to locate the envelope using the element picker. If you locate a part of the SVG which you think is a part of the envelope, you can try deleting it (using the &lt;code&gt;delete&lt;/code&gt; key) and see if the envelope (or its part) actually gets removed. (Use &lt;code&gt;ctrl + z&lt;/code&gt; or &lt;code&gt;cmd + z&lt;/code&gt; to bring it back).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhphiytkfo6tmv6brpo2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhphiytkfo6tmv6brpo2k.png" alt="devtool with located SVG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After playing with the devtools for a bit, you can identify that each envelope is composed of two &lt;code&gt;path&lt;/code&gt; elements followed by a &lt;code&gt;g&lt;/code&gt; element. &lt;/p&gt;

&lt;p&gt;Now, you can head over to your editor, create &lt;code&gt;&amp;lt;Envolope1 /&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Envolope2 /&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Envolope3&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Envelope4 /&amp;gt;&lt;/code&gt;. You should use a &lt;code&gt;g&lt;/code&gt; element as the parent element in your &lt;code&gt;Envelope&lt;/code&gt; components to group the items in it. (Think of the &lt;code&gt;g&lt;/code&gt; element as an SVG alternative to the &lt;code&gt;div&lt;/code&gt; element.)&lt;/p&gt;

&lt;p&gt;The last steps in this part is to create an array of the &lt;code&gt;Envelope&lt;/code&gt; component on top of your main component and include it to where the envelopes where in the &lt;code&gt;svg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;envelopes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Envelope1&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"envelope1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Envelope2&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"envelope1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Envelope3&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"envelope1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Envelope4&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"envelope1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            // ...
            // ...
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image itself should look exactly the same as at the end of the previous section.&lt;/p&gt;

&lt;p&gt;You can view the code for this section in the embedded CodeSandbox below. 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/infallible-tesla-6zgon"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Animate the SVG Elements?
&lt;/h1&gt;

&lt;p&gt;Finally, here comes the fun part! 🎉 &lt;/p&gt;

&lt;p&gt;First, you need something to trigger the animation. Let's use a simple &lt;code&gt;button&lt;/code&gt; which will toggle a variable. Based on the value of that variable, the envelopes will arrive or go away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Toggle animation
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                // ...
                // ...
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you have a &lt;code&gt;toggle&lt;/code&gt; variable to trigger the animation you can start animating. &lt;/p&gt;

&lt;p&gt;For animating an array of elements with &lt;code&gt;react-spring&lt;/code&gt; you should use the &lt;code&gt;useSprings&lt;/code&gt; hook. (&lt;a href="https://www.react-spring.io/docs/hooks/use-springs" rel="noopener noreferrer"&gt;Read the documentation&lt;/a&gt; to learn more about it.)&lt;/p&gt;

&lt;p&gt;To create the animation effect the &lt;code&gt;transform: translate3d(...)&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt; are used. The value passed to the &lt;code&gt;translate3d(...)&lt;/code&gt; function or &lt;code&gt;opacity&lt;/code&gt; is going to change based on the &lt;code&gt;toggle&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useSprings&lt;/code&gt; hook will return an array of animated values which we can map over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSprings&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;envelopes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the number of springs to create&lt;/span&gt;
        &lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;
                    &lt;span class="c1"&gt;// toggle === true -&amp;gt; initial position&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`translate3d(0px, 0px, 0px)`&lt;/span&gt;
                    &lt;span class="c1"&gt;// toggle === false -&amp;gt; move the envelopes to the left&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`translate3d(-400px, 0px, 0px)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
                    &lt;span class="c1"&gt;// toggle === true -&amp;gt; full opacity&lt;/span&gt;
                    &lt;span class="mi"&gt;1&lt;/span&gt;
                    &lt;span class="c1"&gt;// toggle === false -&amp;gt; full transparency&lt;/span&gt;
                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            // ...
            // ...
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the springs you are now ready to map over them! The &lt;code&gt;springs&lt;/code&gt; variable is an array of so-called "animated values" which you pass to the &lt;code&gt;style&lt;/code&gt; property of elements wrapped in &lt;code&gt;animated.g&lt;/code&gt; from &lt;code&gt;react-spring&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Let's see the code excerpt with comments!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSprings&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-spring&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;envelopes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animatedEnvelopes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;animatedStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// use `animated.g` instead of `g` as the `animatedStyle`&lt;/span&gt;
    &lt;span class="c1"&gt;// is a special react-spring flavour of the `style` property&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// YOLO&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animatedStyle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// apply the animated style&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            // ...
            // ...
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                // ...
            // ...
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animatedEnvelopes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; // use `animatedEnvelopes` instead of `envelopes`
                // ...
                // ...
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That wraps up this section! You now have the envelopes moving as you press the "Toggle animation" button.&lt;/p&gt;

&lt;p&gt;You can find all the code for this section in the CodeSandbox &lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/naughty-night-eg602"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Make the animation look good?
&lt;/h1&gt;

&lt;p&gt;You can probably see that the animation we created doesn't really look so good.&lt;/p&gt;

&lt;p&gt;There are at least 3 problems:&lt;/p&gt;
&lt;h2&gt;
  
  
  Problem 1: The Trajectory Is Too Short
&lt;/h2&gt;

&lt;p&gt;The animation trajectory seems to be a bit too short. That's because you can't see the envelopes when they go past the &lt;code&gt;viewBox&lt;/code&gt; of the &lt;code&gt;svg&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Fortunately, the fix is quite easy. You just need to manually adjust the &lt;code&gt;viewBox&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;(The &lt;code&gt;viewBox&lt;/code&gt; specifies what points are visible in the &lt;code&gt;svg&lt;/code&gt; element. It's used like this: &lt;code&gt;viewBox="x0 y0 width height"&lt;/code&gt; where &lt;code&gt;x0&lt;/code&gt; specifies the left-most point, &lt;code&gt;y0&lt;/code&gt; specifies the top-most point and &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; specify the width and height. 🙃)&lt;/p&gt;

&lt;p&gt;We need to give the &lt;code&gt;svg&lt;/code&gt; some extra space on the left, therefore adjust the viewBox from &lt;code&gt;0 0 733.51 728.97&lt;/code&gt; to &lt;code&gt;-200 0 933.51 728.97&lt;/code&gt;. (Change the first number to create some space on the left and the third number to &lt;strong&gt;not&lt;/strong&gt; crop the right-hand part of the image).&lt;/p&gt;
&lt;h2&gt;
  
  
  Problem 2: Envelopes Don't Animate in a Natural Direction
&lt;/h2&gt;

&lt;p&gt;Even though the envelopes are slightly rotated we only animate them in one direction (left-right). It would seem more natural to animate in two directions (left-right + top-bottom). &lt;/p&gt;

&lt;p&gt;How to find out how much vertical movement we should add? You could either fine-tune the &lt;code&gt;translate&lt;/code&gt; property manually or use a bit of trigonometry. Let's do the latter. 😉&lt;/p&gt;

&lt;p&gt;First, let's find out what angle the envelopes are rotated at. You can use the devtools to find that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyj9n87awwgi7cpt91j3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyj9n87awwgi7cpt91j3q.png" alt="rotation angle rotated in devtools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the rotation angle is around &lt;code&gt;83deg&lt;/code&gt;. And the horizontal part of the animation is &lt;code&gt;400px&lt;/code&gt;. We get the vertical part of the animation as: vertical = &lt;code&gt;400px * cos(83deg)&lt;/code&gt; which yields around &lt;code&gt;49px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So change the &lt;code&gt;translate3d(-400px, 0px, 0px)&lt;/code&gt; to &lt;code&gt;translate3d(-400px, -49px, 0px)&lt;/code&gt; and you'll be good to go.&lt;/p&gt;
&lt;h2&gt;
  
  
  Problem 3: Envelopes don't animate individually
&lt;/h2&gt;

&lt;p&gt;Envelopes animate as a group which doesn't really look natural. Creating a staggered effect would make the animation seem much more natural.&lt;/p&gt;

&lt;p&gt;Fortunately, it's two lines of code in &lt;code&gt;react-spring&lt;/code&gt; as we can specify &lt;code&gt;delay&lt;/code&gt; for each animated value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;springs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSprings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;envelopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
                &lt;span class="c1"&gt;// as we map over the envelopes, increase the delay&lt;/span&gt;
                &lt;span class="c1"&gt;// first envelope -&amp;gt; delay: 0ms&lt;/span&gt;
                &lt;span class="c1"&gt;// second envelope -&amp;gt; delay: 100ms&lt;/span&gt;
                &lt;span class="c1"&gt;// etc.&lt;/span&gt;
        &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(It's worth noting that you could also use the &lt;code&gt;useTrail&lt;/code&gt; hook instead of &lt;code&gt;useSpring&lt;/code&gt; with delay to create a staggered effect.)&lt;/p&gt;

&lt;p&gt;Yay! 😲The animation now looks much better! You can find the source code in the CodeSandbox below:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/empty-firefly-lllum"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Create More Advanced Animations?
&lt;/h1&gt;

&lt;p&gt;This is just the beginning—animating the using the &lt;code&gt;translate3d(...)&lt;/code&gt; property is quite similar in SVG and HTML. However, things get more tricky if you try to animate &lt;code&gt;scale&lt;/code&gt;, &lt;code&gt;rotate&lt;/code&gt; properties.&lt;/p&gt;

&lt;p&gt;If you're interested, you can follow me here or/and &lt;a href="https://www.youtube.com/channel/UCE7h4of6ywpAG87KXHV6UrQ" rel="noopener noreferrer"&gt;check out the YouTube channel&lt;/a&gt; where I'll be posting the tutorials.&lt;/p&gt;

</description>
      <category>react</category>
      <category>svg</category>
      <category>animation</category>
      <category>reactspring</category>
    </item>
    <item>
      <title>Blocking Fallback for getStaticPaths–New Next.js 10 feature</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Sun, 01 Nov 2020 10:22:58 +0000</pubDate>
      <link>https://dev.to/tomdohnal/blocking-fallback-for-getstaticpaths-new-next-js-10-feature-1727</link>
      <guid>https://dev.to/tomdohnal/blocking-fallback-for-getstaticpaths-new-next-js-10-feature-1727</guid>
      <description>&lt;h1&gt;
  
  
  Table Of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Why was &lt;code&gt;fallback: 'blocking'&lt;/code&gt; introduced?&lt;/li&gt;
&lt;li&gt;How does &lt;code&gt;fallback: 'blocking'&lt;/code&gt; work?&lt;/li&gt;
&lt;li&gt;When (not) to use &lt;code&gt;fallback: 'blocking'&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Why was &lt;code&gt;fallback: 'blocking'&lt;/code&gt; introduced? 🤔🤔
&lt;/h1&gt;

&lt;p&gt;When Vercel released the &lt;code&gt;9.3&lt;/code&gt; version of their popular Next.js framework, two brand new data fetching methods were introduced: &lt;code&gt;getStaticProps&lt;/code&gt; and &lt;code&gt;getServerSideProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to use &lt;code&gt;getStaticProps&lt;/code&gt; with, for example, a detail page of a product (&lt;code&gt;pages/products/[id].js&lt;/code&gt;) you use &lt;code&gt;getStaticPaths&lt;/code&gt; along with &lt;code&gt;getStaticProps&lt;/code&gt; to define which product IDs you want to generate the page for.&lt;/p&gt;

&lt;p&gt;If, however, you have a large e-commerce site with 10,000 products, you wouldn't want to return the IDs of &lt;em&gt;all&lt;/em&gt; products from the &lt;code&gt;getStaticPaths&lt;/code&gt; as building 10,000 pages would take ages.&lt;/p&gt;

&lt;p&gt;Instead, you might just return the IDs of the most popular products and use &lt;code&gt;fallback: true&lt;/code&gt; in &lt;code&gt;getStaticPaths&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you then a product page of some obscure product that's not frequently visited (e. g. &lt;code&gt;/products/43284&lt;/code&gt;) for the first time, you'd be presented with a loading screen 💻 before the page gets generated (and the product data is fetched in &lt;code&gt;getStaticProps&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;(If you don't want to fetch other products than you specified, use &lt;code&gt;fallback: false&lt;/code&gt; and Next.js will return a 404 🛑 for those pages.)&lt;/p&gt;

&lt;p&gt;Every subsequent visit will serve the page statically 🚀 as the page is built (and cached) on the first visit.&lt;/p&gt;

&lt;p&gt;However, having to use the loading indicator during the first visit has some issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some &lt;code&gt;og:*&lt;/code&gt; crawlers (Facebook, Twitter, LinkedIn, ...) don't support JS and thus fail to fetch correct &lt;code&gt;og:*&lt;/code&gt; tags for &lt;code&gt;fallback: true&lt;/code&gt; pages &lt;/li&gt;
&lt;li&gt;AMP pages 📲 don't work correctly with &lt;code&gt;fallback: true&lt;/code&gt; as they get stuck loading. (&lt;a href="https://github.com/vercel/next.js/issues/14256" rel="noopener noreferrer"&gt;https://github.com/vercel/next.js/issues/14256&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, the Next.js team introduced a third option for the &lt;code&gt;fallback&lt;/code&gt; field: &lt;code&gt;'blocking'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(See &lt;a href="https://github.com/vercel/next.js/issues/15637" rel="noopener noreferrer"&gt;https://github.com/vercel/next.js/issues/15637&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxsfl1gsi7yo0hbxhzz72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxsfl1gsi7yo0hbxhzz72.png" alt="GitHub issue screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  How does &lt;code&gt;fallback: 'blocking'&lt;/code&gt; work? 😲😲
&lt;/h1&gt;

&lt;p&gt;If you're using &lt;code&gt;fallback: true&lt;/code&gt; in your page, you have to use something like this in your code 😕:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductDetail&lt;/span&gt; &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is for the case when the user visits a page with &lt;code&gt;fallback: true&lt;/code&gt; for the first time (a page which has not yet been built and whose props from &lt;code&gt;getStaticProps&lt;/code&gt; hasn't been fetched).&lt;/p&gt;

&lt;p&gt;If, however, you use &lt;code&gt;fallback: 'blocking'&lt;/code&gt; in &lt;code&gt;getStaticPaths&lt;/code&gt;, you don't use the &lt;code&gt;if (router.isFallback)&lt;/code&gt; check. That's because when the user visits a page with &lt;code&gt;fallback: 'blocking'&lt;/code&gt; which has not yet been built, Next.js is first going to build the page and only after it's built it's going the send the response to the user's browser.&lt;/p&gt;

&lt;p&gt;You can play ▶️ with the CodeSandbox below the see how &lt;code&gt;fallback: false&lt;/code&gt;, &lt;code&gt;fallback: true&lt;/code&gt;, and &lt;code&gt;fallback: 'blocking'&lt;/code&gt; differ.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/dark-mountain-ibxx4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  When (not) to use &lt;code&gt;fallback: 'blocking'&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;Generally, the Next.js team encourages you &lt;strong&gt;not&lt;/strong&gt; to use it unless is necessary. Using &lt;code&gt;fallback: 'blocking'&lt;/code&gt; doesn't help the SEO (as Google and other search engine crawlers run JS code and will wait for a &lt;code&gt;fallback: true&lt;/code&gt; page to load). Using &lt;code&gt;fallback: 'blocking'&lt;/code&gt; makes the user wait 🥱 without any response while the page is being built and it's better to use &lt;code&gt;fallback: true&lt;/code&gt; and show a loading skeleton while the page is being built instead.&lt;/p&gt;

&lt;p&gt;If, however, you're experiencing issues with OG tags, AMP, or something else due to the usage of &lt;code&gt;fallback: true&lt;/code&gt;, feel free to switch to &lt;code&gt;fallback: 'blocking'&lt;/code&gt; 🤗.&lt;/p&gt;

&lt;p&gt;You can see the comparison between &lt;code&gt;fallback: false&lt;/code&gt;, &lt;code&gt;fallback: true&lt;/code&gt;, and &lt;code&gt;fallback: blocking&lt;/code&gt; below: ⬇️⬇️⬇️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fallback: false&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkw7s95h2k9ritq6kcl53.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkw7s95h2k9ritq6kcl53.gif" alt="fallback false example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fallback: true&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft87kwpxzds8e12ja3zs7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft87kwpxzds8e12ja3zs7.gif" alt="fallback true example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fallback: 'blocking'&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F16ohivnst4mw5reb5bt4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F16ohivnst4mw5reb5bt4.gif" alt="fallback blocking example"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>vercel</category>
    </item>
    <item>
      <title>SSR (Next.js) - part 2/2: IS IT EVEN WORTH IT? 💎</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Thu, 16 Apr 2020 21:09:28 +0000</pubDate>
      <link>https://dev.to/tomdohnal/migrating-to-ssr-next-js-part-2-3-is-it-even-worth-it-3pnk</link>
      <guid>https://dev.to/tomdohnal/migrating-to-ssr-next-js-part-2-3-is-it-even-worth-it-3pnk</guid>
      <description>&lt;h1&gt;
  
  
  Migrating to SSR (Next.js) - part 2/2: IS IT EVEN WORTH IT? 💎
&lt;/h1&gt;

&lt;p&gt;In this article we'll explore the pros and cons of server-side rendering as opposed to "client-only" single-page apps (and statically generated sites). We'll go through the UX 📱, business 🧳, and product development 👩🏿‍💻perspectives. &lt;strong&gt;You'll learn when you should opt for server-side rendering, when statically generated sites are a better choice, and under which circumstances you'll be better off with a "basic" SPA.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the pros of SSR? 👍🏽
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Improved UX/Speed 🏎
&lt;/h3&gt;

&lt;p&gt;The first argument which favours using SSR is the improved page speed. &lt;/p&gt;

&lt;p&gt;If you navigate to a single-page application in your browser, the browser will first fire a request to download the HTML and JavaScript, and only after the JavaScript is downloaded and evaluated, it can fire an additional request to fetch some data from your API. Meanwhile, the user is presented with a blank screen, spinner or skeleton 💀. &lt;/p&gt;

&lt;p&gt;When you visit a website which uses SSR, the browser will fire a request, but, unlike with the SPAs, the response contains all you need -- JavaScript files, HTML content &lt;em&gt;and&lt;/em&gt; your data. &lt;strong&gt;There are no spinners, skeletons -- no elements jumping around 🤸🏽‍♂️. The content is delivered faster and the time to the first paint improves.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, like with every tool, it might be an overkill for your use-case. Think about if improving your page load by some hundreds of milliseconds is worth it. &lt;strong&gt;It might be crucial in for e-commerce sites&lt;/strong&gt; (which are in an extremely competitive environment), &lt;strong&gt;but might be an overkill for application which are only usable after logging in&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With the growing popularity of the &lt;a href="https://jamstack.org/"&gt;JAM Stack&lt;/a&gt;, you can get similar benefits (even better) in terms of speed for pages which don't require to be highly dynamic -- blogs, marketing sites or even some e-commerce sites.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Better for SEO (controversial 🧐)
&lt;/h3&gt;

&lt;p&gt;I've seen the SEO argument being used countless times, but frankly, I don't believe it is such a big deal all the time. Let's first clarify why some people claim it to be a big deal.&lt;/p&gt;

&lt;p&gt;The way Google (and other) crawlers 🦎 (which are scraping your website to display it in the search results) has &lt;em&gt;traditionally&lt;/em&gt; worked is following:&lt;br&gt;
1) Visit a website&lt;br&gt;
2) Read the HTML delivered from the server/CDN&lt;br&gt;
3) Save it.&lt;/p&gt;

&lt;p&gt;Problems arose as libraries like React or Vue came into existence. As described in &lt;a href="https://dev.to/tomdohnal/migrating-to-ssr-next-js-part-1-3-what-is-ssr-and-how-it-differs-from-other-approaches-50fa"&gt;the previous blog post&lt;/a&gt;, almost no HTML is received in the first response from the server/CDN. It's only after JavaScript gets executed that you can see some meaningful  content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that's the root of the SEO problem -- crawlers would only see the one div or a spinner and wouldn't wait for the actual content to show up. Therefore, your page wouldn't get properly indexed. However, this is no longer the case with the Google crawler as it waits ⏳ for all the content to load up (including the one dynamically generated by JavaScript).&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Where it might still be &lt;em&gt;necessary&lt;/em&gt; is if you want to get a preview of your page when sharing to social media. But if this were your only concern, I think &lt;em&gt;prerendering&lt;/em&gt; using a tool like &lt;a href="https://github.com/stereobooster/react-snap"&gt;react-snap&lt;/a&gt; might be a better solution. 💡&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may &lt;em&gt;still&lt;/em&gt; get some SEO improvements by using SSR even for crawlers which wait until all the content loads up. Indirectly -- &lt;strong&gt;if the search ranking algorithm accounts for the page speed&lt;/strong&gt; (which should improve when using SSR), &lt;strong&gt;your site should rank higher 📈&lt;/strong&gt; in the search results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What are the cons of SSR? 👎🏻
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The need for a server 🖱
&lt;/h3&gt;

&lt;p&gt;As opposed to the "traditional" SPAs where you don't even &lt;em&gt;need&lt;/em&gt; a server to run your code, &lt;strong&gt;you need a server to render the code on the server (it's called &lt;em&gt;server&lt;/em&gt; side rendering after all...). What this means is that you have to pay 💰💰💰 for a server to execute your "front-end" code.&lt;/strong&gt; If you already have a server, the resource consumption might go up. &lt;/p&gt;

&lt;p&gt;What can you do about it? Well, think about if SSR is the right solution for your use-case. You might be better off leveraging JAM Stack or a traditional SPA. Or, with the &lt;a href="https://nextjs.org/blog/next-9-3"&gt;new 9.3 Next.js release&lt;/a&gt;, you can easily combine SSR with static pages which prevents wasting 🗑 server resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's harder for the development (sometimes) 😵
&lt;/h3&gt;

&lt;p&gt;If you were to roll your own SSR solution, you might be surprised that it's not as straightforward as creating a "traditional" SPA. You have to take care of rendering the components to HTML, sending them to the browser, &lt;a href="https://reactjs.org/docs/react-dom.html#hydrate"&gt;hydration&lt;/a&gt;, making sure that you can fetch the data both on the server and the client... 😿&lt;/p&gt;

&lt;p&gt;Of course, if you use frameworks like Next.js or Nuxt.js, they abstract a lot of these pain points away so you don't have to worry about them 😌. However, for larger projects which want to start using SSR or which were using SSR before these frameworks existed, the migration process to such a framework might seem daunting and they need to implement SSR by themselves. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this acricle, we explored which applications benefit from using SSR and what are the potential downsides. My personal view is that the need for SSR gradually decreases 📉. Especially, it's really easy to use statically generated sites with &lt;a href="https://nextjs.org/blog/next-9-3"&gt;the newest edition of Next.js&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>ssr</category>
    </item>
    <item>
      <title>SSR (Next.js) - part 1/2: WHAT IS SSR AND HOW IT DIFFERS FROM OTHER APPROACHES?</title>
      <dc:creator>Tom Dohnal</dc:creator>
      <pubDate>Thu, 02 Apr 2020 21:35:45 +0000</pubDate>
      <link>https://dev.to/tomdohnal/migrating-to-ssr-next-js-part-1-3-what-is-ssr-and-how-it-differs-from-other-approaches-50fa</link>
      <guid>https://dev.to/tomdohnal/migrating-to-ssr-next-js-part-1-3-what-is-ssr-and-how-it-differs-from-other-approaches-50fa</guid>
      <description>&lt;p&gt;In this series of articles, I'm going to go through the &lt;em&gt;what&lt;/em&gt;, &lt;em&gt;why&lt;/em&gt;, and &lt;em&gt;how&lt;/em&gt; of the migration process of our React web application 💻 to a server-side rendering solution. You'll learn what SSR  is, how it differs from the "client-only" single-page applications and "regular" web apps, what are its pros and cons, and, finally, how to go about &lt;strong&gt;migrating an existing React app to an SSR solution (Next.js).&lt;/strong&gt; (The concepts are the same for Vue apps (and Nuxt.js) or similar. 😉)&lt;/p&gt;

&lt;h2&gt;
  
  
  What SSR even is? 🤔
&lt;/h2&gt;

&lt;p&gt;To fully understand what SSR is, we'll first explore the differences between how "client-only" single-page applications (SPAs) and "regular" web apps are delivered to the browser and presented to the user.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  "Regular" web apps 🖥
&lt;/h3&gt;

&lt;p&gt;Let's start with "regular" web apps. What I mean by this term is apps rendered on the server, usually using a language like PHP, Java ☕️, Ruby 💎, Node.js etc. and some templating language on top of HTML.&lt;/p&gt;

&lt;p&gt;When you type in an address to this kind of an app or click a link pointing to it in your browser, the response of the app's server will contain all the HTML that you see in the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L-Wu3mgL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/00q1pv5oueq6b7aofll1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L-Wu3mgL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/00q1pv5oueq6b7aofll1.png" alt="Alt Text" title="Regular app diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check it yourself --- go to &lt;a href="https://en.wikipedia.org/wiki/Main_Page"&gt;Wikipedia&lt;/a&gt; 📖 (it's built using PHP), right-click anywhere on the page and choose "View source code" 👀. You'll see the HTML response that your browser received from the server and it contains &lt;em&gt;all&lt;/em&gt; the content that you see on the page.&lt;/p&gt;



&lt;h3&gt;
  
  
  "Client-only" SPAs ⚛️
&lt;/h3&gt;

&lt;p&gt;On the opposite side of the spectrum 🌈, there are the "client-only" single-page apps. Those are for example applications bootstrapped with &lt;code&gt;create-react-app&lt;/code&gt; or &lt;code&gt;@vue/cli&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you navigate to one of these pages, the response of the server (or CDN) will only contain one &lt;code&gt;div&lt;/code&gt; element (+ maybe some &lt;code&gt;meta&lt;/code&gt; tags or a loader). You might now be wondering -- does it mean that you will only be able to see one &lt;code&gt;div&lt;/code&gt; on their screen? 😨 No, of course not. I didn't mention another important thing which gets fetched in the response. It is a &lt;code&gt;script&lt;/code&gt; tag pointing to the JavaScript bundle. The moment the browser gets the response, the JavaScript engine kicks in 💥 and (using a library like React or Vue) builds the page for you (using a bunch of &lt;code&gt;document.createElement(...)&lt;/code&gt; calls or similar).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CJs6kATN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4cq7ribsfr5bdjgpjsak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CJs6kATN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4cq7ribsfr5bdjgpjsak.png" alt="Alt Text" title="Client-only SPA diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An example of such an application is Netlify. When you visit &lt;a href="https://app.netlify.com/"&gt;its web app&lt;/a&gt; and view the source code, you'll see just a small number of &lt;code&gt;div&lt;/code&gt; elements, &lt;code&gt;script&lt;/code&gt; tags etc. The actual content you see on your screen is built dynamically using JavaScript (React ⚛︎ in this case).&lt;/p&gt;



&lt;h3&gt;
  
  
  Server-side rendered SPAs 🎶
&lt;/h3&gt;

&lt;p&gt;Now that we have an understanding of what "regular" web apps and "client-only" SPAs are, we can proceed to server-side rendered SPAs. As you might have guessed, it is a mixture 🥣 of both approaches which tries to bring you the best of both of the worlds. Let's see how it works.&lt;/p&gt;

&lt;p&gt;The TLDR that I like to use is as follows: It behaves as a "regular" web app on the first render and as a "client-only" SPA afterwards ⏩.&lt;/p&gt;

&lt;p&gt;But what does it really mean? Well, if you visit such a website, your browser will receive a response which already contains all the HTML that is presented on that site. Just like with the "regular" web apps we talked about earlier. Then, the browser will execute the JavaScript code written in React, Vue or similar and start a process called hydration 💦. During this process, it will attach all your listeners  (&lt;code&gt;onClick&lt;/code&gt; etc in React or &lt;code&gt;@click&lt;/code&gt; etc in Vue) on the HTML elements which were delivered to the browser. After the hydration process is completed, the page behaves like a fully interactive SPA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nfa_gdtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/irppqufr8g2hgevd3iv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nfa_gdtK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/irppqufr8g2hgevd3iv7.png" alt="Alt Text" title="Server-side rendering diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An example of such a website is jobs.netflix.com (they use React with Next.js). When you go there, you don't see a spinner or a white screen but all the content appears instantly. Moreover, the whole page is fully interactive and the page transitions don't trigger a reload in the browser.&lt;/p&gt;

&lt;p&gt;How can you make your application leverage server-side rendering? This topic will be covered in the subsequent blog post. (You can do it all in plain React/Vue and Node.js but it's &lt;em&gt;waaay&lt;/em&gt; easier with libraries such as Next.js or Nuxt.js respectively)&lt;/p&gt;



&lt;h3&gt;
  
  
  Statically exported sites 🍓
&lt;/h3&gt;

&lt;p&gt;The list of different ways to architecture and deliver a web application could not be complete without at least mentioning statically exported sites. They are oftentimes written using so-called JAM Stack (JavaScript + API + Markdown) and bootstrapped using tools like Next.js, Gatsby.js, or Nuxt.js.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zpupshX2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6a1nfmg1cpj1iolcx3zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zpupshX2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6a1nfmg1cpj1iolcx3zz.png" alt="Alt Text" title="Statically exported site diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How do they differ from all the other approaches? Well, with these sites, all the HTML is delivered to the browser during the first render, just like with "regular" web apps or "server-rendered" SPAs. What's different is that there is no server running, creating these files on every request using a templating tool and sending them to the browser. Instead, you generate all the files at the build time 🛠, put them on the CDN and have them delivered right to your users' browsers. Basically, it's autogenerating HTML files. 😊&lt;/p&gt;



&lt;h2&gt;
  
  
  Conclusion ✍️
&lt;/h2&gt;

&lt;p&gt;I hope I managed to shed some light on &lt;em&gt;what SSR is&lt;/em&gt; as well as describe some of the other approaches for delivering web apps to the browsers. There is &lt;em&gt;no finite&lt;/em&gt; list of the "patterns" and there are always new ones emerging.&lt;/p&gt;

&lt;p&gt;Of course, every application is different and there are pros and cons for each approach. You should always choose what suits 👔 &lt;em&gt;your&lt;/em&gt; needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the next article, we're going to have a look at the pros and cons of using server-side rendering.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>firstpost</category>
    </item>
  </channel>
</rss>
