Detecting CSS animation support

  • Revision slug: CSS/CSS_animations/Detecting_CSS_animation_support
  • Revision title: Detecting CSS animation support
  • Revision id: 72251
  • Created:
  • Creator: Sheppy
  • Is current revision? No
  • Comment new page; page created, 556 words added

Revision Content

CSS animations make it possible to do creative animations of content using nothing but CSS. However, there are likely to be times when this feature isn't available, and you may wish to handle that case by using JavaScript code to simulate a similar effect. This article, based on this blog post by Chris Heilmann, demonstrates a technique for doing this.

Testing for CSS animation support

This code will check to see if CSS animation support is available:

var domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');  
var pfx = false;
for(var i = 0; i < domPrefixes.length; i++ ) {
  if( elm.style[domPrefixes[i] + 'AnimationName'] !== undefined ) {
    pfx = domPrefixes[i];
    break;
  }
}

This code works by looking to see if the CSS {{ cssxref("AnimationName") }} property on the style collection for the element specified by the variable elm. Notice how this is done by iterating over all the possible prefixes for this property name, since all the major browsers are currently prefixing this property.

Once this code is finished running, the value of pfx will be false if CSS animation support isn't available, or it will be the appropriate prefix to apply to any of the CSS animation properties' names to work on the user's browser.

Animating using the selected prefix

Now that you know what the appropriate prefix is (or that CSS animation support is unavailable), you can animate.

if( pfx === false ) {
  // animate in JavaScript fallback
} else {
  elm.style[ pfx + 'Animation' ] = 'rotate 1s linear infinite';

  var csspfx = pfx.toLowerCase(),
      keyframes = '@-' + csspfx + '-keyframes rotate { '+
                  'from { -' + csspfx + '-transform:rotate( 0deg ); }'+
                  'to { -' + csspfx + '-transform:rotate( 360deg ); }'+
                  '}';
  if( document.styleSheets && document.styleSheets.length ) {
      document.styleSheets[0].insertRule( keyframes, 0 );
  } else {
    var s = document.createElement( 'style' );
    s.innerHTML = keyframes;
    document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
  }
}

This code looks at the value of pfx; if it's false, we know we need to use our JavaScript fallback code to perform our animation. Otherwise, we can use JavaScript to apply the desired animation effects.

Setting the animation property is easy; simply update its value in the style collection. However, adding keyframes is trickier, since they're not defined using traditional CSS syntax (which makes them more flexible, but harder to define from script).

To define our keyframes using JavaScript, we need to write them out as a CSS string. Because the prefixes for CSS are lower case and prefixed with an additional dash ("-"), we need to convert the prefix to lower case before using it; this is done on line 6. After that, the keyframes variable is set up, prefixing each attribute as it's constructed. This variable, once constructed, contains the complete description of all the keyframes needed by our animation sequence.

The next task is to actually add the keyframes to the page's CSS. The first thing to do is look to see if there's already a style sheet on the document; if so, we simply insert the keyframe description into that stylesheet; this is done in lines 11-12.

If there isn't already a style sheet, a new {{ HTMLElement("style") }} element is created, and its content is set to the value of keyframes. Then the new {{ HTMLElement("style") }} element is inserted into the document's {{ HTMLElement("head") }}, thereby adding the new style sheet to the document.

{{ JSFiddleLink("codepo8/ATS2S/2/embedded/result") }}

See also

Revision Source

<p>CSS animations make it possible to do creative animations of content using nothing but CSS. However, there are likely to be times when this feature isn't available, and you may wish to handle that case by using JavaScript code to simulate a similar effect. This article, based on <a class=" external" href="http://hacks.mozilla.org/2011/09/detecting-and-generating-css-animations-in-javascript/" title="http://hacks.mozilla.org/2011/09/detecting-and-generating-css-animations-in-javascript/">this blog post</a> by Chris Heilmann, demonstrates a technique for doing this.</p>
<h2>Testing for CSS animation support</h2>
<p>This code will check to see if CSS animation support is available:</p>
<pre class="brush: js">var domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');  
var pfx = false;
for(var i = 0; i &lt; domPrefixes.length; i++ ) {
  if( elm.style[domPrefixes[i] + 'AnimationName'] !== undefined ) {
    pfx = domPrefixes[i];
    break;
  }
}
</pre>
<p>This code works by looking to see if the CSS {{ cssxref("AnimationName") }} property on the style collection for the element specified by the variable <code>elm</code>. Notice how this is done by iterating over all the possible prefixes for this property name, since all the major browsers are currently prefixing this property.</p>
<p>Once this code is finished running, the value of <code>pfx</code> will be <code>false</code> if CSS animation support isn't available, or it will be the appropriate prefix to apply to any of the CSS animation properties' names to work on the user's browser.</p>
<h2>Animating using the selected prefix</h2>
<p>Now that you know what the appropriate prefix is (or that CSS animation support is unavailable), you can animate.</p>
<pre class="brush: js">if( pfx === false ) {
  // animate in JavaScript fallback
} else {
  elm.style[ pfx + 'Animation' ] = 'rotate 1s linear infinite';

  var csspfx = pfx.toLowerCase(),
      keyframes = '@-' + csspfx + '-keyframes rotate { '+
                  'from { -' + csspfx + '-transform:rotate( 0deg ); }'+
                  'to { -' + csspfx + '-transform:rotate( 360deg ); }'+
                  '}';
  if( document.styleSheets &amp;&amp; document.styleSheets.length ) {
      document.styleSheets[0].insertRule( keyframes, 0 );
  } else {
    var s = document.createElement( 'style' );
    s.innerHTML = keyframes;
    document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
  }
}
</pre>
<p>This code looks at the value of <code>pfx</code>; if it's <code>false</code>, we know we need to use our JavaScript fallback code to perform our animation. Otherwise, we can use JavaScript to apply the desired animation effects.</p>
<p>Setting the animation property is easy; simply update its value in the style collection. However, adding keyframes is trickier, since they're not defined using traditional CSS syntax (which makes them more flexible, but harder to define from script).</p>
<p>To define our keyframes using JavaScript, we need to write them out as a CSS string. Because the prefixes for CSS are lower case and prefixed with an additional dash ("-"), we need to convert the prefix to lower case before using it; this is done on line 6. After that, the <code>keyframes</code> variable is set up, prefixing each attribute as it's constructed. This variable, once constructed, contains the complete description of all the keyframes needed by our animation sequence.</p>
<p>The next task is to actually add the keyframes to the page's CSS. The first thing to do is look to see if there's already a style sheet on the document; if so, we simply insert the keyframe description into that stylesheet; this is done in lines 11-12.</p>
<p>If there isn't already a style sheet, a new {{ HTMLElement("style") }} element is created, and its content is set to the value of keyframes. Then the new {{ HTMLElement("style") }} element is inserted into the document's {{ HTMLElement("head") }}, thereby adding the new style sheet to the document.</p>
<p>{{ JSFiddleLink("codepo8/ATS2S/2/embedded/result") }}</p>
<h2>See also</h2>
<ul> <li><a href="/en/CSS/CSS_animations" title="en/CSS/CSS animations">CSS animations</a></li> <li>{{ CSS_Reference:animation() }}</li>
</ul>
Revert to this revision