Dealing with CSS Vendor Prefixes

The IE team recently posted what they're calling a best practice for dealing with vendor prefixes in modern browsers.

After reading it, I thought I would post the solution used in Gimme, which I implemented as soon as I had to start dealing with vendor prefixes.

I've yanked it out and posted it here as a stand-alone function called getStyleName(). You can use it when you want to set some element's style in Javascript. You always pass it the "standard" name (without any prefix) and it will do (or try to do) the right thing in the right browser.

For instance:

var someElem = document.getElementById('foo');

// MozTransform in Mozilla, webkitTransform in webkit, etc...
someElem.style[getStyleName('transform')] = 'rotate(90deg)';

Here is the getStyleName function in full:

var getStyleName = function()
{
   var styleHash = {};
   var vendorPrefixes = [ 'O', 'ms', 'Moz', 'Webkit' ];

   return function(styleName, elem)
   {
      elem = elem || document.createElement('div');
      var s = styleHash[styleName];
      if (!s)
      {        
         // hope the browser supports the "official" (non-vendor-prefixed) style first
         var camStyle = camelize(styleName);
         
         // if not, then ask getVendorStyle for help -- it will try the various vendor prefixes seeking
         // one that works (if it doesn't find one, it will return an empty string, in which case we
         // revert back to originally passed in styleName)
         if (elem.style[camStyle] === undefined)
         {
            camStyle = getVendorStyle(camStyle, elem) || styleName;
         }

         // finally, store the camelized & vendor-specific (if applicable) value in the styleHash where key = styleName that was passed in
         s = styleHash[styleName] = camStyle;
      }
      return s;
   }

   function getVendorStyle(style, elem)
   {
      var s = camelize('-' + style);
      var i = vendorPrefixes.length;
      while (i--)
      {
         style = vendorPrefixes[i] + s;
         if (elem.style[style] !== undefined)
         {
            return style;
         }
      }
      return '';
   };

   function camelize(s)
   {
      return s.replace(/-(\w)/g, function(m, c)
      {
         return c.toUpperCase();
      });
   }
}();

Got something to say?

Please note: Constructive criticism is welcome. Rude or vulgar comments however, are not and will be removed during moderation.