How to create the snake highlight animation with anime-js

When I came across SVG line animation a couple of years ago I was immediately amazed. I remember feeling that this was something I hadn’t seen before. It felt like a new direction for animations on the web. Something fresh. Line animation was at the time quite different from most effects used around 2013/2014. There and then most animations were CSS transitions, moving parts in all directions. SVG was sparsely used. This resembled somebody actually drawing real figures or sketching on paper.

Below are two early demos showing the technique:

If you are unfamiliar with how the technique works there’s a concise overview on CSS-tricks. It’s well worth a read as it goes through the fundamental parts needed to create the effect.

The trick is to use a pattern of dashes and gaps on SVG strokes. The CSS rules stroke-dasharray and stroke-dashoffset together control the format of this pattern. If we make the gaps between the dashes big, equal to or bigger than the length of the path. Then, by changing the offset of the pattern it appears as a line moving along a path.

Slithering serpents

The snake highlight demo is one of my pens on Codepen. It uses the line animation technique. The demo shows a login screen with the usual email, password and submit button that you’d find in any web login form. The idea here is to create an effect where the underline/highlight guides the user through the from. As the user changes focus from one input to another the line gently slides between the inputs. By using motion we guide and encourage the user to fill out the form. Here’s the demo:

Snake Highlight demo

Finding the inspiration

As often, I didn’t have one single source of inspiration creating this demo. Ideas came from all over the place. One reference to mention though is the below Codrops demo. It too uses the SVG line animation technique but with a slight twist. Here it’s used to animate between two well-defined shapes rather than starting off with a blank paper. The demo toggles between a hamburger menu and a close the menu figure (X). I am reusing the same principle to animate between different well-defined visual states.

There are plenty of other demos showcasing similar ideas on dribbble. Below are two examples:

What goes where?

The form more or less hasn’t change since the early days of HTML. It is a <form> element with inputs and labels. The line parts is in an absolute positioned <svg> element. It’s placed under the form to allow the user to setting focus to the different input elements. An SVG is obviously needed here as the line animation technique relies on strokes. The technique operates on one line at the time. Thus, the line needs to include all the visual states to animate between. I.e. we need draw the line in one whole stroke without lifting the pen. The three different visual states to create are: 1. One underline each for the two inputs (email & password). 2. An outline with rounded corners around the submit button.

SVG highlight/outline path

The above figure is what the complete path looks like displayed in a vector editor (Inkscape). The line starts from topmost left corner. From there it continues through two curves down to the closed super-ellipse in the bottom. That is the part that looks like a velodrome. The last point of the line is the left node of the rightmost pair in the bottom. This is the pair sitting on closed loop (the velodrome) surrounding the submit button. The line overlaps a bit in the end to give some slack. This means that the last part of the animation doesn’t need to be as accurate as the other parts. Another thing to pay attention to is the curves connecting the visual states. These parts are essential for the animation. They makes it possible for the line to slide between the inputs.

Moving things

Let’s break down the animation into separate steps. This is one of the more obvious breakdowns as we have three distinct states to animate between. To trigger these animations we’ll use the focus event. The browser will fire off this event when one of the inputs gets focused. That happens regardless of how inputs receive focus. E.g. by keyboard, mouse, touch etc. Let’s start out with handlers.

const email = document.querySelector('#email'),
password = document.querySelector('#password'),
submit = document.querySelector('#submit');
email.addEventListener('focus', (e) => { ... });
password.addEventListener('focus', (e) => { ... });
submit.addEventListener('focus', (e) => { ... });

The first thing to do in these handlers is to stop (pause) the previous animation, if such exist. This will allows users to interrupt animations.

if (current) { current.pause(); }

The above assures that there are never more than one animation running at the same time.

Dashes and gaps

Next up is the animation triggers. Before we get into the animation syntax we need to figure out the dash and gap properties. This is tricky part so what better way to illustrate finding these values than with a video.

Finding the dashed pattern properties

Let’s walk through the video. The first thing to do is to create the initial step. The step where the underline sits under the email input. To do so we need two things 1. the length of the underline and 2. the length of the whole path. The reason why we need the total length is to create a wide gap as discussed above. I happen to know that the underline is 240px wide. I know this since the input has that width specified in the CSS. To determine the total length of the path there’s an API called getTotalLength(). Calling this function on the SVG path element gives us the complete length of 1391px. These two values give us the stroke properties for the first and the initial visual step. The length of the dash and the length of the gap. This is what it looks like in CSS:

/* stroke-dasharray: <dash> <gap> */
stroke-dasharray: 240 1391

For the second step we need to figure out how much we need to offset the dashed pattern. Since both inputs are equally wide we don’t need to change the dash’s length nor the gap’s. We only need to know how much to move the line to place it under the password input. Using the dev tools we can easily spot that value:

stroke-dashoffset: -336

Last but not least, the outline. Since the outline is longer we need to change both dash properties. The outline is more than twice as long as the underlines. Here are the values for the outline:

stroke-dasharray: 553 1391
stroke-dashoffset: -728

The animation syntax

Now that we have the values let’s have a look at what the animation triggers look like in code. This is a matter of translating them into the format that animejs is using. Calling the anime function in the animejs library creates and starts an animation. Animating to first visual state looks like this:

current = anime({
targets: 'path',
strokeDashoffset: {
value: 0,
duration: 700,
easing: 'easeOutQuart'
},
strokeDasharray: {
value: '240 1386',
duration: 700,
easing: 'easeOutQuart'
}
});

Three things to note above 1. It’s a bit sloppy to use the ‘path’ selector. I get away with it here since there’s only one path and this is a demo. In production code you should use a class hierarchy and some method to structure your CSS/markup. 2. I am only specifying where the animation ends and not where it starts. Animejs supports both implicit and explicit start values. Using implicit start values allows the animation to be interrupted as discussed above. This ensures that the line never jumps between positions. 3. Last but not least, it is always worthwhile to spend some time to find a suitable duration and easing. Animations should be smooth and fluid but at the same time subtle and non-intrusive.

Under the hood

Below is a simplified version of the demo, which shows the animation inside the form. It shows what the animation looks like under the hood. I.e. the placement of the line and how it moves between inputs.

The demo explained

A splash of color

As this is 2018 I obligated to add a splash of color to the demo. Preferably a gradient. If I were to suggest #f00 and #f0f a couple of years ago people would have laughed at me. Today, nothing out of the ordinary.

Wrapping it up

SVG line animation is a fun and creative technique to create alternative effects. We can use it to make tedious user tasks like logging in more lively and charming. Using motion and animation to follow the focus is a good UX pattern. It helps and guides users in the right direction

This is the third article in my series about animating with anime-js. If you’re interested in reading more about anime-js I recommend my previous articles:

  1. How to create a favorite animation with anime-js
  2. How to create a checkmark animation with anime-js

As always, live, learn & engage. All (almost) comments are welcome! You can follow me on Twitter & Codepen if you want to know more about my adventures into the web. Good luck with your animations!