See the Pen IFTTT Slottt Machine by Jennifer Hamon (@jhamon) on CodePen.
At IFTTT we’re always looking for better ways to communicate what our service is and how people can use us to connect the services they love together in powerful ways. One idea I had for this was to create an animation based on the if-logo-then-logo style presentation of recipes used on the WTF page and elsewhere throughout the site. With 442 triggers and 172 actions available at the time of this writing, there are over 76,000 distinct recipes you can make on IFTTT. I really wanted to make something that would convey the wonderful variety of combinations that IFTTT makes possible.
The animation I was imaginging takes some visual inspiration from the spinners on a slot machine. After a little planning, I realized it wouldn’t be too difficult to pull off with some CSS sleight of hand and a bit of JavaScript. If you exclude the long list of asset urls, the finished JavaScript only weighs in around 50 lines. In this article, I’m going to explain how I was able to combine absolute positioning with overlow:hidden
and a small amount of jQuery to build a neat slot machine effect that works in all major browsers.
Game plan
I decided that one easy approach would be to have three types of elements:
- A mask: a wrapper div (or mask div) with a fixed size,
position: relative
andoverflow: hidden
. For this project, I chose the class nameslottt-machine-recipe__mask
. - An inner container to hold the icons: an inner div to hold the icon images with
position: absolute
. For this project I chose the class nameslottt-machine-recipe__items_container
. - The actual icons: I’m fortunate that IFTTT’s great design team had already done the work of preparing nice looking assets in standard sizes for each channel supported on our platform. To get around some weird issues I was having with unwanted extra spacing below
img
elements, I chose to make square divs with the icon images set as their backgrounds. I marked each icon div with the classslottt-machine-recipe__item
This setup is sufficient to conceal all but the “current” icon. The animation is achieved by manipulating the top
property on the absolutely positioned container. To drive home the CSS setup, you can see what this arrangement looks like with overflow: hidden
commented out and some extra border styles turned on:
Writing the CSS
All together, the CSS for those different elements looks something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Building the HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Starting with this basic skeleton, I still needed to add the divs for each icon. Since I had such a large number of icons to display and I wanted to be able to easily change them in the future without crawling through the raw html, I chose to build the innermost icon divs programmatically from a list of urls. I omitted the list to save space, but want to show the general approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
This code gets invoked to build a div for each icon after the page is loaded:
1 2 3 4 5 6 7 8 9 |
|
Basic Animation
Since the inner div has position: absolute
we can position it precisely with respect to the parent div as long as the parent has position: relative
. This means that changing which icon is displayed in the non-hidden area of the mask div can be done by setting the top
position property on the inner container div to a multiple of the image size (150 pixels in this case).
From there, making a “sliding” effect is just a matter of animating the change of the top
property with jQuery’s animate
function (docs here). We could have written our own loop to take care of this, but jQuery has already done a nice job of implementing different easing functions, like swing
, that specify a property’s rate of change over time. Using non-linear easing gives the animation a nice polished feel.
1 2 3 4 5 6 7 |
|
Forever upward
By now we are 90% to the finished result. But instead of randomly scrolling the icons up or down, I really wanted them to scroll infinitely in the same direction. To pull this off we need to do a small amount of extra work to pop elements off the top of our inner container and push them onto the end. By doing this, we can always scroll in the same direction without running out of icons to display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
You can see the resultant effect best by turning off the mask div’s overflow:hidden
property:
Fine-tuning slide distance
For the basic version of the animation, I was just choosing a random icon to scroll to with a function like this:
1 2 3 |
|
This was sufficient to test other aspects of the project, but in the finished product I really want to ensure that the icon we’re spinning to is sufficiently “far” away that the random slot machine feel is preserved; randomly choosing to stay at the current position or roll to an icon only a few notches away just isn’t as satisfying. So, we modify our random index selection to account for that and reject small index choices.
1 2 3 4 |
|
It’s not a problem to reject these small indices as slide targets because of the way we are popping elements off and pushing them onto the end. All the icons will be cycled through the different positions and will eventually be selected for display.
Conclusion
That about wraps it up, and I hope you learned something that will be useful to you in your future projects. You can view and tinker with the finished result on codepen.io.