Testing for CSS 3D Transforms Support
Support for 3D CSS Transforms has made it into most browsers in an experimental form. Opera's support, however, is still busy baking.
Unfortunately, 2D and 3D transforms share at least one property in
common: transform
(though prefixes are still required for now).
Testing for it won't exactly tell you whether the browser supports 3D
transforms. 3D support is possible to detect, however. I'll describe one
approach in this post.
If a browser supports transforms, the value of
getComputedStyle(el).getPropertyValue('transform')
will be a matrix.
Otherwise, it will be undefined
.
A 2D transform, or its equivalent*, will return a matrix such as
matrix(1, 0, 0, 1, 0, 0)
. On the other hand, a successful 3D transform
will result in a 3D matrix such as
matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
. If a 3D
transform can't be calculated — say, if the browser doesn't support
them, or the values in the matrix are somehow invalid — the value of
getComputedStyle(el).getPropertyValue('transform')
will be none
.
Now, here's one way we can test for 3D transforms support using this knowledge. For clarity and readability's sake, the example below does not use prefixed properties. please don't copy-and-paste this example. Use the Gist instead.
function has3d(){
var el, has3d;
/* Create a new element */
el = document.createElement('p');
/* Apply a transform */
el.style['transform'] = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)';
/*
Add it to the body to get the computed style (for Opera mostly).
Since it's empty, it shouldn't interfere with layout in modern browsers.
*/
document.body.insertBefore(el, document.body.lastChild);
/* Get the computed value */
has3d = window.getComputedStyle(el).getPropertyValue('transform');
/*
If it's not undefined, tell us whether it is 'none'.
Otherwise, return false.
*/
if( has3d !== undefined ){
return has3d !== 'none';
} else {
return false;
}
}
In a production environment, you'll also need to determine which prefixed property we need to use. I published a Gist that includes such code. I also published a quick-and-dirty example of how it works.
*matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
and
matrix(1, 0, 0, 1, 0, 0)
are equivalent. They are both identity
matrices, which means applying them has the same effect as not applying
a transform. See Understanding the CSS Transforms
Matrix
for more.