[JS] ブラウザの実装状況に合わせて、ベンダプレフィックスを使い分けてCSSを設定する
こんにちは、@yoheiMuneです。
今日は、JSからDOM要素にCSSを設定する場合に、ブラウザのサポート状況に合わせて、いい感じにCSSを指定する方法をブログに書きたいと思います。
例えば以、transitionを設定する場合には、以下のような実装となります。
これを用いる場合には、以下のようなことを考慮する必要があります。
「指定するCSSはベンダープレフィックス付きで動作することが確約されている」
外に公開せず自前で使う場合や、transitionやtransformなどを限定で扱う場合には、このような簡単な実装が良いですね。
getComputedStyleは、(上記の使い方ではありませんが)jQueryやzeptoでもCSSの実装確認に使われているようです。
上の実装はwebkit限定で、例えばfirefoxの場合には動作しません。firefoxでは、getComputedStyleで保持するCSS名は、ハイフン記法で保持しているようです。本当に実験的な実装です。
jQueryでgetComputedStyleが利用されている例):
最後までご覧頂きましてありがとうございました。
今日は、JSからDOM要素にCSSを設定する場合に、ブラウザのサポート状況に合わせて、いい感じにCSSを指定する方法をブログに書きたいと思います。
Special Thanks to http://flic.kr/p/kpTpJ6
1、UserAgentを利用して、ベンダープレフィックスを使い分ける
まず1つ目の方法として、UserAgentから利用してベンダープレフィックスを使い分ける方法があります。 実装方法は、事前にUserAgentを調べてベンダープレフィックスを把握しておき、実際にCSSを設定する時にそれを使うという方法です。例えば以、transitionを設定する場合には、以下のような実装となります。
// UAを元に必要なベンダープレフィックスを見分ける。
var venderPrefix = (/webkit/i).test(navigator.appVersion) ? 'webkit' :
(/firefox/i).test(navigator.userAgent) ? 'moz' :
(/trident/i).test(navigator.userAgent) ? 'ms' :
'opera' in window ? 'O' : '';
// ベンダープレフィックスを使って、CSSを設定する。
var elm = document.querySelector('#foo');
elm.style[venderPrefix + 'Transition'] = 'opacity 1s ease-in-out';
数行程度の簡単な実装ですね。これを用いる場合には、以下のようなことを考慮する必要があります。
「指定するCSSはベンダープレフィックス付きで動作することが確約されている」
外に公開せず自前で使う場合や、transitionやtransformなどを限定で扱う場合には、このような簡単な実装が良いですね。
定義されているCSSから調べる
次に、定義済みのCSSを調べて、それに合わせてCSS名を判定する方法です。 定義済みのCSSは、以下のように取得する事ができます。(IE8は対象外、Android2系/3系は一部サポートです。詳細はこちら)
// 実装されているCSSを一覧で表示する
var dec = getComputedStyle(document.head, '');
for (p in dec) {
if (dec.hasOwnProperty(p)) {
console.log(p + ' : ' + dec[p]);
}
}
// 実行例(抜粋)
// webkitAnimation : none 0s ease 0s 1 normal none running VM142:6
// webkitAnimationDelay : 0s VM142:6
// webkitAnimationDirection : normal VM142:6
// webkitAnimationDuration : 0s VM142:6
// webkitAnimationFillMode : none VM142:6
// webkitAnimationIterationCount : 1 VM142:6
// webkitAnimationName : none
この情報を利用して、与えられたCSS名に対して、利用可能なCSS名を返す関数を定義することができます。
/*
* 注意:すごく簡易的な実装です。Webkitのみです。
*/
var dec = getComputedStyle(document.head, '');
var getCssName = function (cssName) {
// 与えられたCSS名からハイフンを取り除く
cssName = cssName.replace(/-/g, '');
// 定義済みのCSS名を探す
var reg1 = new RegExp('^' + cssName + '$', 'i');
var reg2 = new RegExp('^(webkit|moz|ms)' + cssName + '$', 'i');
var nameWithPrefix;
for (prop in dec) {
if (dec.hasOwnProperty(prop)) {
if (reg1.test(prop)) {
// ずばりそのものを発見!
return prop;
} else if (reg2.test(prop)) {
// ベンダープレフィックス付きを発見!
return prop;
}
}
}
// 残念、見つからず。
return null;
}
例えばChrome(v.33)の場合、以下のように動作します。
getCssName('transition'); // => transition
getCssName('text-stroke-color'); // => webkitTextStrokeColor
ベンダープレフィックスが必要なCSSプロパティには、ベンダープレフィックス付きの名前が返却されます。getComputedStyleは、(上記の使い方ではありませんが)jQueryやzeptoでもCSSの実装確認に使われているようです。
上の実装はwebkit限定で、例えばfirefoxの場合には動作しません。firefoxでは、getComputedStyleで保持するCSS名は、ハイフン記法で保持しているようです。本当に実験的な実装です。
jQueryでgetComputedStyleが利用されている例):
/*
jquery / src / css / var / getStyles.js
http://git.io/8aByoA
*/
define(function() {
return function( elem ) {
return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
};
});
/*
jquery / src / css / support.js
http://git.io/6z7FZA
*/
function computePixelPositionAndBoxSizingReliable() {
div.style.cssText =
// Support: Firefox<29, Android 2.3
// Vendor-prefix box-sizing
"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
"border:1px;padding:1px;width:4px;position:absolute";
div.innerHTML = "";
docElem.appendChild( container );
var divStyle = window.getComputedStyle( div, null );
pixelPositionVal = divStyle.top !== "1%";
boxSizingReliableVal = divStyle.width === "4px";
docElem.removeChild( container );
}
zepto.jsで利用されている例):
/*
zepto / src / ie.js
http://git.io/njJPSg
*/
// getComputedStyle shouldn't freak out when called
// without a valid element as argument
try {
getComputedStyle(undefined)
} catch(e) {
var nativeGetComputedStyle = getComputedStyle;
window.getComputedStyle = function(element){
try {
return nativeGetComputedStyle(element)
} catch(e) {
return null
}
}
}
最後に
jqueryとかzeptoとかjquery.transitとか、JSからCSSを指定する際に、ブラウザ別にどうやって処理を分けているんだろうなぁと思い、調べました。 調べてみるとgetComputedStyleというメソッドがあることを知り、使ってみたいと思い、試しに使ってみた次第でした。 自分のコードでは実線に投入できるほど、安定とパフォーマンスを発揮しませんが、getComputedStyleの雰囲気を伝えられていれば幸いです。最後までご覧頂きましてありがとうございました。






