ベンダー プレフィックスを使用したプログラミングのベスト プラクティス
本記事は、マイクロソフト本社の IE チームのブログ から記事を抜粋し、翻訳したものです。
【元記事】A Best Practice for Programming with Vendor Prefixes2011/10/29 8:01 AM
ベンダー プレフィックスを使用することにより、Web 開発者は勧告候補の段階になる前の新しい標準仕様を試すことができます。ブラウザー ベンダーではこのプレフィックスを、実装と仕様のタイミングの問題に対処するためのメカニズムとしても使用しています。これについては、こちらの記事を参照してください。IE Test Drive サイト用に新機能のデモを作成するときや、さまざまなプレゼンテーションの際に、IE チームのメンバーの多くはベンダー プレフィックスを非常によく利用します。
今回のブログでは、最近のデモで使用したパターンについて説明します。このパターンは作業が非常に簡素化され、ベスト プラクティスとなっています。このアプローチについて、あるいは皆さんが考える他のベスト プラクティスについて、ぜひご意見をお聞かせください。
間違いを生みやすいコード
スクリプトを使用してベンダー プレフィックスの付いた CSS プロパティにアクセスする場合、次のようなコードになりがちです。
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";
機能はしますが、無駄が多く、美しくもなく、間違いを生みやすいコードです。
ベンダー プレフィックスの付いたプロパティを 1 つの名前に集約する
より優れたパターンとしては、プロパティ名のリストをループするメソッドを定義して、サポートされている最初のプロパティを返すようにします。ブラウザーがどのプロパティもサポートしていない場合は、null を返すようにします。
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;
}
続いて、使用するベンダー プレフィックスの付いたプロパティごとに、変数を初期化します。このとき、可能性のあるプロパティを、使用する順番で並べた配列を渡します。
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"]);
すると、これらのプロパティを使用するサイトのコードは、次のようになります
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
}
FirstSupportedPropertyName で null を返すことで、簡単な機能の検出が行われることに注目してください。
このパターンは、ベンダー プレフィックスの付いた CSS プロパティが複数ある場合も機能します。CSS の "値" (linear-gradient など) にベンダー プレフィックスがある場合は、次のような若干異なるパターンを使用することができます。
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)");
ベンダー プレフィックスの付いたプロパティを使用するサイトのテスト
よくある質問の 1 つは、一部のブラウザーがそのプロパティをまだサポートしていない場合や、プレフィックスのない標準ベースのプロパティをどのブラウザーもサポートしていない場合に、どのようなプロパティ名を使用するのかということです。解決方法は 2 つあり、それぞれにメリットがあります。
- 公開されているブラウザーでまだ機能しなくても、想定されるすべての名前を常に含めるようにする。 この方法の利点は、ブラウザーが新たにベンダー プレフィックスをサポートするようになったとき、またはプレフィックスのないプロパティをサポートするようになったときに、サイトは何も変更しなくても "そのまま" 機能するということです。この方法のリスクは、テストしていない動作がサイトで自動的に実行されてしまう可能性があることです。ベンダー プレフィックスはその動作が確定していないことを示し、プレフィックスの付いたプロパティと付いていないプロパティがすべて同じ動作をするとは限りません。そのため、ブラウザーが新しいサポートを追加すると、サイトは "そのまま" 想定外の動作をする可能性があります。
- テストできるプロパティ名だけを含める。 この方法の利点は、ブラウザーが新しいプロパティをサポートするようになっても、サイトは最初に作成したときと同じように動作することです。この方法のリスクは、必要以上に機能を制限してしまうことです。サンプル サイトやデモ サイトの場合、ブラウザーにまったく機能が搭載されていないと思われてしまう可能性があります。
自分のサイトに合った正しい方法を決定することが必要です。私たちのデモでは、新しい Web プラットフォームの機能を、その機能をサポートしているすべてのブラウザーでお見せしたいと思っています。こうしたデモの小さなエラーはユーザーにとって大きな問題とはならないので、通常は 1 番目の方法を選択しています。一方、動作を変更するとビジネスに支障をきたすような本番稼働中のサイトでは、よりリスクの低い方法を採用する方がよいと考えられます。
どちらの方法を選ぶとしても、テストの重要性は変わりません。ベンダー プレフィックスの付いたプロパティを使用する場合は、まだ日が浅く概して不安定な機能を利用することになります。ブラウザーがそのプロパティのサポートを最初に導入した後から、機能が変更されることもあります。そのため、ブラウザーが更新されるたびに、サイトが想定どおり機能するかどうかをテストすることが非常に重要です。
—John Hrvatin (リード プログラム マネージャー、Internet Explorer)