A Generative SVG Starter Kit
Tags: webdev, tutorial, javascript, css
Published: 2021-03-11 12:09:30

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. 

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!

Sound good? Let's do it 🎨

_Psst! I wrote this article after talking about generative SVG in the wonderful [viewBox newsletter](https://viewbox.club/). Be sure to check out the issue [here](https://buttondown.email/viewBox/archive/a56db097-f200-4915-bf29-1817df7b517e) for more generative treats. _

---

## Who is this starter kit for? 

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!

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. 

If you are _completely_ new to SVG, I recommend reading through this [MDN Tutorial](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial). Keeping an eye on the docs as a reference, experiment in a [CodePen](https://codepen.io/). 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.

---

## Show me the code! 

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 `fork` to get started right away.

{% codepen https://codepen.io/georgedoescode/pen/abBQxBj %}

I know, it doesn't look like much right now, but there's a ton to unpack here... 

Onwards! 

---

## What is generative art? 

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

If not — here's a quick example...

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.

That's all generative art is. Art created with an element of autonomy/chance. There are no rules, aside from the ones _you define_. 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. 

To illustrate the above, here's a simple CodePen that “paints” random stripes on a canvas: 

{% codepen https://codepen.io/georgedoescode/pen/vYyQMaE %}

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.

---

## A blank canvas 

Most paintings start with a blank canvas of some kind. When working with generative SVG, that canvas is an `<svg>` element on a web page. Here's how I set up the HTML/CSS for almost all my generative SVG work.

```html
<svg class="canvas" viewBox="0 0 200 200"></svg>
```

First, in the HTML, we have an `<svg>` element with a single attribute set, `viewBox`.  This attribute defines a coordinate space. In our case, the coordinate space has a width of 200 units and a height of 200 units.

Once defined, we “draw” everything in the SVG element relative to its viewBox. The SVG will then scale its contents to _any_ 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!

_**Note:**_ _I'm keeping things somewhat high-level here. If you would like to read more about the viewBox attribute, check out_ [_this article_](https://css-tricks.com/scale-svg/) _on CSS tricks._

```css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  height: 100vh;
  display: grid;
  place-items: center;
  background: hsl(0, 0%, 96%);
}

.canvas {
  width: 75vmin;
  height: 75vmin;
  background: hsl(0, 0%, 100%);
}
```

Next up, in the CSS, we have a small selection of styles that achieve 2 things:

1.  Make sure the SVG element is a perfect square that always fits within the viewport. Slap-bang in the middle. Perfect for CodePens!
2.  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.

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. 

_**Note:**_ _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._

---

## An SVG paintbrush 

If the SVG element is our canvas, [SVG.js](https://svgjs.com/docs/3.0/) is our paintbrush. When working on generative art, you will need to create elements (such as a `<rect>` or a `<circle>`) in a dynamic way. 

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.

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.

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. 

Here's an excerpt of the JS required for the above stripes program, _without_ SVG.js:

```javascript
for (let i = 0; i < width; i += stripeWidth) {
  ...
  const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");

  rect.setAttribute("x", i);
  rect.setAttribute("y", 0);
  rect.setAttribute('width', stripeWidth);
  rect.setAttribute('height', height);
  rect.setAttribute("fill", color);
  rect.setAttribute("stroke", "#fff");

  svgElement.appendChild(rect);
}

```

Here's an excerpt of the JS required for the above stripes program, _with_ SVG.js:

```javascript
for (let i = 0; i < width; i += stripeWidth) {
  ...
  svg.rect(stripeWidth, height).x(i).y(0).fill(color).stroke("#fff");
}
```

Ah, Much better 🧘

_**Note:** 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._


### SVG.js in the wild

To demonstrate what is possible with SVG.js, I have a couple of amazing CodePens here from [Liam Egan](https://twitter.com/liamegan). These pens are a fantastic example of how beautiful generative SVG can be, and how powerful SVG.js is in a generative context.

“Grow 4”

{% codepen https://codepen.io/shubniggurath/pen/abByPXz %}

“Flare 2”

{% codepen https://codepen.io/shubniggurath/pen/poNWONd %}

Be sure to check out [Liam's CodePen](https://codepen.io/shubniggurath) for more! 🖊


---

## 4 utility functions... endless possibilities 

So, we have a responsive blank canvas and an awesome way of adding to it. What next? Some helpful functions to decide _what_ to render would be great.

First off, a quick note. There's a common misconception that generative art is _super complex 🤯_ and you need to be some kind of math whizz to do it. Well, to quote the great Dwight Shrute... 

> **FALSE**

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.

I have added the source code for all these functions to [this repository](https://github.com/georgedoescode/generative-utils). They are also available as an [NPM package](https://www.npmjs.com/package/@georgedoescode/generative-utils) for ease of installation. 

_**Note:**_ _This is not an “official” library, so please don't expect tests, documentation, etc... yet! 👀_

### random() 

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

Here's how you can use it to produce a random number within a range: 

{% codepen https://codepen.io/georgedoescode/pen/poNqRxg %}

Here's how you can use it to pick a random item from an array: 

{% codepen https://codepen.io/georgedoescode/pen/WNoLRWb %}

Cool! This simple function will be a loyal companion on your generative journey. You could use it to:

*   Generate a random radius for a `<circle>`
*   Position an object at a random position within an SVG 
*   Pick a random fill color from a pre-defined array of values
*   Rotate an element by a random amount 

If this function is new to you, fork the starter CodePen and experiment for a while!

### map() 

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:

{% codepen https://codepen.io/georgedoescode/pen/RwoEKzE %}

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

Although `map()` is fantastic for dealing with user input, it can also be helpful in a bunch of other contexts. You could use it to: 

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

Again, if this function is new to you, have a play. Fire up a new CodePen and experiment! 

### spline() 

If you have read through any of my tutorials, or checked out my CodePen profile, you have seen `spline()` in action. I'm obsessed. It's the best. 

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 `spline()` in action: 

{% codepen https://codepen.io/georgedoescode/pen/zYoyZrp %}

We store an array of random `{ x, y }` coordinates (thank you `random()`) and use `spline()` 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. 

In this CodePen, I use `spline()` to creating an undulating SVG blob: 

{% codepen https://codepen.io/georgedoescode/pen/oNzamjV %}

[You can check out the tutorial for this CodePen here. ](https://dev.to/georgedoescode/tutorial-build-a-smooth-animated-blob-using-svg-js-3pne)

In this example, I use `spline()` to create generative bodies for little blob characters: 

{% codepen https://codepen.io/georgedoescode/pen/dypjOgv %}

[You can check out the tutorial for this CodePen here. ](https://dev.to/georgedoescode/tutorial-generative-blob-characters-using-svg-1igg)

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.

### pointsInPath() 

This is a new addition to my generative utility belt. It returns an array of equidistant points plotted on an SVG `<path>` element. This is amazing, as it allows you to create your very own, generative, stroke styles. 

Here's a demo of this technique that I put together for the wonderful viewBox newsletter: 

{% codepen https://codepen.io/georgedoescode/pen/LYbdXJR %}

Have a quick look around the source code of the above CodePen. You can see how well `random()` works alongside `pointsInPath()`. Magical! 

---

## Color

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.

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 [this post](https://dev.to/georgedoescode/a-beginner-s-guide-to-applying-color-in-ui-design-3904#working-with-hsl%C2%A0).

Using JS [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) and HSL, one can form generative color palettes in a few lines of code. Here's an example:  

{% codepen https://codepen.io/georgedoescode/pen/BaQvWdo %}

In this example, we are making use of `random()` 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.

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 [this article](https://www.canva.com/colors/color-wheel/). 

Say, for example, you wanted to use an analogous color palette _(3 hues, each 30 degrees apart)_, the code would look like this: 

{% codepen https://codepen.io/georgedoescode/pen/NWbepMb %} 


---

## Animation

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.

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...


### Method 1, the animation loop 

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: 

```javascript
function animate() {
  ...
  requestAnimationFrame(animate);
}
```

What's happening here? The function `animate()` calls itself over-and-over again, somewhere around 60 FPS. It does so using the browser method `requestAnimationFrame`. Within this function, you can update variables and move things around. 

I won't be diving too deep into `requestAnimationFrame` here, but [here is a great CSS tricks article](https://css-tricks.com/using-requestanimationframe/) if you would like to learn more.

Here's a simple CodePen to show how you can use an animation loop to move a `<rect>` around the screen: 

{% codepen https://codepen.io/georgedoescode/pen/eYBbvPr %}


### Method 2, GSAP

Recently, I have been turning to the animation library [GSAP](https://greensock.com/) 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. 

I won't go into detail demonstrating GSAP, as it already has comprehensive documentation. It is worth linking, though, to its [utility functions page](https://greensock.com/docs/v3/GSAP/UtilityMethods). There's some great stuff here, including some similar functions to the utilities we explored earlier. 

Here's a quick CodePen demonstrating some generative GSAP animation:  

{% codepen https://codepen.io/georgedoescode/pen/qBqLrGG %}

---

## Next steps

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? 

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...

Another great avenue of exploration if you are stuck for inspiration is [Dribbble](https://dribbble.com/). Dribbble is an absolute goldmine of fresh new design trends. This stuff can be a great source of inspiration for generative work.

Finally, here's a list of generative learning resources. There's enough content here to take you far into your generative journey! 

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

---

## So long! 

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! 

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 _far_ more interesting than what I create to start with! 

**Enjoyed this tutorial? Follow me on Twitter** [<ins>**@georgedoescode**</ins>](https://twitter.com/georgedoescode) **for more front-end/creative coding content 🎨 **

_This tutorial took around 10 hours to put together, all in. If you would like to support my work you can_ [<ins>_buy me a coffee._</ins>](https://ko-fi.com/georgedoescode)