Easier SVG Animation with Sass

I was working on a project recently where I needed to animate an SVG seven segment display. I thought that this would be a great place to use CSS animation and @keyframes but there would be a lot of repetition in the CSS so I scripted it with Sass.

I’ve put together a Sassmeister example (click on the “Result” tab to see it in action):

Play with this gist on SassMeister.

This will only work in IE10+ and modern Chrome, Safari, Firefox.

Elements of Note

There are some specific elements of the solution that I wanted to call out.

Segment Animation Mixin

[gist id=”eafd9e4c18368fdab02c” file=”seg-animation.scss”]

This is the meat of the solution. I am using iteration and calculation to build the @keyframes for the animation. This mixin is called once for each of the seven segments.

Line 1: First, I figure out how big each “slice” of the animation will be ($seg__slice).

Line 6: Then, I iterate from 1 (assuming the animation starts at 1) through the target number.

Line 7: For each iteration I output what the keyframe percent should be for the given target number.

Lines 8-9: I save the $seg__opacity in a variable rather than outputting directly because I want to ensure that I end at the last state on Line 13.

Segment Opacity Function

[gist id=”eafd9e4c18368fdab02c” file=”seg_opacity.scss”]

Since I’m just dealing with turning opacity on and off, I used a bit mask to make the logic easier.

Each element in the $seg_mask map represents a segment in the display and each element in the list value represents the state for a particular digit.

Seven Segment SVG

[gist id=”eafd9e4c18368fdab02c” file=”SassMeister-rendered.html”]

In my first attempt at this, I was changing the SVG fill color in the animation – but I realized that it would be more efficient to manipulate opacity. With this in mind, I updated the SVG to have two sets of segments – on and off. The “off” segments will always be the grey color and the “on” segments will always be the red color. In the animation I simply change the opacity of the “on” segments.

Main Sass

[gist id=”eafd9e4c18368fdab02c” file=”main.scss”]

This is what actually outputs the CSS – everything else is mixins or functions.

Lines 1-9: I used an extend for the default state so that it was shorter in the CSS.

Line 11: The animating class is there to facilitate starting/stopping the animation via JavaScript by simply adding or removing that class.

Line 12: I created the seg_list() function to avoid having to repeat my segment names (tr, br, b, bl, tl, t, m).

Line 14: I used the step-end transition because I wanted a hard change from one state to another, not a gradual fade.