How to create a loop animation that changes different background colors endlessly

I am trying to do the following animation:

I have eight circles, four small and four large. The first (small circle) has a green background, the rest of the small circles have a gray background, and the large circles have a red background. The animation adds a green background color to the circles one by one with every second that passes. When all the circles have a green background, then there will be a 1 second delay before the animation starts. The animation will repeat the animation endlessly.

TL; DR: jsFiddle

Initial state: 1 small circle in green, 3 small circles in gray, 4 large circles in red.

In between: one at a time, each color of each circle is green once every 1 second, until all circles are green.

Final state: 4 small and 4 large green circles. Reset the initial state and repeat the animation indefinitely.

- CHANGE START -

For those interested in the collective solution you've put together, you can find it in this jsFiddle , it includes both CSS and jQuery. When you first see it, it will be using jQuery; to see a pure CSS implementation, remove the CSS comment that will allow animation markup. Don't forget to comment jQuery.

- EDIT END -

Note. I'd rather only find a CSS solution , but I'm very new to CSS animation and it has been a real pain so far, so I came here to ask for help. However, if this is not possible using only CSS, please accept jQuery's solution. In light of that, here's what I've tried in jQuery to no avail:

Html

<div class="smallCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>
<div class="largeCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>

      

CSS

.smallCircles { 
    margin-bottom: 20px;
}
.smallCircles .circle { 
    display: inline-block;
    height: 25px;
    width: 25px;
    border-radius: 25px;    
}
.largeCircles .circle {
    display: inline-block;
    height: 75px;
    width: 75px;
    border-radius: 75px;
}
.smallCircles :first-child {
    background-color: green;
}
.smallCircles :not(:first-child)
    background-color: gray;
}
.largeCircles .circle { 
    background-color: red;
}
.bg--green {
    background-color: green;
}

.bg--gray {
    background-color: gray;
}

      

JQuery

jQuery(document).ready(function(){
    var elements = [jQuery(".smallCircles :nth-child(1)"),
                    jQuery(".smallCircles :nth-child(2)"),
                    jQuery(".smallCircles :nth-child(3)"),
                    jQuery(".smallCircles :nth-child(4)"),
                    jQuery(".largeCircles :nth-child(1)"),
                    jQuery(".largeCircles :nth-child(2)"),
                    jQuery(".largeCircles :nth-child(3)"),
                    jQuery(".largeCircles :nth-child(4)")
                   ];
    var count = elements.length;
    var i;
    var infinitely = 9999999999999999999999999999999999999999;

    for(i = 0; i < infinitely; i++){
        try {
            if (i % count === 0) {
                resetColors((i % count), elements);
            }
            else {
                colorEach((i % count), elements);
            }
        } catch(e) {
            console.log(e);
        }
    }

    function resetColors (i, elements) {
        if (i > 0) { // the changes in here will have occurred on the second loop
            var timer;
            setTimeout(elements.each(function(index, element){
                if(index > 0 && index < 4) { // omit the first element in the list    
                    element.removeClass("bg--green");
                    if(index < 4) { // only the small circles
                        element.addClass("bg--gray");
                    }
                    if(index > 3) { // only the large circles
                        element.addClass("bg--red");
                    }
                }
            }), 3000);
        }
    }

    function colorEach (i, elements)  {
        switch (i) {
            // Small Circles, except the first one
            case 1:
                colorBackground(i, elements, 1);
                break;
            case 2:
                colorBackground(i, elements, 1);
            case 3:
                colorBackground(i, elements, 1);
                break;
            // Large Circles
            case 4:
                colorBackground(i, elements, 0);
                break;
            case 5:
                colorBackground(i, elements, 0);
                break;
            case 6:
                colorBackground(i, elements, 0);
                break;
            case 7:
                colorBackground(i, elements, 0);
                break;
        }
    }

    function colorBackground (i, elements, type) {
        if(type) { // type 1: large circle
            var timer;
            setTimeout(function(i, a){
                console.log("timeout function at colorBackground i: " + i);
                a[i].removeClass("bg--red");
                a[i].addClass("bg--green");
            }, 3000);
        }
        else { // type 0: small circle
            var timer;
            setTimeout(function(i, elements){
                console.log("timeout function at colorBackground i: " + i);
                elements[i].removeClass("bg--gray");
                elements[i].addClass("bg--green");
            }, 3000);
        }
    }
}

      

My failed attempts at animating CSS, this is 100% without jQuery:

.smallCircle :nth-child(2) {
    animation: smallCircle-2 1s infinite;
}
.smallCircle :nth-child(3) {
    animation: smallCircle-3 2s infinite;
}
.largeCircle :nth-child(4) {
    animation: smallCircle-1 3s infinite;
}
.largeCircle :nth-child(1) {
    animation: largeCircle-2 4s infinite;
}
.largeCircle :nth-child(2) {
    animation: largeCircle-3 5s infinite;
}
.largeCircle :nth-child(3) {
    animation: largeCircle-4 6s infinite;
}
.smallCircle :nth-child(4) {
    animation: largeCircle-4 7s infinite;
}
@keyframes smallCircle-2 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes smallCircle-3 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes smallCircle-4 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes largeCircle-1 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes largeCircle-2 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes largeCircle-3 {
    99% { background:gray }
    100% {background:green;}
}
@keyframes largeCircle-4 {
    99% { background:gray }
    100% {background:green;}
}

      

+3


source to share


3 answers


This is only possible with CSS, if a little tedious. You need to set up a new keyframe animation for each circle. Each circle stays gray and then turns green 12.5% ​​(100 divided by 8) further into the animation than the previous animation. All animations are set within 8 seconds and inifinium announcements are repeated.

The following code example uses standard syntax. You might want to add vendor prefixes to provide legacy support, but all major browsers currently support this syntax.



jsFiddle

@keyframes a1 {
    0% { background-color: green; }
}
@keyframes a2 {
    12.5% { background-color: green; }
}
@keyframes a3 {
    25% { background-color: green; }
}
@keyframes a4 {
    37.5% { background-color: green; }
}
@keyframes a5 {
    50% { background-color: green; }
}
@keyframes a6 {
    62.5% { background-color: green; }
}
@keyframes a7 {
    75% { background-color: green; }
}
@keyframes a8 {
    87.5% { background-color: green; }
}

.circle {
    animation-duration: 8s;
    animation-iteration-count: infinite;
    animation-fill-mode: forwards;
    animation-timing-function: steps(1,end)
}

.smallCircles .circle:nth-of-type(1) {
    animation-name: a1;
}

.smallCircles .circle:nth-of-type(2) {
    animation-name: a2;
}

.smallCircles .circle:nth-of-type(3) {
    animation-name: a3;
}

.smallCircles .circle:nth-of-type(4) {
    animation-name: a4;
}

.largeCircles .circle:nth-of-type(1) {
    animation-name: a5;
}

.largeCircles .circle:nth-of-type(2) {
    animation-name: a6;
}

.largeCircles .circle:nth-of-type(3) {
    animation-name: a7;
}

.largeCircles .circle:nth-of-type(4) {
    animation-name: a8;
}

      

+4


source


Try to use .queue()



(function cycle(elems) {
  elems.queue("bg", $.map(elems, function(el, i) {
      return function(next) {
        setTimeout(function() {
          el.style.backgroundColor = "green";
          next();
        }, 1000)
      }
    })).dequeue("bg").promise("bg")
    .then(function(_elems) {
    console.log(_elems);
      setTimeout(function() {
        elems
        .slice(0, 1).css("backgroundColor", "green")
        .addBack()
        .slice(1, 4)
        .css("backgroundColor", "gray")
        .addBack()
        .slice(4)
        .css("backgroundColor", "red");
        cycle(_elems);
      }, 3000);
    });
}($(".circle")));
      

.smallCircles {
  margin-bottom: 20px;
}
.smallCircles .circle {
  display: inline-block;
  height: 25px;
  width: 25px;
  border-radius: 25px;
}
.largeCircles .circle {
  display: inline-block;
  height: 75px;
  width: 75px;
  border-radius: 75px;
  background-color: red;
}
.smallCircles .circle:first-child {
  background-color: green;
}
.largeCircles .circle {
  background-color: red;
}
.smallCircles .circle:not(:first-child) {
  background-color: gray;
}
.bg--green {
  background-color: green;
}
.bg--gray {
  background-color: gray;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="smallCircles">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>
<div class="largeCircles">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>
      

Run codeHide result


+2


source


Solution: This effect can be achieved entirely with keyframes and CSS animations.

Browser support I've included: Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

JSFiddle Demo

HTML:

<div class="smallCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>
<div class="largeCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>

      

CSS

.smallCircles { 
    margin-bottom: 20px;
}
.smallCircles .circle { 
    height: 25px;
    width: 25px;
}
.largeCircles .circle {
    height: 75px;
    width: 75px;
}
.circle {
    display: inline-block;
    border-radius: 50%;
    background-color: gray;
}

.circle {
    -webkit-animation: 8s infinite;
    -moz-animation: 8s infinite;
    -o-animation: 8s infinite;
    animation: 8s infinite;
    -webkit-animation-fill-mode: forwards;
    -moz-animation-fill-mode: forwards;
    -o-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
    -webkit-animation-timing-function: steps(1,end);
    -moz-animation-timing-function: steps(1,end);
    -o-animation-timing-function: steps(1,end);
    animation-timing-function: steps(1,end);
}

.smallCircles > .circle:nth-of-type(1) {
    -webkit-animation-name: state1;
    -moz-animation-name: state1;
    -o-animation-name: state1;
    animation-name: state1;
}
.smallCircles > .circle:nth-of-type(2) {
    -webkit-animation-name: state2;
    -moz-animation-name: state2;
    -o-animation-name: state2;
    animation-name: state2;
}
.smallCircles > .circle:nth-of-type(3) {
    -webkit-animation-name: state3;
    -moz-animation-name: state3;
    -o-animation-name: state3;
    animation-name: state3;
}
.smallCircles > .circle:nth-of-type(4) {
    -webkit-animation-name: state4;
    -moz-animation-name: state4;
    -o-animation-name: state4;
    animation-name: state4;
}
.largeCircles > .circle:nth-of-type(1) {
    -webkit-animation-name: state5;
    -moz-animation-name: state5;
    -o-animation-name: state5;
    animation-name: state5;
}
.largeCircles > .circle:nth-of-type(2) {
    -webkit-animation-name: state6;
    -moz-animation-name: state6;
    -o-animation-name: state6;
    animation-name: state6;
}
.largeCircles > .circle:nth-of-type(3) {
    -webkit-animation-name: state7;
    -moz-animation-name: state7;
    -o-animation-name: state7;
    animation-name: state7;
}
.largeCircles > .circle:nth-of-type(4) {
    -webkit-animation-name: state8;
    -moz-animation-name: state8;
    -o-animation-name: state8;
    animation-name: state8;
}

@-webkit-keyframes state1 {
    0% { background-color: green; }
    100% {background-color: green; }
}
@-moz-keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}

      

.smallCircles { 
    margin-bottom: 20px;
}
.smallCircles .circle { 
    height: 25px;
    width: 25px;
}
.largeCircles .circle {
    height: 75px;
    width: 75px;
}
.circle {
    display: inline-block;
    border-radius: 50%;
    background-color: gray;
}

.circle {
    -webkit-animation: 8s infinite;
    -moz-animation: 8s infinite;
    -o-animation: 8s infinite;
    animation: 8s infinite;
    -webkit-animation-fill-mode: forwards;
    -moz-animation-fill-mode: forwards;
    -o-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
    -webkit-animation-timing-function: steps(1,end);
    -moz-animation-timing-function: steps(1,end);
    -o-animation-timing-function: steps(1,end);
    animation-timing-function: steps(1,end);
}

.smallCircles > .circle:nth-of-type(1) {
    -webkit-animation-name: state1;
    -moz-animation-name: state1;
    -o-animation-name: state1;
    animation-name: state1;
}
.smallCircles > .circle:nth-of-type(2) {
    -webkit-animation-name: state2;
    -moz-animation-name: state2;
    -o-animation-name: state2;
    animation-name: state2;
}
.smallCircles > .circle:nth-of-type(3) {
    -webkit-animation-name: state3;
    -moz-animation-name: state3;
    -o-animation-name: state3;
    animation-name: state3;
}
.smallCircles > .circle:nth-of-type(4) {
    -webkit-animation-name: state4;
    -moz-animation-name: state4;
    -o-animation-name: state4;
    animation-name: state4;
}
.largeCircles > .circle:nth-of-type(1) {
    -webkit-animation-name: state5;
    -moz-animation-name: state5;
    -o-animation-name: state5;
    animation-name: state5;
}
.largeCircles > .circle:nth-of-type(2) {
    -webkit-animation-name: state6;
    -moz-animation-name: state6;
    -o-animation-name: state6;
    animation-name: state6;
}
.largeCircles > .circle:nth-of-type(3) {
    -webkit-animation-name: state7;
    -moz-animation-name: state7;
    -o-animation-name: state7;
    animation-name: state7;
}
.largeCircles > .circle:nth-of-type(4) {
    -webkit-animation-name: state8;
    -moz-animation-name: state8;
    -o-animation-name: state8;
    animation-name: state8;
}

@-webkit-keyframes state1 {
    0% { background-color: green; }
    100% {background-color: green; }
}
@-moz-keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state1 {
    0% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state2 {
    12% { background-color: gray; }
    12.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state3 {
    24.5% { background-color: gray; }
    25% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state4 {
    37% { background-color: gray; }
    37.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state5 {
    49.5% { background-color: gray; }
    50% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state6 {
    62% { background-color: gray; }
    62.5% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state7 {
    74.5% { background-color: gray; }
    75% { background-color: green; }
    100% { background-color: green; }
}
@-webkit-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@-moz-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@-o-keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
@keyframes state8 {
    87% { background-color: gray; }
    87.5% { background-color: green; }
    100% { background-color: green; }
}
      

<div class="smallCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>
<div class="largeCircles">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
</div>
      

Run codeHide result


Alternative: Due to browser compatibility, the code can be very repetitive as we use the same declarations but with different vendor prefixes. The best way to do this would be to use a CSS preprocessor like LESS . This would drastically shorten the code, example below.

SMALLER

@-webkit-keyframes some-animation {.state1;}
@-moz-keyframes some-animation {.state1;}
@-o-keyframes some-animation {.state1;}
@keyframes some-animation {.state1;}

.state1 () {
    0% { background-color: green; }
    100% {background-color: green; }
}

      

+2


source







All Articles