Looping a CSS Transition by kirupa (https://www.kirupa.com/me/index.htm) | filed under Web Animation (https://www.kirupa.com/html5/learn_animation.htm) The story of the transition is an epic tale of overcoming trials and tribulations. From being ignored by all the browsers to shamelessly having to carry around a vendor prefix to now near-universal acceptance, the journey sure was a bumpy one. Despite the great progress the transition property has made in the past few years, there are certain things that it simply cannot do easily when compared to its slightly taller, slightly more handsome ancestor, the animation. I fully describe the differences between transitions and animations in my CSS3: Animations vs. Transitions (https://www.kirupa.com/html5/css3_animations_vs_transitions.htm) tutorial, but there is one important limitation transitions have that I would like to present a workaround for here. That limitation is that transitions do not have a property that allows them to loop. That's right! In today's modern age, a transition is designed to only run once. That is a shame. Fortunately, there is a way to make things right. In this tutorial, I will show you how you can make transitions loop using a simple trick that involves the transitionend event (https://www.kirupa.com/html5/the_transitionend_event.htm). The Example To prove to you that I am only partly crazy, below is an example where I show a transition that loops forever. Simply hover over the blue circle to see the transition start...and never stop: Notice that the circle oscillates between being larger and smaller. By the end of this tutorial, you will create something similar and learn all about how it works. How to Make a Transition Loop Before we dive into creating something, let's first take a step back and understand what exactly it is that we are going to be doing. To help with this, let's bring in my sexy assistant, the amazing circle: [Image: the circle] (https://www.kirupa.com/html5/images/yellow_circle.png) What I want to do is have a transition that acts on a size change. My circle has an initial size. Let's generically call this initial state as stateOne. What I want is to play a transition when my circle gets much larger. This larger state I will call stateTwo: [Image: circle hovered] (https://www.kirupa.com/html5/images/yellow_circle_2.png) Seems pretty simple so far, right? I start off in in stateOne, and now I trigger a transition where I change the size of my circle to the values defined by stateTwo: [Image: initial transition] (https://www.kirupa.com/html5/images/initial_transition_2.png) Because I have a transition defined, instead of suddenly going form stateOne to stateTwo, the circle gradually animates to its final, larger size. Remember, it doesn't matter how I triggered the size change to stateTwo. It could have been by swapping class values on my circle element. It could have been a different size value specified on hover - similar to the example you saw earlier earlier. It could have been me using some JavaScript to change the size on the circle directly. It could have been accomplished in any number ways. It doesn't matter how you triggered the property change. As long as you have a transition defined whose property it is listening for gets changed, the transition will start running. Right now, everything I've said so far should be pretty much a review of what you already know about transitions. Let's change that, for here is where the new stuff comes in. What I want to do is loop this transition. By default, once I transition from stateOne to stateTwo, nothing else happens. Sometimes, depending on how I have my CSS setup, I may go back to stateOne. That's pretty much the extent of what you will see by default. What I want to do is loop the transition by never having it stop. Once I kick the transition down the road, I want to have my circle's size oscillate between values defined in stateOne and stateTwo...forever. When the circle hits stateTwo, I want it to transition back to stateOne. After reaching stateOne, I want the circle to transition back to stateTwo. At stateTwo, I want the...well, you get the picture. Below is a picture to illustrate the loopiness of what I am describing: [Image: looping states] (https://www.kirupa.com/html5/images/looping_states.png) How are we going to do this? Certainly not the easy way! Like I mentioned earlier, the problem is that the CSS transition property doesn't contain something built-in that allows you to specify looping. We are going to have to figure something out on our own. That something is actually pretty sneaky. What we are going to do is wait for the transition to finish. Once the transition finishes, we will forcibly change the properties the transition is listening for. By changing the very properties the transition listens carefully about, your transition starts all over again...running until the new property value you specify is reached. Now that we have a good idea of how to make our transition loop, let's go a little bit into implementation. Detecting when a transition ends is done by listening for the transitionend event. Each time we hear the transitionend event, we will have some JavaScript that changes the properties the transition is listening for. At the end of stateOne's transition, the transitionend event will fire. At this point, we will react by having our JavaScript tell our circle to go to stateTwo. When stateTwo is reached, another transitionend event will fire. This time, we react by telling our circle to go back to stateOne. This will go on for a while, as you can imagine. Here is a diagram that visualizes the looping: [Image: transition end] (https://www.kirupa.com/html5/images/initial_transitionend.png) The initial transition is triggered by whatever approach you use for triggering it. How it gets triggered doesn't matter. What does matter is that all subsequent transitions are triggered via JavaScript. That's where our transitionend trickery kicks in, and the rest (as they say) is history. In the next few sections, let's bring this trickery to life. Getting Started Ok, we can finally get our hands dirty and take all the explanation you saw in the previous paragraphs and put them to work. If you don't want to get your hands dirty and would prefer to just read and passively follow along, go ahead and skip this section and move on to the next one. If you want to actively follow along with this tutorial and re-create the example you see above, create a new HTML document and copy/paste the following HTML and CSS into it: