[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の雰囲気を伝えられていれば幸いです。最後までご覧頂きましてありがとうございました。