CSS3 animation-fill-mode polyfill

99封情书 提交于 2019-12-30 04:04:09

问题


Preface

Let's pretend that a div is animated from opacity:0; to opacity:1; and i want to keep opacity:1; after the animation ends.

That's what animation-fill-mode:forwards; does.

@keyframes myAnimation {
    from { opacity:0; }
    to { opacity:1; }
}
div {
    opacity:0;
    animation-name:myAnimation;
    animation-delay:1s;
    animation-duration:2s;
    animation-fill-mode:forwards;
}​
<div>just a test</div>​

Run it on jsFiddle

  • Note 1: i didn't include the vendor prefixes here to simplify
  • Note 2: that's just an example, please don't reply with "just use jQuery fadeIn function" etc.

Some things to know

In this answer i read that animation-fill-mode is supported by Chrome 16+, Safari 4+, Firefox 5+.

But animation alone is supported by Chrome 1+ and Opera too. So a general test with Modernizr may return positive even if fill-mode is not supported.

To target animation-fill-mode i added a new test on Modernizr:

Modernizr.addTest('animation-fill-mode',function(){
    return Modernizr.testAllProps('animationFillMode');
});

Now i've a .no-animation-fill-mode class for CSS and Modernizr.animationFillMode for JavaScript.

I also read from CSS3 animations specs that:

an animation specified in the document style sheet will begin at the document load


Finally, the question(s)

Is it ok to run a simple jQuery function at the exact number of seconds the animation ends

$(document).ready(function(){
    if(!Modernizr.animation){
        $('div').delay(1000).fadeIn(2000);
    }else if(!Modernizr.animationFillMode){
        $('div').delay(3000).show();
    }
});

And in CSS:

.no-animation-fill-mode div {
    animation-iteration-count:1;
}
/* or just animation:myAnimation 2s 1s 1; for everyone */

Or is there any known polyfill specific for animation-fill-mode ?


Also, what happens if i use the shorthand syntax

animation:myAnimation 2s 1s forwards;

on browsers supporting animation but not animation-fill-mode ?

Thanks a lot!


回答1:


If it were me I'd try an opt for the simpler alternative - if possible. I'd downgrade my implementation so that I'm only using what is commonly accepted. Later on, when the feature is more widely supported I then think about implementing it. I rarely consider using a feature that has This is an experimental technology broadcast on documentation pages - but then maybe I should be classed as boring :)

In your example, you could achieve the same result as animation-fill-mode:forwards by defining the end state of your element initially, and using a chained animation (if a delay before the action is needed):

@keyframes waitandhide {
  from { opacity:0; }
  to { opacity:0; }
}
@keyframes show {
  from { opacity:0; }
  to { opacity:1; }
}
div {
  opacity:1;
  animation: waitandhide 2s 0s, show 2s 2s;
}
<div>just a test</div>​

http://jsfiddle.net/RMJ8s/1/

Now it is possible that slower browsers might flash up your initial element states before hiding them away again. But in my experience I've only seen this on very old machines and for pages that have a huge amount of css to render.

Obviously the above does bloat your css a bit more (as you have to duplicate styles), and it would be more complicated when dealing with complex animations. However:

  1. It should work for pretty much any animation situation.
  2. It would avoid the need for JavaScript (save for the $().fadeIn fallback).
  3. It will work on all browsers that support css animation.
  4. You don't run the risk of JS and CSS being/becoming unsynchronised.

With regard to using short-forms it would be best not to if you want to go for as wide reaching browser compatibility as possible. However, as shown in my examples above I have opted for using short-forms because they hold more clarity and I can understand not wanting to write (or read) the long-winded versions all the time. For this reason I would recommend using less to generate your css:

http://lesscss.org/

http://radiatingstar.com/css-keyframes-animations-with-less




回答2:


I don't know of any polyfill... But I'd say you should indeed use your own custom Modernizr test, and for browser that don't support animation fill mode, you should use the animationEnd event to trigger your callback and set opacity to 1 (or remove a class).

See: CSS3 transition events

As for the shorthand notation, IE <10 does not support the animation-fill-mode property and I'm pretty sure it would break the whole declaration.




回答3:


FYI, here's how i'm implementing pebbl's answer (which is a very clever answer) nowadays. I only need Modernizr's css-animation detection.

Let's suppose i want to slide and fade this div:

<div class="target">Some stuff</div>

first of all, i write down the animation with vendor prefixes

@keyframes byebye {
    0% { height:100px; opacity:1; }
    100% { opacity:0; height:0; }
}

then a new class

.target-animation {
    height:0; opacity:0; // same as "100%" state
    animation:byebye 750ms 1;
}

moving to javascript:

// $('.whatever').on('click',function(){ ...

if(Modernizr.cssanimations)
    // css animations are supported!
    $('.target').addClass('target-animation');
else
    // i hate you IE
    $('.target').animate({height:0,opacity:0},750);

Demo

If you need to trigger the animation multiple times, just remove the class with javascript as explained here:

// if(Modernizr.cssanimations) ...

$('target').addClass('target-animation').on('webkitAnimationEnd oAnimationEnd oanimationend animationend msAnimationEnd',function(){
    $(this).removeClass('target-animation')
    // don't forget to  .hide()  if needed
});

// ... else


来源:https://stackoverflow.com/questions/12534228/css3-animation-fill-mode-polyfill

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!