Optimizing pseudo-random SVG animations
Tags: webdev, css, animation, showdev
Published: 2024-01-09 12:47:39

When I [relaunched my portfolio website in 2021](https://dev.to/ingosteinke/creating-a-fast-and-beautiful-portfolio-website-using-html-css-and-eleventy-and-netlify-9f5), I added a colorful background animation possibly inspired by a tutorial. The animation starts several seconds after the page completes loading and setup, and only if there is no preference for reduced motion. I also added a stop button to respect the pause/stop/hide principle.

## Credits / Inspiration

I have yet to find and link inspirational and informative sources for "my" creation that I never understood entirely. With a deeper understanding, I can finally optimize the existing effect or replace it with a better alternative.

### From liquid gooey animations using CSS and SVG... 💦 

Here is some prior art, rediscovered in my bookmarks, filed under "liquid gooey animations, CSS, SVG", that must have influenced my own creation:

- [Codepad: SVG Liquid Animation](https://codepad.co/snippet/svg-liquid-animation)

Most other 2021 "animation" bookmarks focus on a liquid animation effect. Can I find anything else more specific in my codebase, in git, in chats or emails?

I had made a pull request called [Liquid flatfishy floundry vector animation](https://github.com/openmindculture/ingo-steinke.de/pull/34) with a meaningless commit history ("prepare liquid animation, remove backgrounds", "try liquid vector animations", "integrate liquid vector animation").

My changelog is equally nondescript: "UX: animations and other optional details" and "simplify animation for better performance". But the initial commit contains a code comment crediting the liquid animation codepad.

```
/* inspired by
 * https://codepad.co/snippet/svg-liquid-animation
```

I must have removed the comment when I thought that the original inspiration did not relate to the current code anymore.

### ... to a "flounder" (flat fish) animation! 🐟

What I ended up with was no typical "liquid animation" but something that goes in the same direction after simplifying the original "liquid" animation.

## Benefits

- unique effect
- positive reviews
- cross-browser
- lightweight, at least regarding the codebase
- "CSS only" ( + SVG filter + JS stop button)

## Problems / Challenges

- maintainability
- motion
- legibility
- performance
- empty intervals

Although I liked the visual effects and got positive reviews from developers and designers, some issues made me remove the animation and plan to replace it with a better version – better concerning motion, legibility, and performance.

### Maintainability 🙄

How can I maintain code that I don't entirely understand? That's a [technical debt](https://en.wikipedia.org/wiki/Technical_debt) I will have to reduce if I want to improve my codebase in the future. 

### Motion 🏃

Not everyone knows how to set a reduced motion preference or where to find a stop button when annoyed by an animation.

### Readability / Legibility 👓

I made semi-transparent text paragraph backgrounds to let the animation shine through. The background has a gradient between a more opaque and a more transparent side. All of this makes the text harder to read and should be disabled in favor of a completely opaque background when a high contrast setting is effective or indicated to be preferred.

## Empty intervals 🗌

This might be a feature, adding more variation, but it can also feel confusing: sometimes, there is no animated shape to be seen at all for several seconds.

I did not do this on purpose.

### Performance 🐌

But the biggest problem was that the animation seemed to waste energy and slow down page responsiveness in certain clients. In Firefox on desktop, I could tell the amount of additional CPU load when I heard the laptop fan increase its speed.

Despite positive audit scores and peer reviews from other developers, probably testing in Safari or Chrome on their high-end machines, I know it was far from perfect.

### Testability / Normalization 🟩

I don't remember the initial reason to start the animation after a delay, but it seemed to trick automated performance reviews and it makes page previews and automated screenshot testing much easier when the initial page view always starts with a minimal monochrome background.

## Solutions

The first version used large circular vector objects that changed their sizes and shapes continuously on a background layer much larger than the actual website.

A simpler approach should be possible after questioning my implicit assumptions!

### Size: smaller dimensions ⬇️

If the shapes were only partially visible, I could define pie slices instead of full circles. Maybe I could have a smaller circular shape that moves quickly and some larger objects that mostly stay where they are. 

### Motion: simplified movement 🏃

I don't even remember the original movement algorithm. Still, a simple, linear one can often be a good enough approximation to obtain the same visual effect as by using a complex mathematical piece of art.

### Distortion: does it matter? 🫠

The same should be true for shape-shifting: I can possibly simplify the distortion (transformation).

### Blur: does it matter? 🌫️ 

An additional Gaussian blur filter, inspired by some tutorial that I don't even remember, might also be dispensable.

### Simultaneousness 👯

Not all of the above needs to happen at once all of the time to obtain an illusion of constant movement and transformation.

### Perceived Motion

Even completely static images can appear to be moving thanks to contrast, detail and perspective, also known as op-art, painted on canvas more than 50 years ago by [Victor Vasarely](https://de.wikipedia.org/wiki/Victor_Vasarely), a designer .

### Perceived Randomness 🎲

What essentially makes an animation appear to be random?

We could introduce real random numbers as an optional detail. But the version above already appears to move randomly thanks to its [anticyclic cicade principle](https://devopedia.org/cicada-principle).

### "CSS only"

Technically, my original animation was quite simple.

There are 2 DIV elements and an optional SVG filter in the markup. The shapes and animation keyframes are defined in CSS. JavaScript is only used for the stop button.

## Unoptimized Vector Animation Demo 1

Reduced to the essentials, it's a "CSS only" animation that fits in [a simple codepen](https://codepen.io/openmindculture/pen/WNPxyBZ).

{% codepen https://codepen.io/openmindculture/pen/WNPxyBZ %}

## Optimized Vector Animation Demo 2

Approaching my functional (beautiful, pseudo-random liquid look) and non-functional requirements (more performant, maintainable, CSS-only animation) using the suggested strategies (minimize size and complexity), I came up with a [new animation](https://codepen.io/openmindculture/pen/BaMLJjP) that looks quite similar at first sight - or at least it demonstrates that we only need very simple 2d transformations to create complex motion effects. 

{% codepen https://codepen.io/openmindculture/pen/BaMLJjP %}

It's already too much happening in one place here.

We can remove the secondary object that was supposed to be the liquid drop-like effect moving quickly and add some other gimmick instead, like a blurry border or a real random seed.

Can you spot the differences in detail?

Here is a more recent codepen with some additional JavaScript lines for optional randomization.

{% codepen https://codepen.io/openmindculture/pen/JjxRLpj %}

I found the result was good enough to replace my first attempt on my [personal portfolio website](https://www.ingo-steinke.com/)!