17

I have a modified version of animate.css (added some delay, new timings and new positions), and it works really great when the classes are set by default (html document). But when I am adding the animate class dynamically via js, the animation is not executed!

Even more annoying, I did have it working at some point, but I can't get it to work again (using gumby framework and inview js to add a class when the element is on screen (adding .animated)) . The left box had the classes already in the html, and the right box have the .animate class added by js.

Example:
http://onepageframework.com/28_2_14/strange_anim.html

Any ideas why the right box is not animating?

Using the Gumby inview extension: http://gumbyframework.com/docs/extensions/#!/inview

Edit: added html:

<div class="six columns text-center fadeInLeftMedium delay_2 animated">
    <!-- left box content here -->
</div>
<div class="six columns text-center fadeInLeftMedium delay_2 inview" data-classname="animated">
    <!-- right box content here -->
</div>

css:

.animated {
    -webkit-animation-duration: 1s;
       -moz-animation-duration: 1s;
         -o-animation-duration: 1s;
            animation-duration: 1s;
    -webkit-animation-fill-mode: both;
       -moz-animation-fill-mode: both;
         -o-animation-fill-mode: both;
            animation-fill-mode: both;
}

.delay_2 {
    -webkit-animation-delay: 2s;
       -moz-animation-delay: 2s;
         -o-animation-delay: 2s;
            animation-delay: 2s;    
}

@-webkit-keyframes fadeInLeftMedium {
    0% {
        opacity: 0;
        -webkit-transform: translateX(-400px);
    }

    100% {
        opacity: 1;
        -webkit-transform: translateX(0);
    }
}
@-moz-keyframes fadeInLeftMedium {
    0% {
        opacity: 0;
        -moz-transform: translateX(-400px);
    }

    100% {
        opacity: 1;
        -moz-transform: translateX(0);
    }
}
@-o-keyframes fadeInLeftMedium {
    0% {
        opacity: 0;
        -o-transform: translateX(-400px);
    }

    100% {
        opacity: 1;
        -o-transform: translateX(0);
    }
}
@keyframes fadeInLeftMedium {
    0% {
        opacity: 0;
        transform: translateX(-400px);
    }

    100% {
        opacity: 1;
        transform: translateX(0);
    }
}

.fadeInLeftMedium {
    -webkit-animation-name: fadeInLeftMedium;
    -moz-animation-name: fadeInLeftMedium;
    -o-animation-name: fadeInLeftMedium;
    animation-name: fadeInLeftMedium;
}
code-zoop
  • 7,312
  • 8
  • 47
  • 56

3 Answers3

27

The reason is the same why you can't re-trigger CSS based animations by just subsequently removing and adding a class. The reason is that browsers batch-up these modifications and optimize away the animation. Reason and solutions are discussed here.

From the article, your options are (paraphrased):

  1. Add a small delay before re-adding the class (not recommended)
  2. Clone the element, remove it, and insert the clone
  3. Have 2 identical animations (attached to different css rules) and switch between them
  4. Trigger a reflow between removing and adding the class name:
        element.classList.remove("run-animation");
     // element.offsetWidth = element.offsetWidth; //doesn't work in strict mode
        void element.offsetWidth; // reading the property requires a recalc
        element.classList.add("run-animation");
  1. Change (cycle) the element's CSS animation-play-state attribute to paused or running (does not restart animation)
brichins
  • 3,825
  • 2
  • 39
  • 60
vanthome
  • 4,816
  • 37
  • 44
  • 2
    Edited to summarize the article contents here. I personally feel that 4 is the best approach and use that one myself now. – brichins Oct 13 '16 at 23:25
-1

By swaping the classes, it looks like it got it to work (aminated in the class, and fadeInLeftMedium as the data-classname):

<div class="six columns text-center fadeInLeftMedium delay_2 animated">
    <!-- left box content here -->
</div>
<div class="six columns text-center animated delay_2 inview" data-classname="fadeInLeftMedium">
    <!-- right box content here -->
</div>
code-zoop
  • 7,312
  • 8
  • 47
  • 56
-2

I think you just need to add animated as a class rather than as data-classname="animated"...

So basically:

<div class="six columns text-center fadeInLeftMedium delay_2 inview" data-classname="animated">
    <!-- right box content here -->
</div>

Should be:

<div class="six columns text-center fadeInLeftMedium delay_2 inview animated">
    <!-- right box content here -->
</div>

Otherwise the animation lacks a specified animation duration and without the animation-duration property specified the animation won't work.

apaul
  • 16,092
  • 8
  • 47
  • 82
  • The whole idea is to use inview to add the class, so that you will see the animation when scrolling down to that element. The left box is as you have set it up, and it does animate. But if the element is further down the page, the animation will be fired before the user can see it. – code-zoop Feb 28 '14 at 11:55
  • 1
    @code-zoop I'm just trying to say that you need something more like `$('your-element').addClass('animated, and whatever other classes);` so that the classes get added as classes rather than as data. – apaul Feb 28 '14 at 11:59
  • Yes, I understand. But the inview extension is taking the data from the data-classname and adding it as a class. Thats the whole idea with the inview extension, and it does add the class at it should, but the animation is not executed: http://gumbyframework.com/docs/extensions/#!/inview – code-zoop Feb 28 '14 at 12:02