Browser-Specific Prefixes with a CSS Transition on Transform

Browser-specific prefixes with a CSS transition on transform

UPDATE NOTICE Unfortunately it turns out Safari at the time of this post does not follow the 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: unrecognizedProperty 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 "unrecognizedProperty" is not recognized.

transition: width 2s;
transition: unrecognizedProperty 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;

CSS 3 - transition prefixes - which ones to use?

http://caniuse.com/#search=transition says that you need -webkit- and plain property for modern browsers.

-webkit-transition: all .5s ease;
transition: all .5s ease;

But it will be no problem if you add all of them, just be sure that property without prefix is the last one.

Edit: as said in comment below, if you click on "All versions" you can see when each browser dropped prefix. For now it is better to use -moz- and -o- also.

Edit May 2015: I highly recommend use Autoprefixer as step on your build process (like Gulp/Grunt task) or as plugin to your code editor. It provides automatic prefixing on caniuse.com browser support stats.

Edit 2019: No need in prefixes and less and less need in Autoprefixer, future is nice :)

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

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.

IE10/11 uses transition:-webkit-transform?

I just did some more research on this, and it's looking more like a Chrome bug than something about IE.

Here's what the spec says about unrecognized and non-animatable properties in transition-property:

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’. In other words, unrecognized or non-animatable properties must be kept in the list to preserve the matching of indices.

The spec does not seem to account for cases when none of the properties specified are supported or animatable, not even in the sections following the transition propdefs. It looks like IE is treating the declaration as valid, albeit with no supported properties to be transitioned, thereby overriding the previous declaration, and effectively making the declaration equivalent to transition-property: none (i.e. the result is similar, but as you have observed the value does not actually compute to none).

Firefox appears to behave the same way that IE does, treating the declaration as equivalent to transition-property: none.

Furthermore, if you put the unprefixed and prefixed transform property names in the same declaration, IE and Firefox will animate the transform just fine (order doesn't matter):

transition: -webkit-transform 1s, transform 1s;

However, if you place any other properties that you would expect to work together with the unrecognized property that causes Chrome to drop the declaration... it still drops that declaration. Yes, where IE and Firefox apply the transition correctly in the above declaration, Chrome ignores it entirely.

It seems to only have this problem with unknown property names, though. For example, if you specify a property that is supported but not animatable, such as background-image:

transition: -webkit-transform 1s, background-image 1s;

Chrome is able to animate the transform just fine.

With all that said, I'm still not entirely sure if the spec is ambiguous, or the behavior shown in IE and Firefox is in fact correct. Sounds like it could use a bit of clarification either way, so I've gone ahead and emailed the CSSWG about this.

Are browser prefixes required for all version of animation keyframes

From my answer to this similar question:

  • WebKit-based browsers (including Opera 15 and later) still require the -webkit- prefix for animations today, and transforms are only unprefixed in recent versions of Chrome. You will need the prefix for both features.

(Transforms were unprefixed in Chrome 36; animations were not unprefixed until Chrome 43. Both features were unprefixed simultaneously in Safari 9 so you never need to worry about prefixed/unprefixed overlap in Safari.)

In a nutshell, while your two samples don't provide exactly the same functionality, there is no point including any unprefixed properties in @-webkit-keyframes as most WebKit browsers that depend on the prefixed at-rule are never going to need the unprefixed properties. Specifically, from our chat discussion:

You can lose the unprefixed [animation-timing-function] declaration. @keyframes is in the same family as the animation-* properties and no browser in existence supports one unprefixed without the other

As for transforms, only a very fringe few browsers simultaneously support unprefixed transforms and require prefixes on animations. These browsers do still support prefixed transforms, so similarly you can lose unprefixed transforms in @-webkit-keyframes

Note the difference between "support" and "require"

So, code sample two is all you need. It's over 40% smaller than code sample one, with no loss of functionality. 40% is a big deal. The only change I'd make is move the @-webkit-keyframes rule up:

@-webkit-keyframes coolEffect {
-webkit-transform: some value;
-webkit-animation-timing-function: some value;
}
@keyframes coolEffect {
transform: some value;
animation-timing-function: some value;
}

Readers may also be interested in my comments on Autoprefixer:

I assume Autoprefixer sees that Chrome 36-42 supports unprefixed transforms but requires prefixed animations, so it puts transform in @-webkit-keyframes. I don't think that's a good approach. It needlessly doubles the transform declarations. All those versions of Chrome still understand -webkit-transform, so might as well stick to just that

Autoprefixer is good for those who just don't want to have to worry about prefixes or doing all the research needed to really optimize their stylesheets

If you want to optimize your stylesheet, you'll need to do quite a bit of research to find out where prefixes are needed and where they aren't, where unprefixed declarations are needed and where you can leave them out, etc. Prefixes are a pain either way ;)

How do you determine whether a CSS property requires browser specific prefixes?

This is an excellent summary of browser support for pretty much every CSS property.

However, I tend to use the browser-specific prefixes, as well as the non-specific rule, no matter what - it's not exactly much extra work and it will mean those few people stuck on outdated browsers still see the page as you intended.

Multiple CSS transitions

You're mixing browser specific prefixes with no browser specific prefixes, also to specify multiple animations you just need to separate them with a commma. In you example the fall animation is overwritten by the swing animation.

Something like this:

.box{
width:250px; height:50px;
background:blue;
border: 1px solid black;
position:fixed;
left: 50%;
margin-left:-125px;
top:150px;

animation: fall 1.5s ease-in, swing 4s ease-in-out;
-webkit-animation: fall 1.5s ease-in, swing 4s ease-in-out;
-moz-animation: fall 1.5s ease-in, swing 4s ease-in-out;
}

@-moz-keyframes fall{
0% {top: -50px;}
100% {top: 150px;}
}
@-webkit-keyframes fall{
0% {top: -50px;}
100% {top: 150px;}
}
@-moz-keyframes swing{
-moz-transform-origin: center top;
0%{-moz-transform:rotate(-3deg)}
50%{-moz-transform:rotate(-2deg)}
100%{-moz-transform:rotate(-3deg)}
}
@-webkit-keyframes swing{
-webkit-transform-origin:center top;
0%{-webkit-transform:rotate(-3deg)}
50%{-webkit-transform:rotate(-2deg)}
100%{-webkit-transform:rotate(-3deg)}
}

Check this fiddle

Setting CSS 3 Transition and Transform in Javascript works in Chrome But not in IE 10, FF properly?

One thing which you should definitely keep in mind is the order in which you use vendor-specific prefixes. There is a difference between saying:

gallery.css("transition-duration", duration + "ms");
gallery.css("-webkit-transition-duration", duration + "ms");
gallery.css("-moz-transition-duration", duration + "ms");
gallery.css("-ms-transition-duration", duration + "ms");
gallery.css("-o-transition-duration", duration + "ms");

and...

gallery.css("-webkit-transition-duration", duration + "ms");
gallery.css("-moz-transition-duration", duration + "ms");
gallery.css("-ms-transition-duration", duration + "ms");
gallery.css("-o-transition-duration", duration + "ms");
gallery.css("transition-duration", duration + "ms");

As mentioned in this SO question's accepted answer:

Whichever is last out of -webkit-border-radius and border-radius will be the one that's used.

-webkit-border-radius is the "experimental" property - the implementation may contain deviations from the specification. The implementation for border-radius will match what's in the specification.

It's preferable to have the "W3C implementation" used when it's available, to ensure consistency between all the browsers that support it.

With that said - be aware that your current implementation is likely to override the "W3C implemented" version with the vendor-specific experimental property.

On to a more specific answer to your question:

This table may give you a bit more insight into which versions of which browsers claim support for 3d transformation CSS, from version to version.

  1. Internet Explorer

    According to this blog article, IE 10 supports full CSS3 3D Transformations (note that IE9 only supported 2-D transforms, and previous versions didn't even support that).

  2. Firefox

    As of the fixing of Bug 505115, Firefox claims support of CSS3 3D-Transforms. According to this example page, as well - Mozilla does support the transformations (and even demonstrates doing so if you load that page in Firefox).

    Unfortunately, more complicated tests in Firefox fail. See this link for an example of something that works elegantly in Chrome, but not in FF. Partial support, to be sure, but without the animation of the WebKit implementation.

    Note: I am using Firefox 20.0.1 in order to test.

  3. Opera

    Opera provides this article to describe their support of transforms.

End Result:

Support is coming to the major browsers, but slowly. Future versions claim more full support, but each vendor seems to have a different definition of what "full" means. So - as usual in the web-world... coder-beware... test in multiple environments and see what actually works before trusting the browsers to function properly in accordance with specs.

Multiple, simultaneous CSS3 transform transitions at varied speeds

Don't think you can do it the way you are attempting. Possible solutions would be a wrapper object

eg

Multiple transitions

sample fiddle here

sample code (HTML)

<div class="wrap">
<div class="inner"></div>
</div>

and CSS

.wrap {
width: 100px;
height: 100px;
transition: transform 1s linear;
}
.inner {
width: 100%;
height: 100%;
background: red;
transition: transform 2s linear;
}
.wrap:hover {
transform: scale(1.5);
}
.wrap:hover .inner {
transform: rotate(45deg);
}

or use animations and keyframes as mentioned in answer by @slynagh

Just out of note, the transform property doesn't seem to work when used in transition on chrome (i.m on V33), but it works fine on IE11, thats all I have tested this on

Avoid vendor specific prefixes in CSS

A javascript based solution is http://leaverou.github.io/prefixfree/

-prefix-free lets you use only unprefixed CSS properties everywhere. It works behind the scenes, adding the current browser’s prefix to any
CSS code, only when it’s needed.



Related Topics



Leave a reply



Submit