28

How would I detect that a browser supports CSS transitions using Javascript (and without using modernizr)?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Toby Hede
  • 36,755
  • 28
  • 133
  • 162
  • Using [minified Modernizr to test for CSS transitions only](http://modernizr.com/download/#-csstransitions-testprop-testallprops-domprefixes), the entire block of code is just over 2000 bytes. Larger than the other tests posted here, but hardly enough to trouble a user. (I prefer Modernizr because sooner or later, every website grows and needs more than one of its tests.) – Blazemonger Nov 25 '13 at 14:52
  • 13
    I will never understand the motivation of people suggesting something that the asker has specifically asked to NOT use. – L0j1k Jun 10 '14 at 18:52

5 Answers5

48

Perhaps something like this. Basically it's just looking to see if the CSS transition property has been defined:

function supportsTransitions() {
    var b = document.body || document.documentElement,
        s = b.style,
        p = 'transition';

    if (typeof s[p] == 'string') { return true; }

    // Tests for vendor specific prop
    var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];
    p = p.charAt(0).toUpperCase() + p.substr(1);

    for (var i=0; i<v.length; i++) {
        if (typeof s[v[i] + p] == 'string') { return true; }
    }

    return false;
}

Adapted from this gist. All credit goes there.

David Sherret
  • 101,669
  • 28
  • 188
  • 178
vcsjones
  • 138,677
  • 31
  • 291
  • 286
  • I submitted a change for `Ms` => `ms`, which is how IE exposes their vendor prefixes dom styles. (They're weird.) Toby, why are you trying to do this sans-Modernizr? – Paul Irish Sep 02 '11 at 07:08
  • 13
    @paul trying to get the latency and size down (way down), and modernizer is quite large for this single detection that we need. – Toby Hede Sep 02 '11 at 11:12
  • 6
    toby, modernizr has a modular build generator which gets the filesize WAY down. You should take a look. Right now this code will fail to detect transition support in IE10. Such is the case with reinventing wheels. :/ – Paul Irish Sep 21 '11 at 14:52
  • @vcsjones, can you update the code to use `ms` instead of `Ms`? – Paul Irish Sep 21 '11 at 14:53
  • didn't know there was such a thing as a 'style' object inside an element, good stuff – leopic Dec 06 '12 at 18:18
  • @PaulIrish works for me in IE10 (win7+8). Did they change anything in the meantime ...!? – Philipp Kyeck Sep 03 '13 at 09:17
  • `v` is a global variable and the line should end with a `;` not a `,`. So the line should read `var v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'];` – Dan Jan 17 '14 at 15:48
  • Webkit seems to use the lower case format now for transform i.e. "webkitTransform"...? When did that come about? – marksyzm Jan 20 '14 at 11:46
  • Would something like this be more reusable? https://gist.github.com/jehoshua02/d33892df58a95244cf5c – Stoutie Sep 05 '14 at 01:05
  • Deobfuscated: https://gist.github.com/VelizarHristov/18e66fa9185b2d187783fa91f87e6927 – Velizar Hristov Oct 04 '18 at 11:22
  • Also, this doesn't work on my app, which uses Vue.js. It always returns true. On closer inspection, both the first and the second if statement always return true, and the the detected string is always an empty string. If I only return true on nonempty strings, then it always returns false - even during animations. – Velizar Hristov Oct 04 '18 at 11:24
34

3 ways of doing so:

var supportsTransitions  = (function() {
    var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
        v = ['ms','O','Moz','Webkit']; // 'v' for vendor

    if( s['transition'] == '' ) return true; // check first for prefeixed-free support
    while( v.length ) // now go over the list of vendor prefixes and check support until one is found
        if( v.pop() + 'Transition' in s )
            return true;
    return false;
})();

console.log(supportsTransitions) // 'true' on modern browsers

OR:

var s = document.createElement('p').style,
        supportsTransitions = 'transition' in s ||
                              'WebkitTransition' in s ||
                              'MozTransition' in s ||
                              'msTransition' in s ||
                              'OTransition' in s;

console.log(supportsTransitions);  // 'true' on modren browsers

If you actually want to use the right prefixed, use this:

function getPrefixed(prop){
    var i, s = document.createElement('p').style, v = ['ms','O','Moz','Webkit'];
    if( s[prop] == '' ) return prop;
    prop = prop.charAt(0).toUpperCase() + prop.slice(1);
    for( i = v.length; i--; )
        if( s[v[i] + prop] == '' )
            return (v[i] + prop);
}

// get the correct vendor prefixed property
transition = getPrefixed('transition');
// usage example
elment.style[transition] = '1s';
vsync
  • 118,978
  • 58
  • 307
  • 400
5

As of 2015, this one-liner should do the deal (IE 10+, Chrome 1+, Safari 3.2+, FF 4+ and Opera 12+):-

var transitionsSupported = ('transition' in document.documentElement.style) || ('WebkitTransition' in document.documentElement.style);
Samuel Katz
  • 24,066
  • 8
  • 71
  • 57
2

Here the way I used:

    var style = document.documentElement.style;

    if (
        style.webkitTransition !== undefined ||
        style.MozTransition !== undefined ||
        style.OTransition !== undefined ||
        style.MsTransition !== undefined ||
        style.transition !== undefined
    )
    {
        // Support CSS3 transititon
    }
Angolao
  • 986
  • 1
  • 15
  • 27
  • 3
    checking for undefined is better with: `typeof (style.webkitTransition) !== "undefined"` – naor Sep 04 '13 at 08:01
  • Its only better when not in strict mode because `undefined` could be re-assigned by someone lazy/mischievous, `style.webkitTransition !== void(0)` is better (faster) for non-strict mode use... However we should all be using "use strict" in our code. – bm_i Sep 04 '15 at 12:50
0

Also you can use the following approach (kind of one line function):

var features;
(function(s, features) {
    features.transitions = 'transition' in s || 'webkitTransition' in s || 'MozTransition' in s || 'msTransition' in s || 'OTransition' in s;
})(document.createElement('div').style, features || (features = {}));

console.log(features.transitions);