Hace poco escribí un artículo en el que explicaba cómo estos prefijos son también una forma que tienen los fabricantes de navegadores para salvar el tiempo que media entre el momento en que disponen de sus implementaciones y las fechas en que se publican especificaciones definitivas. A la hora de desarrollar demos de las nuevas funcionalidades en nuestro sitio web IE Test Drive y en algunas presentaciones para eventos, muchos de nosotros en el equipo de IE hemos tenido que trabajar de forma muy habitual con prefijos de fabricante.
En este artículo explicaré un modelo de trabajo que he aplicado a algunas demos recientes y que hace mucho más fáciles las cosas y se ha convertido en una buena práctica. Me gustaría que lo probaseis y me dierais vuestras opiniones sobre esta cuestión o cualquier otro asunto que consideréis que puede tener la categoría de una "buena práctica".
var elm = document.getElementById("myElement");
elm.style.msTransitionProperty = "all";
elm.style.msTransitionDuration = "3s";
elm.style.msTransitionDelay = "0s";
elm.style.webkitTransitionProperty = "all";
elm.style.webkitTransitionDuration = "3s";
elm.style.webkitTransitionDelay = "0s";
elm.style.MozTransitionProperty = "all";
elm.style.MozTransitionDuration = "3s";
elm.style.MozTransitionDelay = "0s";
elm.style.OTransitionProperty = "all";
elm.style.OTransitionDuration = "3s";
elm.style.OTransitionDelay = "0s";
Aunque funciona, es farragoso, feo y muy propenso a errores.
function FirstSupportedPropertyName(prefixedPropertyNames) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedPropertyNames.length; ++i) {
if (typeof tempDiv.style[prefixedPropertyNames[i]] != 'undefined')
return prefixedPropertyNames[i];
}
return null;
}
Cuando inicializamos una variable para cada propiedad con prefijo de fabricante que utilizamos, le pasamos un array con todas las propiedades posibles en el orden que prefiramos.
var transformName = FirstSupportedPropertyName(["transform", "msTransform", "MozTransform", "WebkitTransform", "OTransform"]);
var backfaceVisibilityName = FirstSupportedPropertyName(["backfaceVisibility", "msBackfaceVisibility", "MozBackfaceVisibility", "WebkitBackfaceVisibility", "OBackfaceVisibility"]);
var transitionName = FirstSupportedPropertyName(["transition", "msTransition", "MozTransition", "WebkitTransition", "OTransition"]);
var animationName = FirstSupportedPropertyName(["animation", "msAnimation", "MozAnimation", "WebkitAnimation", "OAnimation"]);
var gridName = FirstSupportedPropertyName(["gridRow", "msGridRow", "MozGridRow", "WebkitGridRow", "OGridRow"]);
var regionsName = FirstSupportedPropertyName(["flowFrom", "msFlowFrom", "MozFlowFrom", "WebkitFlowFrom", "OFlowFrom"]);
var hyphensName = FirstSupportedPropertyName(["hyphens", "msHyphens", "MozHyphens", "WebkitHyphens", "OHyphens"]);
var columnName = FirstSupportedPropertyName(["columnCount", "msColumnCount", "MozColumnCount", "WebkitColumnCount", "OColumnCount"]);
Después, el código de tu sitio web que utilice estas propiedades quedaría más o menos así:
var elm = document.getElementById("myElement");
if (transitionName) {
elm.style[transitionName + "Property"] = "all";
elm.style[transitionName + "Duration"] = "3s";
elm.style[transitionName + "Delay"] = "0s";
}
else {
// fallback for browsers without CSS3 transitions
}
Como ves, de una forma sencilla tenemos una detección de funcionalidad al devolver null en FirstSupportedPropertyName.
Este modelo funciona también cuando las propiedades CSS tienen prefijos de fabricante. Podemos aplicar un patrón ligeramente distinto en el caso en el que sea el valor de CSS (por ejemplo linear-gradient) el que lleva el prefijo:
function FirstSupportedFunctionName(property, prefixedFunctionNames, argString) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedFunctionNames.length; ++i) {
tempDiv.style[property] = prefixedFunctionNames[i] + argString;
if (tempDiv.style[property] != "")
return prefixedFunctionNames[i];
}
return null;
}
var linearGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-linear-gradient", "-moz-linear-gradient", "-webkit-linear-gradient", "-o-linear-gradient"], "(top, black, white)");
var radialGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-radial-gradient", "-moz-radial-gradient", "-webkit-radial-gradient", "-o-radial-gradient"], "(50% 50%, circle cover, black, white)");
Con independencia de cuál de ellas elijas, lo que siempre hay que hacer es probarlo. Cuando utilizas propiedades con prefijo de fabricante en una fase inicial, a menudo son funcionalidades inestables que pueden cambiar incluso después de que el navegador empiece a ofrecer soporte para una propiedad definitiva, de modo que es imprescindible y crítico el probar cada actualización de cada navegador para asegurarnos de que todo funciona como estaba previsto.