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):
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
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
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
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.
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 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.