9/19/13
The latest CSS specification, called CSS3, is chock full of dazzling visual effects such as transformations, animation, and box shadows that website owners love to have. After all, the more attractive the site, the more visitors it will draw (everything else being equal of course). Even before the spec was made official, browser vendors raced to bring CSS3 properties to their users. In offering an interim solution while the details of the official properties were fully hashed out, each defined their own prefixes. Now, we Web developers have to deal with them. Today’s article will offer a starting point for working with CSS3 vendor prefixes without going stir crazy in the process.
Prefix Roundup
All major browsers added their own vendor prefix to every CSS3 property that they wished to support. The reason was sound enough; it was to avoid naming collisions, since all vendors were pretty much implementing the new properties at the same time, blind as to what others were producing. This list of prefixes was the end result:
Vendor | CSS3 Prefix | CSS3 Examples | JavaScript Prefix | JS Examples |
---|---|---|---|---|
Microsoft | -ms- | -ms-filter, -ms-behavior, -ms-zoom | ms | msFilter, msBehavior, msZoom |
Mozilla | -moz- | -moz-box-shadow, -moz-border-radius, -moz-transform | moz | mozBoxShadow, mozBorderRadius, mozTransform |
Webkit (Safari, Chome etc) | -webkit- | -webkit-box-shadow, -webkit-border-radius, -webkit-transform | webkit | webkitBoxShadow, webkitBorderRadius, webkitTransform |
Opera | -o- | -o-transition, -o-text-overflow, -o-transform | o | oTransition, oTextOverflow, oTransform |
Konqueror | -khtml- | -khtml-user-select, -khtml-border-radius | khtml | khtmlUserSelect, khtmlBorderRadius |
Naming Conventions
Most of the time, you can simply take the standard CSS property and add the prefix to it for each browser. For example, here is a CSS3 rule for a transition:
.mywidget { -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); -webkit-transform: rotate(45deg); transform: rotate(45deg); }
Usually, the prefixed properties are listed first, as we did above.
Unfortunately, there are exceptions where the vendor-prefixed version of a property is not based on the standard property. Case in point, some versions of Chrome and Safari called their linear-gradient properties “-webkit-gradient”. To make matters worse, the values can also differ across vendors! Take the gradient property; the webkit implementation is a somewhat complex but versatile solution. Mozilla’s, on the other hand, is closer to the draft W3C specification:
#top-to-bottom-gradient { /* fallback */ background-color: #1a82f7; background: url(images/linear_bg_2.png); background-repeat: repeat-x; /* Safari 4-5, Chrome 1-9 */ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1a82f7), to(#2F2727)); /* Safari 5.1, Chrome 10+ */ background: -webkit-linear-gradient(top, #2F2727, #1a82f7); /* Firefox 3.6+ */ background: -moz-linear-gradient(top, #2F2727, #1a82f7); /* IE 10 */ background: -ms-linear-gradient(top, #2F2727, #1a82f7); /* Opera 11.10+ */ background: -o-linear-gradient(top, #2F2727, #1a82f7); }
A JavaScript Solution
As you can well imagine, once you get a few CSS3 rules in your stylesheets, vendor prefixes will cause your code to quickly become very large and time consuming to write. Therefore, using JavaScript to find the supported vendor extension for a property makes a lot of sense. The idea is to loop through each vendor prefix to find the right property or return an empty string if none are found:
function getSupportedProperty(css3Prop, oElm, vendorPrefixes){ //reference root element of document by default oElm = oElm || document.documentElement; vendorPrefixes = vendorPrefixes || ['Moz', 'ms', 'Webkit', 'O', 'Khtml']; vendorPrefixes.unshift(''); var i = 1, propName = css3Prop; do { if (propName in oElm.style) { return propName; } propName = vendorPrefixes[i] + css3Prop.charAt(0).toUpperCase() + css3Prop.slice(1); } while(i++<vendorPrefixes.length); return ''; } var myDiv = document.getElementById("container"); var boxShadowProp = getSupportedProperty('boxShadow', myDiv); //get appropriate CSS3 box-shadow property if (boxShadowProp) { myDiv.style[boxShadowProp]="5px 5px 1px #818181"; } //set CSS shadow for "myDiv"
A few notable points on using the above code:
- Internet Explorer has to run in standards mode to support the box-shadow property. You can force IE to run in standards mode by including the following tag in the HEAD section:
<meta http-equiv="X-UA-Compatible" content="IE=edge">
- Capitalization of JavaScript CSS# properties varies wildly:
- “webkit” and “Webkit” both work for WebKit browsers.
- “ms” works in IE, but not “Ms”;
- “Moz” and “O” work for Firefox and Opera, but not “moz” or “o” (Opera also recognizes “Webkit”, but not “webkit”
Conclusion
Now that all of the major browser vendors have released their versions of the new CSS3 properties, time will tell how many will rename them to the unprefixed standards. In the mean time, you don’t have to bend over backwards trying to remember which browser supports which properties. There are several free tools that help make you stylesheets work on all major browsers. In an upcoming article, I’ll name a few.