Generating visual designs with code
Why designers should be excited about programming
There is an ongoing debate over whether or not designers should learn how to code. I tend to side with the proponents because it allows you to solve entirely new classes of problems (and design is, after all, mostly problem solving). For those with an aversion to coding, I’d like to present an argument for learning to program that you may not have considered before.
We designers are, of course, visual thinkers. Sure, you can write code that will sort an array, but you can also write code to create pixels. If you’ve written CSS, you’ve already witnessed plain text transforming into pixels. Let’s take that concept to the next level.
My co-worker, James Kang, recently created one of my favorite Octocats for our GitHub Bounty site.
Writing code to simulate smoke is interesting, but very specific to one situation. I’d like to talk about a technique that is capable of creating nearly endless design variations with the same code.
A little while ago, we used to show a generic placeholder if you didn’t have an avatar on your GitHub profile. Generally speaking, this was fine, but it was somewhat annoying when viewing organization member pages or discussion threads with a bunch of avatar-less users.
We decided to generate “identicons” for users without avatars. The idea of identicons has been around a while and it’s a way to visually represent a unique value. In our case, every user has a unique user ID and we generate a sort of retro graphic specific to them.
The same few dozen lines of code can create millions of combinations of colors and patterns. If this sounds interesting, put on your propeller hat and continue on.
We were recently presented with a couple of similar design problems. We were launching a site called GitHub Guides as well as an updated Explore Showcases feature on GitHub.com. For both, we wanted to have some sort of distinct visual design for each guide and each Showcase category, but we didn’t want to rely on a designer or illustrator to create ongoing custom artwork.
Using the idea behind the identicons to generate unique colors and patterns seemed to make sense. We’re going get a little technical now, but if you lean into it, I promise it’ll be fun.
The key to creating these sorts of generative designs is the SHA. There’s a family of algorithms used in cryptography to generate “hashes” of strings so they can be stored securely (e.g. your password is encrypted before storing it in a database). Pretty much all programming languages have SHA libraries you can use.
This may all sound intimidating, but the only thing we care about in this case is that no matter what text we put into the SHA function (I’m specifically using the SHA1 function which you can tinker with here), we’ll get back a 40 character hexadecimal string (the same characters you use in your CSS colors).
For example, the string Making pixels with code becomes
Believe it or not, we now have everything we need to make cool patterns.
GeoPatterns: a case study
Since every GitHub Guide and Explore Showcase section has a name, we can use that to generate a SHA. One nice thing about this technique is that even if the name changes by a single character, the entire SHA changes entirely. This means that even if your strings are relatively similar, their SHAs will be very different.
I wrote a Ruby library called geo_pattern which is open source and free to use. In a nutshell, you give it a string (like the title of an article) and it generates a unique SVG image that can be tiled as a background image.
We do this by using the values at different positions in the SHA. I arbitrarily chose to look at the character at position 20 (which is f, with the first character at position 0) to decide which of 16 types of patterns to use. Why 16? Because a single hex character can be 0 through f, or 16 possible values.
f3da29ce23e96dc8b38d f 6ab3b6aaf7995cc581a
This value corresponds to a pattern called chevrons in the geo_pattern library. Again, these were all arbitrary decisions — you get to make up all of the rules when doing something like this.
Still with me? Great! There’s one more important concept I want to explain before continuing.
We’re going to want to define colors and sizes within certain acceptable ranges (e.g. the size of a shape should be between 25 and 100 pixels), but all of our values are 0 — 15. We want to map a given value from one range to another range.
For example, let’s say we have the hexadecimal value 5 (which could have been anything between 0 — 15) and we want to map it to a range of 25 — 100.
Continuing on, let’s take a look at how we come up with a background color. The library uses a base color which then gets modified based on certain SHA values.
First, we use the SHA characters at positions 14, 15, and 16 to determine how far to shift the hue.
f3da29ce23e96d c8b 38df6ab3b6aaf7995cc581a
We’re looking to shift the hue somewhere between 0 and 359°. Converting c8b from hex to decimal gives us 3211. The minimum we could have gotten from those three characters was 0 and the maximum would have been 4095. Next we map our 0 — 359 scale to our 0 — 4095 version with 3211 on it and get 281. So we shift our hue 281°.
The saturation gets adjusted similarly, but it just uses a single SHA value. If the value is even, the saturation gets increased and decreased if it’s odd. In the case of the identicons, I also adjusted the luminosity value.
When the various color adjustments have been made, we have a background color of #77903f.
Continuing on, we start drawing a 6x6 grid of chevron shapes. This means we’ll use 36 out of the 40 characters in the SHA. First though, how big should each chevron be? We look at the first character (f) and map that to a value between 30-80 pixels. It’s easy to see that f maps to 80 here, so our chevrons will be 80x80 pixels. We could have gotten a little fancier and used one value for the width and another for the height.
As we walk through the SHA values, we set their color to either black or white depending on if they are even or odd. The opacity is then set by mapping the 0 — 15 value to one in the 0.02 — 0.15 range.
We now have one tile that can be repeated as a background image. There’s a little extra work involved in making sure the various patterns can tile seamlessly. For example, this one requires that the top and bottom rows are the same and that only half of each is visible.
If you’ve never ventured out of Photoshop or past some basic HTML and CSS work, this is all probably a little overwhelming. But hopefully, it’s a little exciting too. I think it’s pretty awesome to be able to make up your own rules, code them up, and then see what sorts of designs come out of it.