Browser-specific prefixes with a CSS transition on transform

Problem

According to caniuse.com, for those browsers that support both CSS transition and CSS transform, combinatorically there are at least three different types:

  1. Those that require the -webkit- prefix on both transition and transform (e.g. Safari 6, Android browser < 4.4).
  2. Those that only require the -webkit- prefix on transform (e.g. Chrome 3x).
  3. Those that require prefixes on neither (e.g. FF and IE10/11).

How can I safely write my transition styles so that they are parsed correctly in each type? I see two options:

-webkit-transition: -webkit-transform 300ms;
        transition: -webkit-transform 300ms, transform 300ms;

or

-webkit-transition: -webkit-transform 300ms;
        transition: -webkit-transform 300ms;
        transition: transform 300ms;

Now because of type 2 and type 3 browsers I need to have a prefix-less transition for both -webkit-transform and transform. The problem with the first option is I worry that type 2 and type 3 browsers will not be able to parse the second line, since they will always contain an unrecognized property. The question is, how do browsers handle invalid properties inside a transition--ignore the entire transition style or just skip the invalid property?

I thought this may be mitigated by separating it into two properties so that if one is not parseable it will just be ignored. Apart from this second option being a bit verbose, I still wonder if, in the case of type 2 browsers, the third transition will be unparseable and "reset" the transition back to null.

Any ideas how these perform, generally? Also, which of these are future-compliant for when Chrome et al. switch from -webkit-transform to the prefix-less transform?

Problem courtesy of: 0x24a537r9

Solution

UPDATE NOTICE Unfortunately it turns out Safari at the time of this post does not follow the explicit standard outlined in the W3 Specification below, and including both a webkit prefixed property and a prefix-less property after transition will cause it to break and not be animated at all. I am still exploring this issue for a good general solution but it looks like until Safari fixes this, there may not be one that works everywhere, and for all future properties, without adjusting your CSS rules per browser dynamically with JavaScript.


If you add an unrecognized or invalid property to a list of transition properties, the valid properties in the list will still be added (except on Safari, see notice above).

According to section 2.1 of the w3 Specification for CSS Transitions:

If one of the identifiers listed is not a recognized property name or is not an animatable property, the implementation must still start transitions on the animatable properties in the list using the duration, delay, and timing function at their respective indices in the lists for ‘transition-duration’, ‘transition-delay’, and ‘transition-timing-function’.

W3 Specification for CSS Transitions

If you take the following style, the width property will still be animated despite being preceded by an invalid and unrecognized property.

transition: garbageProperty 2s, width 2s;

If you follow a transition rule with another transition rule (with the same prefixing or lack thereof), the first rule will be overwritten and no longer applied even if the second rule only has invalid properties listed on the right hand side.

If you try the following style the width will not be animated because the first rule will be overwritten by the second rule, which effectively does nothing since "garbageProperty" is not recognized.

transition: width 2s;
transition: garbageProperty 2s;

Based on this I believe your first approach is correct.

-webkit-transition: -webkit-transform 300ms;
        transition: -webkit-transform 300ms, transform 300ms;

The first rule will only be applied if -webkit-transition is recognized, in which case since transform came out after transition it will definitely have to be prefixed and we can omit the unprefixed transform property (although I don't think it would hurt to leave it). The second rule will only be applied if unprefixed transition is recognized, in which case whichever of the right-hand side properties that are recognized by the browser will be applied, even if other properties in the list are not recognized.

Your second approach is flawed since the second rule will always be overwritten by the third rule regardless of if any properties on the right hand side are or are not recognized.

I believe the complete list of browser prefixed properties to guarantee that you apply transition of 2s to transform on all browsers that are capable is the following, but please read the rational below because it only happens to be this neat for this property pair by chance:

-webkit-transition: -webkit-transform 2s;
   -moz-transition:    -moz-transform 2s;
     -o-transition:      -o-transform 2s;
        transition:         transform 2s;

1) Note there is no such thing as -ms-transition, but there is a -ms-transform. That being said transition was not added to IE until 10 where -ms-transform was also outdated by unprefixed transform. Hence for IE the only rule we need is "transition: transform".

2) I will additionally note that any time we have a browser prefix for transition (< Chrome 26, < Firefox 16, < Safari 6.1, < Opera 12.1), then transform was definitely still prefixed as well (< Chrome 36, < Firefox 16, all Safari, < Opera 23), meaning we can leave off the unprefixed version of transform following a prefixed rule.

3) Since Firefox released unprefixed transition at the same time as their unprefixed transform, we do not need the prefixed "-moz-transform" on the right-hand side of the unprefixed "transition".

4) Opera at some point used -webkit- prefix for transform in addition to -o-, however they started using -webkit-transform in version 15, after starting to use prefixless transition in version 12.1, so we do not need to include the -webkit-transform after -o-transition. Also since Opera only used prefixless or -webkit-transform after version 12.1, we do not need to include -o-transform after the prefixless transition.

5) In this case we do not have to include -webkit-transform to the right of prefix-less transition because browsers that only recognize -webkit-tranform will fall back to -webkit-transition and still apply this property.


If you don't mind the length of your CSS though, the following should be a safe generalized solution for ensuring proper browser prefixing of transition and a prefixed right hand property. UPDATE NOTICE As it turns out this approach may not be safe on Safari since they do not follow the W3 standard on ignoring unrecognized properties to the right of transition if there is one that is prefixed and one that is not.

-webkit-transition: -webkit-property,
                            property;
   -moz-transition:    -moz-property,
                            property;
    -ms-transition:     -ms-property,
                            property;
     -o-transition:      -o-property,
                    -webkit-property,
                            property;
        transition: -webkit-property,
                       -moz-property,
                        -ms-property,
                         -o-property,
                            property;
Solution courtesy of: Wade Norris

Discussion

I believe the transition prefix that is unrecognized is simply skipped until a recognized one is found.

I am currently using this for a site and it works for us.

CSS

.viewElement{
   -webkit-transform: translatex(0) translatey(500px);
   -moz-transform: translatex(0) translatey(500px);
   -o-transform: translatex(0) translatey(500px);
   -ms-transform: translatex(0) translatey(500px);
   transform: translatex(0) translatey(500px);
   -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=0)";
   filter: alpha(opacity=0);
   opacity: 0.0;
   -webkit-transition: all .8s ease-out;
   -moz-transition: all .8s ease-out;
   -o-transition: all .8s ease-out;
   -ms-transition: all .8s ease-out;
   transition: all .8s ease-out;
}
Discussion courtesy of: Phlume

This recipe can be found in it's original form on Stack Over Flow.