What is the right combination of prefixes for CSS transitions and transforms?

11,590

Solution 1

As I mentioned in a very similar question...

This is one of those cases where vendor prefixes for standardized features become extremely problematic, because you need to account for all the different prefixed and/or unprefixed implementations of different features in different versions of different browsers.

What a mouthful. And then you have to combine various permutations of these. What a handful.

In short, you need to figure out which versions of each browser requires a prefix for each of the individual properties, and unless you don't mind the bloat, you will need to apply the prefixes differently for individual browsers.

The linked question refers to animations rather than transitions which results in significantly different notations, but both features went through similar unprefixing processes AFAIK. That being said, here are the compatibility tables from caniuse.com for 2D transforms and transitions.

In other words, just because one feature is prefixed in one version of one browser doesn't mean the other feature is necessarily also prefixed in the same version of the same browser. For example, Chrome unprefixed transitions at least ten major versions (26) before it unprefixed transforms (36), and Safari still requires prefixes for transforms. As a result, you're definitely going to have to have this declaration:

transition: -webkit-transform .3s ease-in-out;

And if you absolutely need to, you will have to cover even older versions with the following:

-webkit-transition: -webkit-transform .3s ease-in-out;

Other browsers, miraculously, were able to unprefix both transitions and transforms (as well as animations) simultaneously, which makes things much easier:

  • -ms-transition is only used by pre-release versions of IE10, which have long since expired. No other version of IE uses prefixed transitions, so you should remove that particular transition prefix.

    -ms-transform with the prefix is only used by IE9; IE10 and later ship with unprefixed transforms. But for the purposes of graceful degradation you may want to keep your -ms-transform: rotateX(-30deg); declaration — just keep in mind that it cannot be transitioned as IE9 does not support CSS transitions or animations.

  • -moz-transition and -moz-transform were used by Firefox up to and including 15, then unprefixed in 16.

  • -o-transition and -o-transform were used by Opera up to and including 12.00, then unprefixed in 12.10, then re-prefixed as -webkit- in later versions in its move to Blink.

In summary, here are all the prefixes that you need, based on the information given by caniuse.com (which I trust to be current and accurate for the most part):

-webkit-transition: -webkit-transform .3s ease-in-out; /* Chrome < 26, Safari < 7 */
   -moz-transition:    -moz-transform .3s ease-in-out; /* Firefox < 16 */
     -o-transition:      -o-transform .3s ease-in-out; /* Opera < 12.10 */
        transition: -webkit-transform .3s ease-in-out; /* Chrome 26-35, Safari, Opera 15-23 */
        transition:         transform .3s ease-in-out; /* IE10+, Firefox 16+, Chrome 36+, Opera 12.10 */

 -webkit-transform: rotateX(-30deg);
    -moz-transform: rotateX(-30deg);
     -ms-transform: rotateX(-30deg); /* Only for graceful degradation in IE9, cannot be transitioned */
      -o-transform: rotateX(-30deg);
         transform: rotateX(-30deg);

The bare minimum that you will need to support the latest version of each browser as of this writing is:

        transition: -webkit-transform .3s ease-in-out; /* Chrome 26-35, Safari, Opera 15-23 */
        transition:         transform .3s ease-in-out; /* IE10+, Firefox 16+, Chrome 36+, Opera 12.10 */

 -webkit-transform: rotateX(-30deg);
         transform: rotateX(-30deg);

As mentioned in the comments, you can use a tool like Autoprefixer to automate this for you based on the level of browser support you require. However, for those who prefer to write their CSS manually, or for those who are just wondering exactly which prefixes are needed by which browsers, this is it.

On a final note: notice the two unprefixed transition declarations in the above examples? Now, you'd think it'd be easy enough to just combine them into a single declaration like this:

transition: -webkit-transform .3s ease-in-out, transform .3s ease-in-out;

But, unfortunately, Chrome will erroneously completely ignore this declaration, while other browsers will apply it just fine.

Solution 2

As of right now, if you’re supporting the top-two newest versions of each browser, here are the prefixes you need:

-webkit-transition: -webkit-transform .3s ease-in-out;
transition: transform .3s ease-in-out;

-webkit-transform: rotateX(-30deg);
transform: rotateX(-30deg);

So to answer your question, yes, the prefix-transition should target the prefix-transform. Pretty sure that is always true for transforms (although not necessarily for other properties. Flexbox and Gradients can be complex prefix-wise, I suggest you use Autoprefixer to keep those rules straight).

Also, my favorite way to figure out this kind of question is to go to a new Pen in CodePen, turn on Autoprefixer in the CSS settings, paste my code in, and compile it. Autoprefixer automatically adds prefixes for the top-two of each browser. Kinda magical!

Share:
11,590
Jabba Da Hoot
Author by

Jabba Da Hoot

Front-ender @ Software Company

Updated on June 10, 2022

Comments

  • Jabba Da Hoot
    Jabba Da Hoot almost 2 years

    What would be the right way to prefix this CSS in order to cover the widest range of browsers and versions?

    Version 1:

    -webkit-transition: -webkit-transform .3s ease-in-out;
       -moz-transition:    -moz-transform .3s ease-in-out;
        -ms-transition:     -ms-transform .3s ease-in-out;
         -o-transition:      -o-transform .3s ease-in-out;
            transition:         transform .3s ease-in-out;
    
     -webkit-transform: rotateX(-30deg);
        -moz-transform: rotateX(-30deg);
         -ms-transform: rotateX(-30deg);
          -o-transform: rotateX(-30deg);
             transform: rotateX(-30deg);
    

    Or version 2:

    -webkit-transition: transform .3s ease-in-out;
       -moz-transition: transform .3s ease-in-out;
        -ms-transition: transform .3s ease-in-out;
         -o-transition: transform .3s ease-in-out;
            transition  transform .3s ease-in-out;
    
     -webkit-transform: rotateX(-30deg);
        -moz-transform: rotateX(-30deg);
         -ms-transform: rotateX(-30deg);
          -o-transform: rotateX(-30deg);
             transform: rotateX(-30deg);
    

    It appears to me that when using vendor prefixes on a transition property, I should also target the vendor prefixed attribute I want to transition.

    I can't really find any closure to this.