DEV Community

loading...
Cover image for A Generative SVG Starter Kit

A Generative SVG Starter Kit

georgedoescode profile image George Francis ・12 min read

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. Be sure to check out the issue here 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. Keeping an eye on the docs as a reference, experiment in a CodePen. 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.

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: 

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.

<svg class="canvas" viewBox="0 0 200 200"></svg>
Enter fullscreen mode Exit fullscreen mode

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 on CSS tricks.

* {
  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%);
}
Enter fullscreen mode Exit fullscreen mode

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

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);
}

Enter fullscreen mode Exit fullscreen mode

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

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

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

“Flare 2”

Be sure to check out Liam's CodePen 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. They are also available as an NPM package 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: 

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

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:

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: 

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: 

You can check out the tutorial for this CodePen here. 

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

You can check out the tutorial for this CodePen here. 

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: 

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.

Using JS template literals and HSL, one can form generative color palettes in a few lines of code. Here's an example:  

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

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

 


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:

function animate() {
  ...
  requestAnimationFrame(animate);
}
Enter fullscreen mode Exit fullscreen mode

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

Method 2, GSAP

Recently, I have been turning to the animation library GSAP 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. 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:


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. 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 - I learned to code watching this channel. Dan has fantastic videos on almost every generative subject you could think of.
  • Tyler Hobbs - Tyler is a fantastic artist who writes some incredible essays. A veritable banquet of generative treats.
  • The Nature Of Code - An excellent book on simulating natural systems in code.
  • More from me! - 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 @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 buy me a coffee.

Discussion (12)

pic
Editor guide
Collapse
jamesthomson profile image
James Thomson

Great write up. I've been using SVG in many different ways over the past years and love it. The fact that it's XML based makes it so easy to manipulate values and bring vector graphics to life.

Do you have much experience with canvas? As a lot of what's discussed in your article could be applied to canvas, I'd be interested in your take on the pros/cons between the two.

Collapse
georgedoescode profile image
George Francis Author

Cheers, James!

I started out doing generative stuff in canvas, by way of p5.js. I still love both SVG and Canvas, but most often reach for SVG nowadays. I tend to only switch to canvas / occasionally webGL when I really need the performance :)

Just as an example - if I was working on a piece with a particle system, or a piece with very large animated elements, I would choose canvas. For just about anything else, I would choose SVG.

It mostly comes down to simplicity for me. I personally just find SVG much easier/quicker to write. I can focus on the creative aspect rather than worrying about lower level graphics code.

Maybe this deserves a blog post of it's own... Thanks so much for taking the time to comment and for making me think about process. It's not something I usually give much thought to! 💡

Collapse
jamesthomson profile image
James Thomson

Thanks for the reply. Makes complete sense regarding particles/more intensive animations. Would enjoy a blog post on this. Tag me if you end up writing one 🙂

Collapse
blindfish3 profile image
Ben Calder • Edited

Nice article. I've used dynamically generated SVG in a couple of work projects, as well as personal projects, and found it really straightforward and flexible.

One suggestion I would make: it's also possible to dynamically render SVG with a component-based framework. I've managed that with Angular (some hoops to jump through) and Svelte (straightforward). I would expect it's possible in React but haven't tried yet...

Why would you do that? It allows you to write SVG markup inside component templates and then dynamically combine these components as you wish: so you can create component-based SVGs. One major benefit of this is that you can write SVG mark-up directly rather than generating it via code. I personally don't like the approach of manually setting attributes via method calls (D3 I'm looking at you) when I can simply write them directly in my markup. An example from Svelte:

<circle  cx={x} cy={y} r={r} fill={c} />
Enter fullscreen mode Exit fullscreen mode

Here's a rather mundane chart to demonstrate the principle; and something more fun :)

One word of caution though: from what I understand browsers are not always good at optimising animation in SVG - especially Chrome-based browsers - so for anything where animation performance is critical use canvas (I highly recommend PixiJS for 2d canvas work).

edit: reference for the comment on performance: Using SVG with CSS3 and HTML5.

Collapse
blindfish3 profile image
Ben Calder

Since it's a slow rainy day I decided to finally try this with React; so here's a simple demo: codepen.io/blindfish3/pen/LYbaNrw

No major issues implementing this; other than having to use <g> as a wrapper on some output. From what I remember that was also required in all components on Angular - as well as some additional configuration (I'll have to look that up later).

Of the three libraries I've now tried this approach with, Svelte is definitely the easiest to use with SVGs.

Collapse
georgedoescode profile image
George Francis Author

Awesome! I love this approach, too. I have used Vue a few times to do generative art stuff. It's a lovely way of working. I really appreciate you taking the time to make a demo, too! I'll have to check out Svelte...

Collapse
camerenisonfire profile image
Cameren Dolecheck

Excellent post with a lot of great examples and explanation. I'm super glad to find someone making quality write ups on generative designs here.

I've used generative design with SVGs for a marketing project that output branded designs for use in slideshows. It can be real rewarding find real-world use cases for generative designs; of course, doing it just for fun is great, too.

Also, Tyler Hobbs has long been my favorite gen-artist. He has a surprisingly level of expressiveness and emotion to his pieces that is hard to find in other gen-art works.

Collapse
georgedoescode profile image
George Francis Author

Thank you so much Cameren! That's wonderful to hear. I'm totally with you there, I love to see generative techniques applied to “real world” problems. Cheers!

Collapse
san00 profile image
Osania - sancodes

Hi George, thank you for another fantastic article.
This is great. I'm going to have some fun, trying out some generative art. I love the creativity. Thank you for sharing :)

Collapse
georgedoescode profile image
George Francis Author

Ah, Thank you for reading! I’m glad you found the post helpful 😊 Good luck on your generative journey! 🚞

Collapse
moritzrupp profile image
Moritz Rupp

The post is written very well!
I'm new to the SVG topic and wasn't aware of the possibility of the generative approach. That is awesome!

Thanks a lot for the input, ideas and the starter kit!

Collapse
georgedoescode profile image
George Francis Author

Ah, I'm so glad to hear it! Thank you for reading!