Gray Burst

Avatar of Chris Coyier
Chris Coyier on (Updated on )

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

I made this neat little gray burst thing. It’s nothing particularly special, especially compared to the amazing creativity on CodePen, but I figured I could document some of the things happening in it for learning reasons.

It’s SVG

SVG has <line x1 y1 x2 y2>, so I figured it would be easy to use for this burst look. The x1 y1 is always the middle, and the x2 y2 are randomly generated. The mental math for placing lines is pretty easy since it’s using viewBox="0 0 100 100". You might even prefer -50 -50 100 100 so that the coordinate 0 0 is in the middle.

Random numbers

const getRandomInt = (min, max) => {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;

It’s nice to have a function like that available for generate art. I use it not just for the line positioning but also the stroke width and opacity on the grays.

I’ve used that function so many times it makes me think native JavaScript should have a helper math function that is that clear.

Generating HTML with template literals is so easy

This is very readable to me:

let newLines;
for (let i = 0; i < NUM_LINES; i++) {
  newLines += `
    x2="${getRandomInt(10, 90)}"
    y2="${getRandomInt(10, 90)}"
    stroke="rgba(0, 0, 0, 0.${getRandomInt(0, 25)})"
    stroke-width="${getRandomInt(1, 2)}"

svg.insertAdjacentHTML("afterbegin", newLines);

Interactivity in the form of click-to-regenerate

If there is a single function to kick off drawing the artwork, click-to-regenerate is as easy as:


window.addEventListener("click", doArt);


I find it far more pleasing with stroke-linecap="round". It’s nice we can do that with stroke endings in SVG.

The coordinates of the lines don’t move — it’s just a CSS transform

I just popped this on the lines:

line {
  transform-origin: center;
  animation: do 4s infinite alternate;
line:nth-child(6n) {
  animation-delay: -1s;
line:nth-child(6n + 1) {
  animation-delay: -2s;
line:nth-child(6n + 2) {
  animation-delay: -3s;
line:nth-child(6n + 3) {
  animation-delay: -4s;
line:nth-child(6n + 4) {
  animation-delay: -5s;

@keyframes do {
  100% {
    transform: scale(0.69);

It might look like the lines are only getting longers/shorter, but really it’s the whole line that is shrinking with scale(). You just barely notice the thinning of the lines since they are so much longer than wide.

Notice the negative animation delays. That’s to stagger out the animations so they feel a bit random, but still have them all start at the same time.

What else could be done?

  • Colorization could be cool. Even pleasing, perhaps?
  • I like the idea of grouping aesthetics. As in, if you make all the strokes randomized between 1-10, it feels almost too random, but if it randomized between groups of 1-2, 2-4, or 8-10, the aesthetics feel more considered. Likewise with colorization — entirely random colors are too random. It would be more interesting to see randomization within stricter parameters.
  • More movement. Rotation? Movement around the page? More bursts?
  • Most of all, being able to play with more parameters right on the demo itself is always fun. dat.GUI is always cool for that.