Squigglevision a (real!) term for animation where the lines appear to squirm around, even when the object/scene is at rest. It’s part of the iconic look of shows like Dr. Katz, remember that?
Quite a unique look! It’s even patented. But the patent talks about five edited images and displaying them in “rapid succession”. Wikipedia:
In order to create the line oscillation effects that characterize Squigglevision, Tom Snyder Productions’ animators loop five slightly different drawings in a sequence called a flic.
On the web, if we had to animate five (or more) images in rapid success, we’d probably do it with a step()
-based @keyframes
animation and a sprite sheet. Here’s a great example of that by simuari that shows exactly how it works, with the sprite sheet on top (10 images combined into 1) and the animation below.
But that’s a lot of work! There is a way we can get the wiggle jiggle squiggle on any element without having to hand-craft a bunch of individual images and make bespoke keyframes of specialized sizes to make it work.
The trick?
Rapidly iterated SVG turbulence filters
Whaaaat? Yep, it’s so cool.
I learned this trick from David Khourshid who made a wonderful demo, Alex the CSS Husky (look below), where the squiggling wasn’t even the main feature of the demo! David says he got the trick from Lucas Bebber in another demo I’ll embed below.
(That’s my forked version for a tiny Firefox fix: you can’t display: none;
the SVG in Firefox.)
Here’s how a single SVG turbulence filter works. First, you declare it with some inline <svg>
:
<svg display="none">
<defs>
<filter id="turb">
<feTurbulence baseFrequency="0.3" numOctaves="2" />
<feDisplacementMap in="SourceGraphic" scale="20" />
</filter>
</defs>
</svg>
Then you can apply it to any HTML element like this:
.filter {
filter: url("#turb");
}
Here’s a before/after:
That’s a pretty extreme amount of turbulence. Try cranking it down to baseFrequency="0.003"
and see a way more subtle version. Hmmm—almost looks like a very slight squiggle, doesn’t it?
The trick is to use just a smidge, make several different ones, then animate between them.
Here are five different turbulence filters, all slightly different from each other, with different ID’s:
<svg>
<filter id="turbulence-1">
<feTurbulence type="fractalNoise" baseFrequency="0.001" numOctaves="2" data-filterId="3" />
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="25" />
</filter>
<filter id="turbulence-2">
<feTurbulence type="fractalNoise" baseFrequency="0.0015" numOctaves="2" data-filterId="3" />
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="25" />
</filter>
<filter id="turbulence-3">
<feTurbulence type="fractalNoise" baseFrequency="0.002" numOctaves="2" data-filterId="3" />
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="25" />
</filter>
<filter id="turbulence-4">
<feTurbulence type="fractalNoise" baseFrequency="0.0025" numOctaves="2" data-filterId="3" />
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="25" />
</filter>
<filter id="turbulence-5">
<feTurbulence type="fractalNoise" baseFrequency="0.003" numOctaves="2" data-filterId="3" />
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="25" />
</filter>
</svg>
And a CSS keyframes animation to animate between them:
@keyframes squigglevision {
0% {
filter: url("#turbulence-1");
}
25% {
filter: url("#turbulence-2");
}
50% {
filter: url("#turbulence-3");
}
75% {
filter: url("#turbulence-4");
}
100% {
filter: url("#turbulence-5");
}
}
Which you call on anything you wanna squiggle:
.squiggle {
animation: squigglevision 0.4s infinite alternate;
}
That’s pretty much exactly what’s happening with Alex the CSS Husky, only the filters are even more chill.
Here’s Lucas’ original demo: