<?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: George Francis</title>
    <description>The latest articles on DEV Community by George Francis (@georgedoescode).</description>
    <link>https://dev.to/georgedoescode</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%2F361652%2F127850ae-49cf-4ffa-934d-3209f3790010.jpg</url>
      <title>DEV Community: George Francis</title>
      <link>https://dev.to/georgedoescode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/georgedoescode"/>
    <language>en</language>
    <item>
      <title>CodePen - Wibbly Wobbly SVG Jelly ✨</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Wed, 19 May 2021 07:43:54 +0000</pubDate>
      <link>https://dev.to/georgedoescode/wibbly-wobbly-svg-jelly-1fe1</link>
      <guid>https://dev.to/georgedoescode/wibbly-wobbly-svg-jelly-1fe1</guid>
      <description>&lt;p&gt;This lil' jelly character is an example from my upcoming tutorial “Creating a Liquid Hover Effect with GSAP &amp;amp; SVG“ — stay tuned for updates! 👀&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/MWpjVgB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Introducing... My New Site! ✨</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Fri, 07 May 2021 14:20:04 +0000</pubDate>
      <link>https://dev.to/georgedoescode/introducing-my-new-site-5g8g</link>
      <guid>https://dev.to/georgedoescode/introducing-my-new-site-5g8g</guid>
      <description>&lt;p&gt;Check out the site here! &lt;a href="https://georgefrancis.dev/"&gt;https://georgefrancis.dev/&lt;/a&gt; 👀&lt;/p&gt;




&lt;p&gt;Hey! How's it going? I've been a little quiet on DEV recently, but... I'm very happy to finally share why! 🎉&lt;/p&gt;

&lt;p&gt;Well, as you might have noticed from the big ol' title/URL above, I have launched my very own site! As much as I love DEV 💛, and think it's a fantastic place to publish, I have found myself wanting a singular home for all of my CodePens, articles, and other bits and pieces — so I decided to build one. &lt;/p&gt;

&lt;p&gt;The site is built with &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;, hosted on &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;, and is finished off with a healthy scoop of generative magic ✨ It features all of my past writing from DEV, and will be the best place to catch any new content from me going forward. &lt;/p&gt;

&lt;p&gt;Honestly, I could chat forever about the design process, tech stack, etc, &lt;em&gt;(and maybe I will someday)&lt;/em&gt; but for now, I'd just like to share the site with y'all! If you do have any specific questions, though, please do give me a shout. I'm always happy to chat.&lt;/p&gt;

&lt;p&gt;Anyway, now that the site is launched, I am starting to rattle through my ever-growing Trello list of article ideas, so expect some fresh new creative coding/generative art content from me soon 🎨&lt;/p&gt;

&lt;p&gt;In case you missed it up there ^ &lt;a href="https://www.georgefrancis.dev"&gt;here's a link to the site.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers! &lt;/p&gt;

&lt;p&gt;George 👀&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>css</category>
      <category>news</category>
    </item>
    <item>
      <title>CodePen - A Very Wobbly Liquid SVG Button ✨</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Fri, 16 Apr 2021 11:16:29 +0000</pubDate>
      <link>https://dev.to/georgedoescode/a-very-wobbly-liquid-svg-button-5818</link>
      <guid>https://dev.to/georgedoescode/a-very-wobbly-liquid-svg-button-5818</guid>
      <description>&lt;p&gt;This very wobbly button makes use of vectors, catmull-rom splines and linear interpolation to create an entirely vector based "liquid" button.&lt;/p&gt;

&lt;p&gt;Toggle the debug mode to see how it works!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/yLgExbV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>CodePen - Generative SVG Noise Grid Pattern Maker 🎨</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Thu, 08 Apr 2021 08:07:00 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-generative-svg-noise-grid-pattern-maker-1nhd</link>
      <guid>https://dev.to/georgedoescode/codepen-generative-svg-noise-grid-pattern-maker-1nhd</guid>
      <description>&lt;p&gt;I'm a huge fan of these kinds of noisy grid patterns, and I wanted to add some to my in-progress personal site. Rather than tinkering away in Figma, I thought I would make a little generator. &lt;/p&gt;

&lt;p&gt;I hope some other folks find it useful! 🚀&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/dyNVNjG?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>design</category>
    </item>
    <item>
      <title>CodePen - Fuzzy VHS Dream Clouds 📼 ☁️ [PIXI]</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Fri, 19 Mar 2021 09:34:08 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-fuzzy-vhs-dream-clouds-pixi-398</link>
      <guid>https://dev.to/georgedoescode/codepen-fuzzy-vhs-dream-clouds-pixi-398</guid>
      <description>&lt;p&gt;I'm not really sure what this is... but I kinda like it. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/RwozaEO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>CodePen - Generative macOS Big Sur Waves 🌊 [SVG]</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Sat, 13 Mar 2021 08:34:01 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-generative-macos-big-sur-waves-svg-413e</link>
      <guid>https://dev.to/georgedoescode/codepen-generative-macos-big-sur-waves-svg-413e</guid>
      <description>&lt;p&gt;This is a generative program that creates macOS Big Sur style wave backgrounds. Each image is random within constraints 🎲&lt;/p&gt;

&lt;p&gt;The waves generated here may not always look perfect, but they are unique! If you find an output you like, you can copy the SVG to your clipboard using the download button 🚀&lt;/p&gt;

&lt;p&gt;Interested in a tutorial on how I made this? Let me know! &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/bGBzGKZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>A Generative SVG Starter Kit</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Thu, 11 Mar 2021 12:09:30 +0000</pubDate>
      <link>https://dev.to/georgedoescode/a-generative-svg-starter-kit-5cm1</link>
      <guid>https://dev.to/georgedoescode/a-generative-svg-starter-kit-5cm1</guid>
      <description>&lt;p&gt;SVG is a fantastic medium for generative art. It can scale to any resolution, is a joy to debug, and has a multitude of incredible filters/effects built-in. &lt;/p&gt;

&lt;p&gt;This post aims to provide you with all the tools you need to start creating your own generative SVG art/design. Unlike my other tutorials, we won't be creating one single example here. Rather, we will be examining a collection of libraries, utility functions, and techniques that once learned can be used to create anything you like!&lt;/p&gt;

&lt;p&gt;Sound good? Let's do it 🎨&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Psst! I wrote this article after talking about generative SVG in the wonderful &lt;a href="https://viewbox.club/"&gt;viewBox newsletter&lt;/a&gt;. Be sure to check out the issue &lt;a href="https://buttondown.email/viewBox/archive/a56db097-f200-4915-bf29-1817df7b517e"&gt;here&lt;/a&gt; for more generative treats. &lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Who is this starter kit for? 
&lt;/h2&gt;

&lt;p&gt;Generative art savant, who is somewhat new to SVG? SVG magician, who is dipping their toe into the generative art ocean? There is something here for everyone!&lt;/p&gt;

&lt;p&gt;No prior generative art knowledge is necessary to make the most out of this post. Some basic SVG knowledge (drawing shapes, giving them a fill color, etc) will be helpful, though. To make the most out of this starter kit, you'll need a working knowledge of HTML/CSS/JS, too. &lt;/p&gt;

&lt;p&gt;If you are &lt;em&gt;completely&lt;/em&gt; new to SVG, I recommend reading through this &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial"&gt;MDN Tutorial&lt;/a&gt;. Keeping an eye on the docs as a reference, experiment in a &lt;a href="https://codepen.io/"&gt;CodePen&lt;/a&gt;. Draw some simple shapes, move them around, color them in. SVG is a markup language like HTML, and it's a lot less scary than it seems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Show me the code! 
&lt;/h2&gt;

&lt;p&gt;If you would like to skip ahead and dive in with creating using this starter pack, I got you. Here's a CodePen with all the utility functions and HTML/CSS setup included. Hit &lt;code&gt;fork&lt;/code&gt; to get started right away.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/abBQxBj?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I know, it doesn't look like much right now, but there's a ton to unpack here... &lt;/p&gt;

&lt;p&gt;Onwards! &lt;/p&gt;




&lt;h2&gt;
  
  
  What is generative art? 
&lt;/h2&gt;

&lt;p&gt;For some folks reading this post, the term &lt;em&gt;“Generative Art”&lt;/em&gt; may be an unfamiliar one. If you are familiar with a generative approach to art/design already, feel free to skip this section. &lt;/p&gt;

&lt;p&gt;If not — here's a quick example...&lt;/p&gt;

&lt;p&gt;Say, you are a painter. You have some dice and 6 colors in your palette. You roll the dice. Based on how the dice lands, you choose one of the 6 colors and paint a stripe on your canvas. If the dice reads “1” you always paint a blue stripe, “2” and you paint a red stripe, and so on. You continue this process until your canvas is full.&lt;/p&gt;

&lt;p&gt;That's all generative art is. Art created with an element of autonomy/chance. There are no rules, aside from the ones &lt;em&gt;you define&lt;/em&gt;. Generative art doesn't even need to digital. Computers only happen to be wonderful companions for this type of creation. Why? They are fantastic at performing repetitive tasks, fast. &lt;/p&gt;

&lt;p&gt;To illustrate the above, here's a simple CodePen that “paints” random stripes on a canvas: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/vYyQMaE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Try clicking the regenerate button. Pretty speedy right? The computer re-renders the image, with a random result, in a matter of milliseconds. Far more efficient than a squishy human painting on a physical canvas! This kind of speed is invaluable when exploring more complex emergent behavior/patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  A blank canvas 
&lt;/h2&gt;

&lt;p&gt;Most paintings start with a blank canvas of some kind. When working with generative SVG, that canvas is an &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element on a web page. Here's how I set up the HTML/CSS for almost all my generative SVG work.&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;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 200 200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, in the HTML, we have an &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element with a single attribute set, &lt;code&gt;viewBox&lt;/code&gt;.  This attribute defines a coordinate space. In our case, the coordinate space has a width of 200 units and a height of 200 units.&lt;/p&gt;

&lt;p&gt;Once defined, we “draw” everything in the SVG element relative to its viewBox. The SVG will then scale its contents to &lt;em&gt;any&lt;/em&gt; resolution. This is one of SVG's most handy features, especially when it comes to generative art. A single SVG can produce a huge physical print or render on a narrow mobile screen!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;I'm keeping things somewhat high-level here. If you would like to read more about the viewBox attribute, check out&lt;/em&gt; &lt;a href="https://css-tricks.com/scale-svg/"&gt;&lt;em&gt;this article&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on CSS tricks.&lt;/em&gt;&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="o"&gt;*&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;padding&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;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&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;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&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;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;place-items&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="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;96%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.canvas&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;75vmin&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;75vmin&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="n"&gt;hsl&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="m"&gt;0%&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, in the CSS, we have a small selection of styles that achieve 2 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Make sure the SVG element is a perfect square that always fits within the viewport. Slap-bang in the middle. Perfect for CodePens!&lt;/li&gt;
&lt;li&gt; Give the SVG element a white fill, and set the page background to a very light grey color. This is to help visualize the canvas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it! This HTML/CSS setup is everything you need to get started with generative SVG. It's simple, flexible, and will make sure your work looks great on everyone's screen. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;A 200x200 unit canvas is my preference and completely arbitrary. Not feeling the square? Experiment with your own viewBox units and aspect ratios/element sizes.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  An SVG paintbrush 
&lt;/h2&gt;

&lt;p&gt;If the SVG element is our canvas, &lt;a href="https://svgjs.com/docs/3.0/"&gt;SVG.js&lt;/a&gt; is our paintbrush. When working on generative art, you will need to create elements (such as a &lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; or a &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;) in a dynamic way. &lt;/p&gt;

&lt;p&gt;Say you would like to create shapes as part of a loop. You create a for-loop that iterates 100 times. Within each iteration, you choose a random number between 0 and 1. If that number is greater than 0.5, you draw a rectangle. If it is less than 0.5, you draw a circle.&lt;/p&gt;

&lt;p&gt;As SVG is a markup language, there is no real way of handling this kind of conditional/real-time rendering built-in. That's where JavaScript, by way of SVG.js, comes in to help.&lt;/p&gt;

&lt;p&gt;Scripting SVG with JavaScript alone can be tedious. SVG.js provides a terse, easy-to-use way of creating/removing/updating SVG elements. That's it. It provides close to complete coverage of the SVG spec and is a joy to work with. &lt;/p&gt;

&lt;p&gt;Here's an excerpt of the JS required for the above stripes program, &lt;em&gt;without&lt;/em&gt; SVG.js:&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;width&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="nx"&gt;stripeWidth&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;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElementNS&lt;/span&gt;&lt;span class="p"&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="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stripeWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&lt;/span&gt;&lt;span class="dl"&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;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stroke&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="nx"&gt;svgElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rect&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;Here's an excerpt of the JS required for the above stripes program, &lt;em&gt;with&lt;/em&gt; SVG.js:&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;width&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="nx"&gt;stripeWidth&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;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stripeWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;x&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="nf"&gt;y&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="nf"&gt;fill&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="nf"&gt;stroke&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ah, Much better 🧘&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you would prefer to reduce your dependencies, working with just JavaScript is completely fine. There are likely some more elegant ways of handling the above but personally, I prefer to offload my SVG scripting and focus on the creative stuff.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG.js in the wild
&lt;/h3&gt;

&lt;p&gt;To demonstrate what is possible with SVG.js, I have a couple of amazing CodePens here from &lt;a href="https://twitter.com/liamegan"&gt;Liam Egan&lt;/a&gt;. These pens are a fantastic example of how beautiful generative SVG can be, and how powerful SVG.js is in a generative context.&lt;/p&gt;

&lt;p&gt;“Grow 4”&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/shubniggurath/embed/abByPXz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;“Flare 2”&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/shubniggurath/embed/poNWONd?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Be sure to check out &lt;a href="https://codepen.io/shubniggurath"&gt;Liam's CodePen&lt;/a&gt; for more! 🖊&lt;/p&gt;




&lt;h2&gt;
  
  
  4 utility functions... endless possibilities 
&lt;/h2&gt;

&lt;p&gt;So, we have a responsive blank canvas and an awesome way of adding to it. What next? Some helpful functions to decide &lt;em&gt;what&lt;/em&gt; to render would be great.&lt;/p&gt;

&lt;p&gt;First off, a quick note. There's a common misconception that generative art is &lt;em&gt;super complex 🤯&lt;/em&gt; and you need to be some kind of math whizz to do it. Well, to quote the great Dwight Shrute... &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;FALSE&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You don't. I promise it's not as scary as it seems. Armed with the 4 functions/examples taught here you will have all you need to make beautiful works of art. No crazy math skills required. Creativity is the most important ingredient in delicious generative art.&lt;/p&gt;

&lt;p&gt;I have added the source code for all these functions to &lt;a href="https://github.com/georgedoescode/generative-utils"&gt;this repository&lt;/a&gt;. They are also available as an &lt;a href="https://www.npmjs.com/package/@georgedoescode/generative-utils"&gt;NPM package&lt;/a&gt; for ease of installation. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;This is not an “official” library, so please don't expect tests, documentation, etc... yet! 👀&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  random() 
&lt;/h3&gt;

&lt;p&gt;This is a stone-cold generative classic. My version of &lt;code&gt;random()&lt;/code&gt; can do two things; return a random number within a range, or return a random item from an array. &lt;/p&gt;

&lt;p&gt;Here's how you can use it to produce a random number within a range: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/poNqRxg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here's how you can use it to pick a random item from an array: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/WNoLRWb?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Cool! This simple function will be a loyal companion on your generative journey. You could use it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Generate a random radius for a &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Position an object at a random position within an SVG &lt;/li&gt;
&lt;li&gt;  Pick a random fill color from a pre-defined array of values&lt;/li&gt;
&lt;li&gt;  Rotate an element by a random amount &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this function is new to you, fork the starter CodePen and experiment for a while!&lt;/p&gt;

&lt;h3&gt;
  
  
  map() 
&lt;/h3&gt;

&lt;p&gt;This is a super helpful function, especially when dealing with user interaction. It does 1 thing — map a number that usually exists in one range to another. This is a little tricky one to explain, so here's a CodePen:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/RwoEKzE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this example, we use &lt;code&gt;map()&lt;/code&gt; to modulate an ellipse's width/height based on the user's mouse position. Dig into the JavaScript for a practical example of how &lt;code&gt;map()&lt;/code&gt; works 👀&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;map()&lt;/code&gt; is fantastic for dealing with user input, it can also be helpful in a bunch of other contexts. You could use it to: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Set an element's size based on how far it is from another&lt;/li&gt;
&lt;li&gt;  Map temperature data from a weather API to the opacity of a yellow circle... like the sun! &lt;/li&gt;
&lt;li&gt;  Animate an element on scroll by mapping the current scroll position to a more useful (random?) range&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, if this function is new to you, have a play. Fire up a new CodePen and experiment! &lt;/p&gt;

&lt;h3&gt;
  
  
  spline() 
&lt;/h3&gt;

&lt;p&gt;If you have read through any of my tutorials, or checked out my CodePen profile, you have seen &lt;code&gt;spline()&lt;/code&gt; in action. I'm obsessed. It's the best. &lt;/p&gt;

&lt;p&gt;What does it do? It draws a perfect, smooth curve between any set of points. It's incredible for creating organic, soft shapes. Here's a simple example of &lt;code&gt;spline()&lt;/code&gt; in action: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/zYoyZrp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We store an array of random &lt;code&gt;{ x, y }&lt;/code&gt; coordinates (thank you &lt;code&gt;random()&lt;/code&gt;) and use &lt;code&gt;spline()&lt;/code&gt; to draw a smooth curve through them. Nice. You may already see how this could be great for data-visualization, but spline can do so much more. &lt;/p&gt;

&lt;p&gt;In this CodePen, I use &lt;code&gt;spline()&lt;/code&gt; to creating an undulating SVG blob: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/oNzamjV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/georgedoescode/tutorial-build-a-smooth-animated-blob-using-svg-js-3pne"&gt;You can check out the tutorial for this CodePen here. &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, I use &lt;code&gt;spline()&lt;/code&gt; to create generative bodies for little blob characters: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/dypjOgv?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/georgedoescode/tutorial-generative-blob-characters-using-svg-1igg"&gt;You can check out the tutorial for this CodePen here. &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool! As per usual, experiment with this function and see what cool stuff you can create. You could even follow along with one of the above tutorials if you like.&lt;/p&gt;

&lt;h3&gt;
  
  
  pointsInPath() 
&lt;/h3&gt;

&lt;p&gt;This is a new addition to my generative utility belt. It returns an array of equidistant points plotted on an SVG &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; element. This is amazing, as it allows you to create your very own, generative, stroke styles. &lt;/p&gt;

&lt;p&gt;Here's a demo of this technique that I put together for the wonderful viewBox newsletter: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/LYbdXJR?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Have a quick look around the source code of the above CodePen. You can see how well &lt;code&gt;random()&lt;/code&gt; works alongside &lt;code&gt;pointsInPath()&lt;/code&gt;. Magical! &lt;/p&gt;




&lt;h2&gt;
  
  
  Color
&lt;/h2&gt;

&lt;p&gt;Some folks love working in black and white, and that's awesome. Me... I like things to be bright and colorful. I don't have a fixed approach to color in generative art, but I love to use HSL as a format.&lt;/p&gt;

&lt;p&gt;Why? HSL is far more intuitive, to me than HEX or RGB. I won't go on an HSL deep dive here, but I explain how it works in detail in &lt;a href="https://dev.to/georgedoescode/a-beginner-s-guide-to-applying-color-in-ui-design-3904#working-with-hsl%C2%A0"&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using JS &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template literals&lt;/a&gt; and HSL, one can form generative color palettes in a few lines of code. Here's an example:  &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/BaQvWdo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this example, we are making use of &lt;code&gt;random()&lt;/code&gt; to pick a “base” random hue. We then create 3 template literal colors, each with a hue 120 degrees apart. The technical term for this is a “triadic” color palette. This is a classic, simple, way of choosing colors that look great together.&lt;/p&gt;

&lt;p&gt;You can extend this method to use many other steps of rotation... for more information about color theory, and using a color wheel, check out &lt;a href="https://www.canva.com/colors/color-wheel/"&gt;this article&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Say, for example, you wanted to use an analogous color palette &lt;em&gt;(3 hues, each 30 degrees apart)&lt;/em&gt;, the code would look like this: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/NWbepMb?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;


&lt;h2&gt;
  
  
  Animation
&lt;/h2&gt;

&lt;p&gt;So far, we have only focused on the static creation of visual elements. For a lot of stuff, this is great! I love to create still generative images. Sometimes, though, you gotta get things moving around.&lt;/p&gt;

&lt;p&gt;Generative animation is a huge subject and deserves a post of its own. For now, though, here's an overview of the two primary ways I work with animation...&lt;/p&gt;
&lt;h3&gt;
  
  
  Method 1, the animation loop
&lt;/h3&gt;

&lt;p&gt;For some sketches, like the undulating blob I referenced earlier, I use an animation loop. An animation loop in JavaScript usually looks something like this:&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;animate&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="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&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;What's happening here? The function &lt;code&gt;animate()&lt;/code&gt; calls itself over-and-over again, somewhere around 60 FPS. It does so using the browser method &lt;code&gt;requestAnimationFrame&lt;/code&gt;. Within this function, you can update variables and move things around. &lt;/p&gt;

&lt;p&gt;I won't be diving too deep into &lt;code&gt;requestAnimationFrame&lt;/code&gt; here, but &lt;a href="https://css-tricks.com/using-requestanimationframe/"&gt;here is a great CSS tricks article&lt;/a&gt; if you would like to learn more.&lt;/p&gt;

&lt;p&gt;Here's a simple CodePen to show how you can use an animation loop to move a &lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; around the screen: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/eYBbvPr?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2, GSAP
&lt;/h3&gt;

&lt;p&gt;Recently, I have been turning to the animation library &lt;a href="https://greensock.com/"&gt;GSAP&lt;/a&gt; to handle some of my animations. GSAP is super powerful, flexible, and lends itself well to generative work. It also has fantastic easing presets baked in. &lt;/p&gt;

&lt;p&gt;I won't go into detail demonstrating GSAP, as it already has comprehensive documentation. It is worth linking, though, to its &lt;a href="https://greensock.com/docs/v3/GSAP/UtilityMethods"&gt;utility functions page&lt;/a&gt;. There's some great stuff here, including some similar functions to the utilities we explored earlier. &lt;/p&gt;

&lt;p&gt;Here's a quick CodePen demonstrating some generative GSAP animation:  &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/qBqLrGG?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;You made it to the end! Congratulations. That was a real whirlwind generative tour. You are now set up with all the technical stuff you need to make wonderful generative art. But what about, like... inspiration? &lt;/p&gt;

&lt;p&gt;If I am struggling for ideas, I look to artists/designers I love. I find a piece of theirs I like; examine its structure, the colors, the shapes, the texture, and go from there. How could you make a piece generative? Good artists borrow, etc...&lt;/p&gt;

&lt;p&gt;Another great avenue of exploration if you are stuck for inspiration is &lt;a href="https://dribbble.com/"&gt;Dribbble&lt;/a&gt;. Dribbble is an absolute goldmine of fresh new design trends. This stuff can be a great source of inspiration for generative work.&lt;/p&gt;

&lt;p&gt;Finally, here's a list of generative learning resources. There's enough content here to take you far into your generative journey! &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw"&gt;The Coding Train&lt;/a&gt; - I learned to code watching this channel. Dan has fantastic videos on almost every generative subject you could think of.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://tylerxhobbs.com/essays"&gt;Tyler Hobbs&lt;/a&gt; - Tyler is a fantastic artist who writes some incredible essays. A veritable banquet of generative treats.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://natureofcode.com/"&gt;The Nature Of Code&lt;/a&gt; - An excellent book on simulating natural systems in code.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/georgedoescode"&gt;More from me!&lt;/a&gt; - Total shameless plug right here. I write a lot of generative tutorials, so if you enjoyed this one be sure to check them out.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  So long! 
&lt;/h2&gt;

&lt;p&gt;Thank you for taking the time to read this article. I hope you have learned some cool new techniques, and I can't wait to see what you make with them! &lt;/p&gt;

&lt;p&gt;If you do make anything with this stuff, please do send it my way. There's nothing I love more than seeing what people do with my tutorials. It's always &lt;em&gt;far&lt;/em&gt; more interesting than what I create to start with! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enjoyed this tutorial? Follow me on Twitter&lt;/strong&gt; &lt;a href="https://twitter.com/georgedoescode"&gt;&lt;strong&gt;@georgedoescode&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;for more front-end/creative coding content 🎨 &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial took around 10 hours to put together, all in. If you would like to support my work you can&lt;/em&gt; &lt;a href="https://ko-fi.com/georgedoescode"&gt;&lt;em&gt;buy me a coffee.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>CodePen - A Simple SVG Blob Editor [GSAP]</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Sat, 06 Mar 2021 07:59:45 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-a-simple-svg-blob-editor-gsap-316o</link>
      <guid>https://dev.to/georgedoescode/codepen-a-simple-svg-blob-editor-gsap-316o</guid>
      <description>&lt;p&gt;I have been wanting to try GSAP for a while, so I made a simple little “spline” editor as a test... It works best in Chrome + Safari!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/ExNpqJP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A beginner's guide to applying color in UI design</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Thu, 25 Feb 2021 12:28:41 +0000</pubDate>
      <link>https://dev.to/georgedoescode/a-beginner-s-guide-to-applying-color-in-ui-design-3904</link>
      <guid>https://dev.to/georgedoescode/a-beginner-s-guide-to-applying-color-in-ui-design-3904</guid>
      <description>&lt;p&gt;Is color theory getting you down? Are you tired of the same old preset palettes? Sick of hitting “regenerate” on a magical color palette creator? &lt;/p&gt;

&lt;p&gt;Don't worry, we've all been there...&lt;/p&gt;

&lt;p&gt;This post hopes to be your virtual guide up the mystical mountain of color. By the time you reach the top, you will have all the skills you need to create beautiful, coherent palettes.&lt;/p&gt;

&lt;p&gt;Sound OK? Let's set off for basecamp.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites 
&lt;/h2&gt;

&lt;p&gt;To make the most out of this tutorial, you should be comfortable working with both HTML and CSS. &lt;/p&gt;




&lt;h2&gt;
  
  
  The format of this tutorial
&lt;/h2&gt;

&lt;p&gt;This tutorial is all about learning by doing. We will be starting with the same base design and adding our own individual style. &lt;/p&gt;

&lt;p&gt;The base design itself is a &lt;em&gt;“product card”&lt;/em&gt;, the likes of which you will likely have come across on a variety of e-commerce sites. It is a simple example but provides an excellent blank canvas to experiment with color. &lt;/p&gt;

&lt;p&gt;I have created a &lt;a href="https://codepen.io/georgedoescode/pen/xxRrdJp"&gt;CodePen&lt;/a&gt; that you can &lt;a href="https://blog.codepen.io/documentation/forks/#:~:text=To%20fork%20a%20Pen%20or,ready%20to%20save%20your%20changes."&gt;fork&lt;/a&gt; to get started. &lt;/p&gt;

&lt;p&gt;Here it is: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/xxRrdJp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Right now, the colors are either black or white. There is no product image and the design has little personality. It's very basic, but that's OK. This is where you come in!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Choosing&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;your&lt;/strong&gt;&lt;/em&gt; &lt;strong&gt;product&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First things first, you should choose an image to replace the question mark. This could be anything — a chocolate bar, a pair of shoes, a tractor, a cool hat... It's up to you. &lt;/p&gt;

&lt;p&gt;I encourage everyone to choose their &lt;em&gt;own&lt;/em&gt; individual product image, though. Why? &lt;/p&gt;

&lt;p&gt;Different products will suit different aesthetics and thus different color palettes. You may choose to add vibrant, bright colors for a candy bar or subdued, calming colors for a yoga mat. By choosing your own aesthetic and palette, you can better learn how to &lt;strong&gt;apply&lt;/strong&gt; the techniques to your own work.&lt;/p&gt;

&lt;p&gt;The starter CodePen comes with &lt;a href="https://twemoji.twitter.com/"&gt;Twemoji&lt;/a&gt; built in to make choosing a product image as easy as possible. If you change the emoji in &lt;code&gt;card__img&lt;/code&gt;, Twemoji will replace it with a high-res SVG version.&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__img"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;❓&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Tip:&lt;/strong&gt; on macOS, you can open an emoji keyboard with &lt;code&gt;ctrl + cmd + space&lt;/code&gt;. On Windows, you can open one with &lt;code&gt;windows/start + .&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm going to choose the “herbs” emoji for my product card. I'm also going to change the card title and meta description to match my choice. &lt;/p&gt;

&lt;p&gt;My product card now looks something like this: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/KKNZMdL?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You should have something similar, but with your own product image/emoji and text content. Nice work! Let's move on up the color mountain. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Working with HSL &lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When working with color, I always reach for HSL. To me, it is the most intuitive way of representing colors in the browser. We will be using HSL throughout this tutorial, too, so here's a quick primer... &lt;/p&gt;

&lt;p&gt;HSL stands for &lt;strong&gt;hue, saturation, lightness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hue&lt;/strong&gt; is the angle of rotation &lt;em&gt;(in degrees)&lt;/em&gt; on a color wheel for a particular color. In the browser, red sits at 0 degrees. Here's an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmta8ze43rejq7y5hkxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmta8ze43rejq7y5hkxk.png" alt="A color wheel, 12 colors" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saturation&lt;/strong&gt; is how “intense” a color is. A lower saturation will appear more grey, a higher saturation more vibrant: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ogxa89s7kl0wngxflg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ogxa89s7kl0wngxflg1.png" alt="A range of colors with different saturation values, ranging from greyed-out to vibrant" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lightness&lt;/strong&gt; is how close to black or white the color is. A value of 0% lightness will always appear black, a value of 100% will always appear white:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5n9jt6lz83tpv0inzk98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5n9jt6lz83tpv0inzk98.png" alt="A range of colors with different lightness values, ranging from dark to light" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We write HSL colors in CSS like this:&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="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* hue, saturation(%), lightness(%) */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;100%&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this is all new to you, don't worry! It can take a little while to get used to HSL, but I promise it is worth it. &lt;/p&gt;

&lt;p&gt;If you feel like you need some practice, spend a little time experimenting. You can do this in a graphics editor such as Figma or Sketch, or right in the browser. Whatever fits with your workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Designing in grayscale
&lt;/h2&gt;

&lt;p&gt;My personal preference when creating a design is to always start with shades of gray. By holding the color until the end, we can focus on our typography, spacing, and content. &lt;/p&gt;

&lt;p&gt;You may notice in the starter CodePen that there are only two colors, black and white. This isn't quite enough to design with, so we need to add some more. Let's not start throwing colors in at random, though...&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Defining the shades of gray&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A good practice when working with color is to define a system up-front. For very small projects like this one, 5 shades of each color should be enough. For larger projects, 9 - 10 shades are best. &lt;/p&gt;

&lt;p&gt;If you check out the &lt;a href="https://tailwindcss.com/docs/customizing-colors"&gt;Tailwind&lt;/a&gt; and &lt;a href="https://material-ui.com/customization/color/#color"&gt;Material UI&lt;/a&gt; documentation you can observe this pattern in the wild.&lt;/p&gt;

&lt;p&gt;To work out some initial shades, let's use a method based on &lt;a href="https://refactoringui.com/previews/building-your-color-palette/"&gt;this article&lt;/a&gt; by the Refactoring UI folks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Choose a middle/base shade -&lt;/strong&gt; There are no set rules here, but try not to go too light or dark. For grays, a lightness of around &lt;strong&gt;40 / 50&lt;/strong&gt; is a good start. I like to make sure this shade has enough contrast for use with text &lt;em&gt;(more on this a little later)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x77gmuvu6tiydcu03eh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x77gmuvu6tiydcu03eh.png" alt="A gray circle" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Choose the darkest and lightest shades -&lt;/strong&gt; Again, there are no right or wrong answers here. I'm using a lightness value of &lt;strong&gt;10&lt;/strong&gt; for my darkest color and &lt;strong&gt;96&lt;/strong&gt; for my lightest:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xth54uh2kfgcma4i9f0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xth54uh2kfgcma4i9f0.png" alt="3 gray circles, their colors moving from light to dark" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Fill in the gaps -&lt;/strong&gt; Finally, choose two more shades that sit between the middle and darkest / lightest colors. The lightness values I have chosen for these two shades are &lt;strong&gt;25&lt;/strong&gt; and &lt;strong&gt;85&lt;/strong&gt;, respectively. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukmo0xjaj88katn24dvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukmo0xjaj88katn24dvz.png" alt="5 gray circles, their colors moving from light to dark" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After following the steps above, you should have a rough grayscale palette all set up. This will change over time and likely need some tweaking as you work with it, but it's perfect for now. &lt;/p&gt;

&lt;p&gt;Again, I encourage you to make these shades your own. You don't need to copy the above example exactly, but it should provide a good reference as you build your own palette. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Applying the shades of gray&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's apply our grayscale colors to our product card and mellow out those harsh visual vibes. I'm looking at you &lt;code&gt;#000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;I would usually define my shades of gray before starting any design work and apply them as I go. For the purposes of this tutorial, though, we are going to be adding them after-the-fact.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, let's add the pre-defined shades of gray as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*"&gt;CSS custom properties&lt;/a&gt; in our code. Storing our colors as custom properties will allow for simple tweaking later on.&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="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--gray-100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;46%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;83%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;96%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;--white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&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="m"&gt;0%&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to label my shades &lt;code&gt;&amp;lt;color_name&amp;gt;-&amp;lt;increment_of_100&amp;gt;&lt;/code&gt; This is a personal preference and it works great for me, but feel free to name them as you wish. I understand naming conventions are very personal! &lt;/p&gt;

&lt;p&gt;Now we have our custom properties added to our CSS, we can apply them to various elements of our product card.&lt;/p&gt;

&lt;p&gt;First, let's make the card's description our &lt;strong&gt;second darkest&lt;/strong&gt; gray. This will leave enough room “either side” to create a visual hierarchy for our headers and meta 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;.card__description&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-200&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 can now make our card title our &lt;strong&gt;darkest&lt;/strong&gt; shade of gray. I often like to set headings a little darker in shade than other text elements to help them stand out.&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;.card__title&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-100&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 further build our hierarchy, let's push the card's “meta” text back a little by making it our &lt;strong&gt;middle&lt;/strong&gt; gray shade. We can also make the little dot our &lt;strong&gt;second-to-lightest&lt;/strong&gt; gray:&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;.card__meta&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__meta&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;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-200&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;Looking good! From here, we can style up our “primary” and “secondary” buttons using an assortment of shades:&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;.card__btn&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-100&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__btn--outline&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--white&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-200&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;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-400&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 can set our image background to our &lt;strong&gt;lightest&lt;/strong&gt; shade of gray, and the little heart icon to the &lt;strong&gt;middle&lt;/strong&gt;:&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;.card__img-wrapper&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-500&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card__heart&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-300&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;Phew! That's a lot of changes. Here's a CodePen showing everything we have done so far...&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/MWbvEYN?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Through using &lt;em&gt;only shades of gray&lt;/em&gt; we have established a clear visual hierarchy. Important elements such as the product title are darker and more prominent. Less important elements are lighter and less prominent. &lt;/p&gt;

&lt;p&gt;Compared to the original black and white design, there is a lot more order to the card's layout. Before, every element was fighting for your eye's attention. Now, everything sits in its own space.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A note on accessibility - check your contrast&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When applying color, particularly to text elements, be wary of contrast. Contrast, or perceived “luminance”,  is the difference in brightness between two colors. &lt;/p&gt;

&lt;p&gt;This light gray text on a white background, for example, has a rather low contrast ratio of &lt;strong&gt;1.48&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6f4g9et13bdrdv5emdt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6f4g9et13bdrdv5emdt.png" alt="Light gray text on a white background with a crying face emoji" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This dark gray text has a far higher contrast ratio of &lt;strong&gt;10.37&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rsx9fjivkdkr26gqogh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rsx9fjivkdkr26gqogh.png" alt="Dark gray text on a white background with a happy face emoji" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When working on the web, we must always hit &lt;em&gt;at least&lt;/em&gt; &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html"&gt;WCAG AA color contrast guidelines&lt;/a&gt;. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A ratio of at least &lt;strong&gt;4.5:1&lt;/strong&gt; for regular text elements&lt;/li&gt;
&lt;li&gt;  A ratio of at least &lt;strong&gt;3:1&lt;/strong&gt; for large text elements &lt;em&gt;(usually around 18.5px and bold, or 24px with a regular weight)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  A ratio of at least &lt;strong&gt;3:1&lt;/strong&gt; for graphical objects and UI components &lt;em&gt;(the border on a text-input, for example)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many methods available for checking color contrast in your designs. For testing a whole page, I like to use Chrome's &lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;lighthouse&lt;/a&gt; that runs straight from dev-tools. For checking individual colors, I like &lt;a href="https://colourcontrast.cc/"&gt;this excellent tool&lt;/a&gt; from &lt;a href="https://twitter.com/alexmclapperton"&gt;Alex Clapperton&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In time, you will find your own way of checking contrast that best fits your workflow. For a start, though, these will work great.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing a personality
&lt;/h2&gt;

&lt;p&gt;OK, so our product cards are looking good. By establishing a visual hierarchy, things are already looking a lot more “designed”. We have done a lot of work using &lt;em&gt;only grays&lt;/em&gt;, but it's time to add a little touch of color. &lt;/p&gt;

&lt;p&gt;First things first, spend a moment thinking about the personality you want to convey with your UI. The personality you land on will help decide your primary/base color. &lt;/p&gt;

&lt;p&gt;If you have chosen a diamond ring for your product image, you may want to go for a  regal/exclusive personality.  &lt;/p&gt;

&lt;p&gt;If you have chosen a beach umbrella, you may want to explore a happy, vibrant personality.&lt;/p&gt;

&lt;p&gt;There are no right or wrong answers with this so go with your gut. For my herbs, I am going for calm and natural.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Choosing a primary color + shades&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When creating a color palette, I like to start with a single primary/base color. We will apply this color &lt;strong&gt;the most&lt;/strong&gt; throughout our UI. &lt;/p&gt;

&lt;p&gt;Keeping the personality you landed on earlier in mind, decide on a color to begin exploring. In my case, I have chosen &lt;strong&gt;green&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are &lt;em&gt;tons&lt;/em&gt; of resources online that explore the relationship of different colors/emotions. While these are a great reference, they aren't going to give you a definitive answer. Use them as a guide, but trust your eye. &lt;a href="https://en.wikipedia.org/wiki/Color_psychology#:~:text=Color%20psychology%20is%20the%20study,enhance%20the%20effectiveness%20of%20placebos."&gt;This Wikipedia page on color psychology&lt;/a&gt; is a good starting point.&lt;/p&gt;

&lt;p&gt;Once you have chosen a rough color, how you experiment is completely up to you. Some like to work in a graphics editor such as Figma/Sketch, whilst others like to work in the browser. &lt;/p&gt;

&lt;p&gt;If you aren't sure, fire up a new CodePen, create a square in the middle of the page, and start experimenting with &lt;code&gt;hsl()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;Stuck? Don't worry!&lt;/p&gt;

&lt;p&gt;I know, choosing a primary color can feel like an impossible task. Even after narrowing things down to an approximate hue, there are thousands of options. How on earth do you choose one?&lt;/p&gt;

&lt;p&gt;If you find yourself getting a little lost at color sea, I recommend trying out the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Research some brands/sites you like and use dev-tools or &lt;a href="https://www.colorzilla.com/"&gt;an extension&lt;/a&gt; to inspect their palette. In particular - examine how they set the saturation and lightness for their primary/base color. This should help you get in the right ballpark for yours. &lt;/li&gt;
&lt;li&gt;  Choose a painting or photograph  you like. Use a browser extension to extract its colors in the same way as above. This can be a fantastic source of inspiration if you hit a wall!&lt;/li&gt;
&lt;li&gt;  Try a color generator such as &lt;a href="https://coolors.co/"&gt;coolors.co&lt;/a&gt;, or check out a design resource such as &lt;a href="https://twitter.com/colours__cafe"&gt;colors.cafe&lt;/a&gt;. Whilst I don't recommend using a generator or preset palette for your &lt;em&gt;whole&lt;/em&gt; color scheme... they could help you find a great primary/base color to start with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my primary color, I have landed on this shade of green: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttmcplhm09a8nwqk5vhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttmcplhm09a8nwqk5vhi.png" alt="A green circle" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why? &lt;/p&gt;

&lt;p&gt;First, it fits my desired natural/calm personality. &lt;/p&gt;

&lt;p&gt;Second, it has enough contrast against a white background for text elements. This will make adding it to the UI far easier in the future. Again, there are no right or wrong answers here, but try and choose a color that hits these two criteria. &lt;/p&gt;

&lt;p&gt;Once you have chosen your primary color, you will need to define some more shades. For this, you can follow the exact process we ran through to choose our grays. For my green color, that looks like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuofxor6a0jzoib4xa46u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuofxor6a0jzoib4xa46u.png" alt="5 green circles, their colors moving from light to dark" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;darker shades often need more saturation, whilst lighter shades often need a little less.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Say, in an alternate universe I had decided to use the beach umbrella emoji for my product image, I may have ended up with some colors like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fcrfqtlhvnq5l6678g0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fcrfqtlhvnq5l6678g0.png" alt="5 orange circles, their colors moving from light to dark, and a beach umbrella emoji" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I had chosen the candy/sweets as my product, I may have ended up with something like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7bnp7ppo04lm6wmnoeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7bnp7ppo04lm6wmnoeo.png" alt="5 pink circles, their colors moving from light to dark, and a candy emoji" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Applying the primary/base color
&lt;/h2&gt;

&lt;p&gt;Awesome. We now have each have a unique primary/base color + shades to apply to our product card. Although we have 5 exciting shades to choose from, we only need to apply &lt;em&gt;touches&lt;/em&gt; of color. Remember, our grays can do most of the work. &lt;/p&gt;

&lt;p&gt;To get started, place your primary/base color shades into your CSS in the same way as your grays:&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="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--green-100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&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="m"&gt;8%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--green-200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&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="m"&gt;16%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--green-300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&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="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--green-400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&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="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--green-500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&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="m"&gt;96%&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;A great way to get started applying your primary/base color is to add it to a button. In our case, the “Buy now” button is perfect. It is the main action we want to highlight for the card, and adding a splash of color will help it stand out. &lt;/p&gt;

&lt;p&gt;Let's set the buttons' background to our &lt;strong&gt;middle&lt;/strong&gt; shade and its text color to the &lt;strong&gt;lightest&lt;/strong&gt; shade. This is a handy little tip I use a lot. A lighter shade of a color sat on top of a darker shade will often look a lot more natural than pure white:&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;.card__btn&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--green-300&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--green-500&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;Looking good! Next up let's set our product image background to our &lt;strong&gt;lightest&lt;/strong&gt; shade:&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;.card__img-wrapper&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--green-500&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 set our little meta-info dot to our &lt;strong&gt;second-to-lightest&lt;/strong&gt; shade:&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;.card__meta&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;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--green-400&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;Here's a Codepen showing my product card after making these changes: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/wvoPVdG?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Through using a few splashes of color, we have added a ton of personality to our product card. &lt;/p&gt;

&lt;p&gt;Don't worry if you aren't 100% happy with your first try here. This stuff takes practice. If you get stuck, try a different product emoji and experiment with some different colors! &lt;/p&gt;




&lt;h2&gt;
  
  
  Tinted grays 
&lt;/h2&gt;

&lt;p&gt;A great tip for making the colors in your UI feel more coherent, is to add a hint of your primary/base color to your grays. You will want to keep this subtle. Darker shades can take more of a tint than lighter shades. &lt;/p&gt;

&lt;p&gt;For my color choices, that looks something like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg2pu91lyt6m8vvjxou4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg2pu91lyt6m8vvjxou4.png" alt="5 green-tinted gray circles" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My “gray” custom properties now look like this:&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="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--gray-100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;45%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-300&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;83%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--gray-500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;96%&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;em&gt;Pssst... Remember to re-check your color contrast after adjusting your grays! You may need to tweak the lightness value of some of your colors after introducing a tint. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is a CodePen showing my product card UI with these shades applied:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/KKNyOjQ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Not bad, eh! It's a small change, but it's worth making.&lt;/p&gt;




&lt;h2&gt;
  
  
  Expanding your palette
&lt;/h2&gt;

&lt;p&gt;At this point, our product card is almost complete. We have achieved a lot with only 5 shades of a primary/base color, and 5 shades of gray. For our small design, this is almost enough. For larger projects, you are likely going to need more.&lt;/p&gt;

&lt;p&gt;Combining colors and building color palettes deserves an entire post all to itself. For our basic design, though, let's explore a simple way to add 1 more color to our UI...&lt;/p&gt;

&lt;p&gt;Remember the color wheel from earlier? This is going to be our new best friend when it comes to finding colors that work together. &lt;/p&gt;

&lt;p&gt;By starting at our base color hue, and rotating 180 degrees, we will reach our base's &lt;em&gt;complimentary&lt;/em&gt; hue. You can pretty much guarantee that this hue and your primary/base hue will work great together! &lt;/p&gt;

&lt;p&gt;Here's a visualization: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20jyltoyozr1afi8brjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20jyltoyozr1afi8brjp.png" alt="12 colors in a circle/wheel with two opposite colors highlighted" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, the complementary hue is a maroon color. For you, it could be anything! To achieve this in CSS, just add 180 to your primary/base hue value.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note, in CSS hsl(), numbers above 360 will simply “wrap” back around to 0, so don't worry about doing any fancy calculation. Adding 180 to your base hue is all you need. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Boom! That's it. From here, you can follow the same pattern we used before to create 5 shades. For me, that looks like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5eiq627yz3flxp53ixrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5eiq627yz3flxp53ixrk.png" alt="5 maroon circles, their colors ranging from light to dark" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have defined your shades, you can add them as custom properties and apply them how you wish. For me, I am going to use my new complementary shades to add some color to the “like” button:&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;.card__heart&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--maroon-300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--maroon-500&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 it. We're done! &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/rNWpxwJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Your product card should look similar to mine, but with a totally different color scheme and product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;That's all folks. I hope you learned some useful new things about color from this tutorial. I hope you managed to make a cool product card, too. Whilst the example we created is simple, the techniques applied here will see you through much larger projects.&lt;/p&gt;

&lt;p&gt;If you like, please share any CodePens / examples you make. I'd love to see them!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enjoyed this tutorial? Follow me on Twitter &lt;a href="https://twitter.com/georgedoescode"&gt;@georgedoescode&lt;/a&gt; for more front-end/creative coding content 🎨 &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This tutorial took around 12 hours to put together, all in. If you would like to support my work you can &lt;a href="https://ko-fi.com/georgedoescode"&gt;buy me a coffee&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webdev</category>
      <category>css</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>CodePen - BauBuds - Generative Bauhaus inspired Characters</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Wed, 17 Feb 2021 18:17:43 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-baubuds-generative-bauhaus-inspired-characters-1ef5</link>
      <guid>https://dev.to/georgedoescode/codepen-baubuds-generative-bauhaus-inspired-characters-1ef5</guid>
      <description>&lt;p&gt;BauBuds are generative Bauhaus inspired characters for an upcoming project... keep an eye out for them in the future! 👀&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/VwmbxRy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>CodePen - Generative “Embroidery Ring” Style Hills</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Tue, 16 Feb 2021 14:08:58 +0000</pubDate>
      <link>https://dev.to/georgedoescode/codepen-generative-embroidery-ring-style-hills-57j1</link>
      <guid>https://dev.to/georgedoescode/codepen-generative-embroidery-ring-style-hills-57j1</guid>
      <description>&lt;p&gt;A lil' generative sketch inspired by embroidery rings. Inspired by the Sussex downs! &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/xxRgQLb?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Create a generative landing page &amp; WebGL powered background animation</title>
      <dc:creator>George Francis</dc:creator>
      <pubDate>Mon, 08 Feb 2021 11:25:51 +0000</pubDate>
      <link>https://dev.to/georgedoescode/create-a-generative-landing-page-webgl-powered-background-animation-3nl0</link>
      <guid>https://dev.to/georgedoescode/create-a-generative-landing-page-webgl-powered-background-animation-3nl0</guid>
      <description>&lt;p&gt;Recently I took a trip to the faraway land of &lt;a href="https://www.dribbble.com" rel="noopener noreferrer"&gt;dribbble&lt;/a&gt; and saw something magical. There were fuzzy orbs and beautiful, glass-like interfaces floating around everywhere. Serene! &lt;/p&gt;

&lt;p&gt;This got me thinking. Wouldn't it be cool to create a &lt;em&gt;generative&lt;/em&gt; landing page in this style? &lt;/p&gt;




&lt;h2&gt;
  
  
  The end result 
&lt;/h2&gt;

&lt;p&gt;First of all, here's a kind of visual TL;DR.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/georgedoescode/embed/XWNmvro?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/georgedoescode/full/XWNmvro" rel="noopener noreferrer"&gt;You can check out a full-page example here, too.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The color palette is random &lt;em&gt;within constraints.&lt;/em&gt; The colorful orbs move with a mind of their own. These elements of randomness are what make our landing page generative.&lt;/p&gt;

&lt;p&gt;If generative art/design is new to you, &lt;a href="https://dev.to/aspittel/intro-to-generative-art-2hi7"&gt;here is an excellent primer&lt;/a&gt; from &lt;a href="https://twitter.com/ASpittel" rel="noopener noreferrer"&gt;Ali Spittel&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/1800THEHIVE" rel="noopener noreferrer"&gt;James Reichard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like what you see? Let's build!&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To get the most out of this tutorial you will need to be comfortable writing HTML, CSS, and JavaScript. &lt;/p&gt;

&lt;p&gt;If you have read “WebGL” and fallen into a state of shader-induced panic, don't worry. We will be using &lt;a href="https://www.pixijs.com/" rel="noopener noreferrer"&gt;PixiJS&lt;/a&gt; to abstract away the scary stuff. This tutorial will serve as a nice introduction to Pixi if you haven't used it before, too. &lt;/p&gt;




&lt;h2&gt;
  
  
  Creating the background animation
&lt;/h2&gt;

&lt;p&gt;The first thing we are going to build is the orbs. To create them, we are going to need some libraries/packages. Let's get the boring stuff out of the way first and add them to the project. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Package overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here's a quick summary of the libraries/packages we will be using. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/pixi.js/v/5.0.0-rc" rel="noopener noreferrer"&gt;PixiJS&lt;/a&gt; - A powerful graphics library built on WebGL, we will use it to render our orbs.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/@pixi/filter-kawase-blur" rel="noopener noreferrer"&gt;KawaseBlurFilter&lt;/a&gt; - A PixiJS filter plugin for ultra smooth blurs.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/simplex-noise" rel="noopener noreferrer"&gt;SimplexNoise&lt;/a&gt; - Used to generate a stream of self-similar random numbers. More on this shortly.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/hsl-to-hex" rel="noopener noreferrer"&gt;hsl-to-hex&lt;/a&gt; - A tiny JS utility for converting HSL colors to HEX.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/debounce" rel="noopener noreferrer"&gt;debounce&lt;/a&gt; - A  JavaScript &lt;a href="https://davidwalsh.name/javascript-debounce-function" rel="noopener noreferrer"&gt;debounce function.&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Package installation
&lt;/h3&gt;

&lt;p&gt;If you are following along on CodePen, add the following imports to your JavaScript file and you are good to go:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PIXI&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;https://cdn.skypack.dev/pixi.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;KawaseBlurFilter&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;https://cdn.skypack.dev/@pixi/filter-kawase-blur&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SimplexNoise&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;https://cdn.skypack.dev/simplex-noise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;hsl&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;https://cdn.skypack.dev/hsl-to-hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;debounce&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;https://cdn.skypack.dev/debounce&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;If you are hanging out in your own environment, you can install the required packages with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm i pixi.js @pixi/filter-kawase-blur simplex-noise hsl-to-hex debounce


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can then import them like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PIXI&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;pixi.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;KawaseBlurFilter&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;@pixi/filter-kawase-blur&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SimplexNoise&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;simplex-noise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;hsl&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;hsl-to-hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;debounce&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;debounce&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;em&gt;Note: Outside of CodePen you will need a build tool such as Webpack or Parcel to handle these imports.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A blank (Pixi) canvas &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Awesome, we now have everything we need to get started. Let's kick things off by adding a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element to our HTML:&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;canvas&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"orb-canvas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we can create a new Pixi instance with the canvas element as it's “view” &lt;em&gt;(where Pixi will render)&lt;/em&gt;. We will call our instance &lt;code&gt;app&lt;/code&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;// Create PixiJS app&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PIXI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// render to &amp;lt;canvas class="orb-canvas"&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.orb-canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// auto adjust size to fit the current window&lt;/span&gt;
  &lt;span class="na"&gt;resizeTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// transparent background, we will be creating a gradient background later using CSS&lt;/span&gt;
  &lt;span class="na"&gt;transparent&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you inspect the DOM and resize the browser, you should see the canvas element resize to fit the window. Magic! &lt;/p&gt;

&lt;h3&gt;
  
  
  Some helpful utilities 
&lt;/h3&gt;

&lt;p&gt;Before going any further, we should add some utility functions to our JavaScript.&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;// return a random number within a range&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;max&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// map a number from 1 range to another&lt;/span&gt;
&lt;span class="kd"&gt;function&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;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end2&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="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;end1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;end2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;start2&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 have followed any of my tutorials before, you might be familiar with these already. I'm a little obsessed...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;random&lt;/code&gt; will return a random number within a limited range. For example, &lt;em&gt;“Give me a random number between 5 and 10”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;map&lt;/code&gt; takes a number from one range and maps it to another. For example, if a number (0.5) usually exists in a range between 0 - 1 and we map it to a range of 0 - 100, the number becomes 50. &lt;/p&gt;

&lt;p&gt;I encourage experimenting with these two utilities a little if they are new to you. They will be useful companions in your generative journey! Pasting them into the console and experimenting with the output is a great place to start. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Creating the Orb class&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, we should have everything we need to create our orb animation. To start, let's create an &lt;code&gt;Orb&lt;/code&gt; class:&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;// Orb class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Orb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Pixi takes hex colors as hexidecimal literals (0x rather than a string with '#')&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// bounds = the area an orb is "allowed" to move within&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBounds&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// initialise the orb's { x, y } values to a random point within it's bounds&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// how large the orb is vs it's original radius (this will modulate over time)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// what color is the orb?&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// the original radius of the orb, set relative to window height&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// starting points in "time" for the noise/self similar random values&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xOff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yOff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// how quickly the noise/self similar random values step through time&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// PIXI.Graphics is used to draw 2d primitives (in this case a circle) to the canvas&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PIXI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Graphics&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.825&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 250ms after the last window resize event, recalculate orb positions.&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;debounce&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBounds&lt;/span&gt;&lt;span class="p"&gt;();&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="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;Our &lt;code&gt;Orb&lt;/code&gt; is a simple circle that exists in a 2d space. &lt;/p&gt;

&lt;p&gt;It has an x and a y value, a radius, a fill color, a scale value &lt;em&gt;(how large it is vs its original radius)&lt;/em&gt; and a set of bounds. Its bounds define the area it can move around in, like a set of virtual walls. This will stop the orbs from getting too close to our text.&lt;/p&gt;

&lt;p&gt;You may notice the use of a non-existent &lt;code&gt;setBounds&lt;/code&gt; function in the snippet above. This function will define the virtual constraints our orbs exist within.  Let's add it to the &lt;code&gt;Orb&lt;/code&gt; class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;setBounds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// how far from the { x, y } origin can each orb move&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxDist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// the { x, y } origin for each orb (the bottom right of the screen)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.25&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;originY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.375&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// allow each orb to move x distance away from it's { x, y }origin&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;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;originX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;maxDist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;originX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;maxDist&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;originY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;maxDist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;originY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;maxDist&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;OK, great. This is coming together! Next up, we should add an &lt;code&gt;update&lt;/code&gt; and a &lt;code&gt;render&lt;/code&gt; function to our &lt;code&gt;Orb&lt;/code&gt; class. Both of these functions will run on each animation frame. More on this in a moment.&lt;/p&gt;

&lt;p&gt;The update function will define how the orb's position and size should change over time. The render function will define how the orb should display itself on-screen.&lt;/p&gt;

&lt;p&gt;First, here is the &lt;code&gt;update&lt;/code&gt; function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// self similar "psuedo-random" or noise values at a given point in "time"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xNoise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simplex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;noise2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xOff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xOff&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;yNoise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simplex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;noise2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yOff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yOff&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;scaleNoise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simplex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;noise2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xOff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yOff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// map the xNoise/yNoise values (between -1 and 1) to a point within the orb's bounds&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&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;xNoise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&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;yNoise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// map scaleNoise (between -1 and 1) to a scale value somewhere between half of the orb's original size, and 100% of it's original size&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&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;scaleNoise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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="mf"&gt;0.5&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="c1"&gt;// step through "time"&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xOff&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yOff&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inc&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;In order for this function to run, we must also define &lt;code&gt;simplex&lt;/code&gt;. To do so, add the following snippet anywhere before the &lt;code&gt;Orb&lt;/code&gt; class definition:&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;// Create a new simplex noise instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simplex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SimplexNoise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There's a lot of “noise” talk going on here. I realize that for some folks this will be an unfamiliar concept. &lt;/p&gt;

&lt;p&gt;I won't be going deep on noise in this tutorial, but I would recommend &lt;a href="https://www.youtube.com/watch?v=8ZEMLCnn8v0" rel="noopener noreferrer"&gt;this video&lt;/a&gt; by Daniel Shiffman as a primer. If you are new to the concept of noise - pause this article, check out the video, and pop back!&lt;/p&gt;

&lt;p&gt;In a nutshell, though, noise is a great way of generating _ self-similar_ random numbers. These numbers are amazing for animation, as they create smooth yet unpredictable movement. &lt;/p&gt;

&lt;p&gt;Here's an image from &lt;a href="https://natureofcode.com/" rel="noopener noreferrer"&gt;The Nature of Code&lt;/a&gt; showing the difference between traditional random (e.g. &lt;code&gt;Math.random()&lt;/code&gt; and noisy random values: &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%2F7l8ej48s9jal1i9xo05u.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%2F7l8ej48s9jal1i9xo05u.png" alt="A ragged, random distribution compared to a smooth noisy one"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;update&lt;/code&gt; function here uses noise to modulate the orb's &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;scale&lt;/code&gt; properties over time. We pick out noise values based on our &lt;code&gt;xOff&lt;/code&gt; and &lt;code&gt;yOff&lt;/code&gt; positions. We then use &lt;code&gt;map&lt;/code&gt; to scale the values (always between -1 and 1) to new ranges.&lt;/p&gt;

&lt;p&gt;The result of this? The orb will always drift &lt;strong&gt;within its bounds.&lt;/strong&gt; Its size is &lt;em&gt;random within constraints.&lt;/em&gt; The orb's behavior is unpredictable. There are no keyframes or fixed values here. &lt;/p&gt;

&lt;p&gt;This is all well and good, but we still can't see anything! Let's fix that by adding the &lt;code&gt;render&lt;/code&gt; function to our &lt;code&gt;Orb&lt;/code&gt; class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// update the PIXI.Graphics position and scale values&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// clear anything currently drawn to graphics&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// tell graphics to fill any shapes drawn after this with the orb's fill color&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beginFill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// draw a circle at { 0, 0 } with it's size set by this.radius&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawCircle&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// let graphics know we won't be filling in any more shapes&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endFill&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;code&gt;render&lt;/code&gt;  will draw a new circle to our canvas each frame. &lt;/p&gt;

&lt;p&gt;You may notice that the circle's &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; values are both 0. This is because we are moving the &lt;code&gt;graphics&lt;/code&gt; element itself, rather than the circle within it. &lt;/p&gt;

&lt;p&gt;Why is this? &lt;/p&gt;

&lt;p&gt;Imagine that you wanted to expand on this project, and render a more complex orb. Your new orb is now comprised of &amp;gt; 100 circles. It is simpler to move the entire graphics instance than to move every element within it. This &lt;em&gt;may&lt;/em&gt; give you some performance gains, too.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Creating some orbs!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It's time to put our &lt;code&gt;Orb&lt;/code&gt; class to good use. Let's create 10 brand new orb instances, and pop them into an &lt;code&gt;orbs&lt;/code&gt; array:&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;// Create orbs&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orbs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&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;0&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;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// each orb will be black, just for now&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Orb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphics&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;orbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orb&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 calling &lt;code&gt;app.stage.addChild&lt;/code&gt; to add each graphics instance to our canvas. This is akin to calling &lt;code&gt;document.appendChild()&lt;/code&gt; on a DOM element. &lt;/p&gt;

&lt;h3&gt;
  
  
  Animation! Or, no animation?
&lt;/h3&gt;

&lt;p&gt;Now that we have 10 new orbs, we can start to animate them. Let's not assume everyone wants a moving background, though. &lt;/p&gt;

&lt;p&gt;When you are building this kind of page, it is crucial to respect the user's preferences. In our case, if the user has &lt;code&gt;prefers-reduced-motion&lt;/code&gt; set, we will render a static background. &lt;/p&gt;

&lt;p&gt;Here's how we can set up a Pixi animation loop that will respect the user's preferences:&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;// Animate!&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(prefers-reduced-motion: reduce)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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;// update and render each orb, each frame. app.ticker attempts to run at 60fps&lt;/span&gt;
    &lt;span class="nx"&gt;orbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;orb&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="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// perform one update and render per orb, do not animate&lt;/span&gt;
  &lt;span class="nx"&gt;orbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;orb&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="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&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;When we call &lt;code&gt;app.ticker.add(function)&lt;/code&gt;, we tell Pixi to repeat that function at around 60 frames per second. In our case, if the user prefers reduced motion, we only run &lt;code&gt;update&lt;/code&gt; and render our orbs once.  &lt;/p&gt;

&lt;p&gt;Once you have added the above snippet, you should see something like this in the browser: &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%2Fkea24zae2xtxvj353353.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%2Fkea24zae2xtxvj353353.png" alt="A group of black circles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hooray! Movement! Believe it or not, we are almost there. &lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the blur 
&lt;/h3&gt;

&lt;p&gt;Our orbs are looking a little... harsh right now. Let's fix that by adding a blur filter to our Pixi canvas. This is actually very simple and will make a huge difference to our visual output.&lt;/p&gt;

&lt;p&gt;Pop this line below your &lt;code&gt;app&lt;/code&gt; definition:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KawaseBlurFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, if you check out the browser you should see some much softer orbs! &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%2Fce1ouotst33m27asxtim.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%2Fce1ouotst33m27asxtim.png" alt="A group of blurry black circles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking great. Let's add some color. &lt;/p&gt;




&lt;h2&gt;
  
  
  A Generative color palette using HSL
&lt;/h2&gt;

&lt;p&gt;To introduce some color to our project, we are going to create a &lt;code&gt;ColorPalette&lt;/code&gt; class. This class will define a set of colors we can use to fill in our orbs but also style the wider page.&lt;/p&gt;

&lt;p&gt;I always use HSL when working with color. It's more intuitive than hex and lends itself rather well to generative work. Here's how:&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;class&lt;/span&gt; &lt;span class="nc"&gt;ColorPalette&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setColors&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCustomProperties&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setColors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// pick a random hue somewhere between 220 and 360&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// define a fixed saturation and lightness&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saturation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lightness&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;// define a base color&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saturation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lightness&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// define a complimentary color, 30 degress away from the base&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryColor1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saturation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lightness&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// define a second complimentary color, 60 degrees away from the base&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryColor2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saturation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lightness&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// store the color choices in an array so that a random one can be picked later&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorChoices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryColor1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryColor2&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;randomColor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// pick a random color&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorChoices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~~&lt;/span&gt;&lt;span class="nf"&gt;random&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorChoices&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="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&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;0x&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="nf"&gt;setCustomProperties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// set CSS custom properties so that the colors defined here can be used throughout the UI&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&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="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--hue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&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="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--hue-complimentary1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue1&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&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="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--hue-complimentary2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complimentaryHue2&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 are picking 3 main colors. A random base color, and two complimentary. We pick our complementary colors by rotating the hue 30 and 60 degrees from the base.&lt;/p&gt;

&lt;p&gt;We then set the 3 hues as custom properties in the DOM and define a &lt;code&gt;randomColor&lt;/code&gt; function. &lt;code&gt;randomColor&lt;/code&gt; returns a random Pixi-compatible HSL color each time it is run. We will use this for our orbs. &lt;/p&gt;

&lt;p&gt;Let's define a &lt;code&gt;ColorPalette&lt;/code&gt; instance before we create our orbs:&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;const&lt;/span&gt; &lt;span class="nx"&gt;colorPalette&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ColorPalette&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 then give each orb a random fill on creation:&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;const&lt;/span&gt; &lt;span class="nx"&gt;orb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Orb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colorPalette&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomColor&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 check the browser, you should now see some color! &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%2Fgr5snevpd1leplkhii6n.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%2Fgr5snevpd1leplkhii6n.png" alt="A group of colorful, blurry circles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you inspect the root &lt;code&gt;html&lt;/code&gt; element in the DOM, you should also see some custom properties have been set. We are now ready to add some markup and styles for the page. &lt;/p&gt;




&lt;h2&gt;
  
  
  Building the rest of the page
&lt;/h2&gt;

&lt;p&gt;Awesome! So our animation is complete. It looks great and is running real fast thanks to Pixi. Now we need to build the rest of the landing page. &lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the markup
&lt;/h3&gt;

&lt;p&gt;First of all, let's add some markup to our HTML file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="c"&gt;&amp;lt;!-- Overlay --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Overlay inner wrapper --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__inner"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Title --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Hey, would you like to learn how to create a
      &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;"text-gradient"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;generative&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; UI just like this?
    &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Description --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      In this tutorial we will be creating a generative “orb” animation using pixi.js, picking some lovely random colors, and pulling it all together in a nice frosty UI.
      &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;We're gonna talk accessibility, too.&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Buttons --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__btns"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__btn overlay__btn--transparent"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Tutorial out Feb 2, 2021
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overlay__btn overlay__btn--colors"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;Randomise Colors&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;"overlay__btn-emoji"&lt;/span&gt;&lt;span class="nt"&gt;&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;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There's nothing too crazy going on here, so I won't dig in too much. Let's move onto our CSS:&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the CSS
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--dark-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&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="m"&gt;9%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--light-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;98%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&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="py"&gt;--complimentary1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-complimentary1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&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="py"&gt;--complimentary2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-complimentary2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&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="py"&gt;--font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Poppins"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system-ui&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="py"&gt;--bg-gradient&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;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;99%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;84%&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="o"&gt;*&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;padding&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;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&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;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1920px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&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;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;place-items&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="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--font-family&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-color&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--bg-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;.orb-canvas&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;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&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;left&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;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="nl"&gt;height&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="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;z-index&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="nt"&gt;strong&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;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay&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="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1140px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;640px&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;8rem&lt;/span&gt; &lt;span class="m"&gt;6rem&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&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="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.375&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&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.75rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__inner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;36rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__title&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;1.875rem&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;2.75rem&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;700&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.025em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.text-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="m"&gt;45deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--complimentary2&lt;/span&gt;&lt;span class="p"&gt;)&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;-webkit-text-fill-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;-moz-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;-moz-text-fill-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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__description&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;1rem&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.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__btns&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="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30rem&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__btn&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;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;2.5rem&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&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="nl"&gt;align-items&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="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.875rem&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;600&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--light-color&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-color&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="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;not-allowed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;150ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;95%&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__btn--colors&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__btn--transparent&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="nb"&gt;transparent&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-color&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="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&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;0.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.overlay__btn-emoji&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.375rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1140px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.overlay&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;8rem&lt;/span&gt; &lt;span class="m"&gt;4rem&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;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;840px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay&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;4rem&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="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay__title&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;1.25rem&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;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay__description&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;0.875rem&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.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2.5rem&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;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.overlay&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;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay__btns&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay__btn&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="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75rem&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.overlay__btn&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&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;The key part of this stylesheet is defining the custom properties in &lt;code&gt;:root&lt;/code&gt;. These custom properties make use of the values we set with our &lt;code&gt;ColorPalette&lt;/code&gt; class. &lt;/p&gt;

&lt;p&gt;Using the 3 hue custom properties defined already, we create the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;--dark-color&lt;/code&gt; - To use for all our text and primary button styles,  this is &lt;em&gt;almost&lt;/em&gt; black with a hint of our base hue. This helps make our color palette feel coherent.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--light-color&lt;/code&gt; - To use in place of pure white. This is much the same as the dark color, &lt;strong&gt;almost&lt;/strong&gt; white with a hint of our base hue.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--complimentary1&lt;/code&gt; - Our first complimentary color, formatted to CSS friendly HSL.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--complimentary2&lt;/code&gt; - Our second complementary color, formatted to CSS friendly HSL.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--bg-gradient&lt;/code&gt; - A subtle linear gradient based on our base hue. We use this for the page background. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We then apply these values throughout our UI. For button styles, outline colors, even a gradient text effect. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note on accessibility &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we are &lt;em&gt;almost&lt;/em&gt; setting our colors and letting them run free. In this case, we should be ok given the design choices we have made. In production, though, &lt;strong&gt;always make sure you meet at least &lt;a href="https://webaim.org/articles/contrast/" rel="noopener noreferrer"&gt;WCAG 2.0 color contrast guidelines&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Randomising the colors in real-time
&lt;/h2&gt;

&lt;p&gt;Our UI and background animation are now complete. It's looking great, and you will see a new color palette/orb animation each time you refresh the page. &lt;/p&gt;

&lt;p&gt;It would be good if we could randomize the colors without refreshing, though. Luckily, thanks to our custom properties/color palette setup, this is simple. &lt;/p&gt;

&lt;p&gt;Add this small snippet to your JavaScript:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.overlay__btn--colors&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;colorPalette&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setColors&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;colorPalette&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCustomProperties&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;orbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;orb&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="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colorPalette&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomColor&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 this snippet, we are listening for a click event on our primary button. On click, we generate a new set of colors, update the CSS custom properties, and set each orb's fill to a new value.&lt;/p&gt;

&lt;p&gt;As CSS custom properties are reactive, our entire UI will update in real-time. Powerful stuff.&lt;/p&gt;




&lt;h2&gt;
  
  
  That's all folks
&lt;/h2&gt;

&lt;p&gt;Hooray, we made it! I hope you had fun and learned something from this tutorial. &lt;/p&gt;

&lt;p&gt;Random color palettes may be a tad experimental for most applications, but there's a lot to take away here. Introducing an element of chance could be a great addition to your design process.&lt;/p&gt;

&lt;p&gt;You can never go wrong with a generative animation, either. &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Follow on on Twitter &lt;a href="https://twitter.com/georgedoescode" rel="noopener noreferrer"&gt;@georgedoescode&lt;/a&gt; for more creative coding/front-end development content.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article and demo took around 12 hours to create. If you would like to support my work you &lt;a href="https://ko-fi.com/georgedoescode" rel="noopener noreferrer"&gt;can buy me a ☕&lt;/a&gt; ❤️&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>css</category>
    </item>
  </channel>
</rss>
