実際のアプリケーションではこれを実際に行うべきではなく、必要とするべきでもありませんが、これは単なる楽しみであると言っているので。ここに楽しい部分があります:
はい、できます。AJAX呼び出しを介してCSSファイルをロードすることが唯一の方法ではありませんが、それを実際にクロスブラウザーにする唯一の(しかし非効率的な)方法である可能性があります。関数はすべてのブラウザーでサポートされているわけではなく、CSS3の機能であるため、以下の宣言でさえ、真のクロスブラウザーにはなりません。calc()
編集:2018年現在、calc
すべての最新のブラウザでサポートされています。
div {
width: 300px; /* a fallback value for old browsers */
width: -webkit-calc(100% - 50px);
width: -moz-calc(100% - 50px);
width: calc(100% - 50px);
}
とそのルールから生のCSSコードを取得できます。ルールdocument.styleSheets
のプロパティはあなたに完全なステートメントを与えます。ただし、ブラウザが異なれば、関数cssText
を使用した値の解析も異なる場合があります。calc()
calc()
より複雑な例を使用して、ブラウザーが関数をどのように処理するかを確認します。
calc(100% - -50px*6 + 4em/2);
Firefox(v.18)はこれを次のように扱います。
そして、これはGoogle Chrome(v.24)がそれをどのように扱うかです:
示されているように; FFはプレフィックスなしのcalc
値をそのまま取得し、Chromeは-webkit
プレフィックス付きの値を取得して、ネストされた括弧で再解析します(必要な場合)。Chromeで-webkitと宣言しない場合。値を完全に無視します。したがって、calcステートメントを操作するときは、これらを考慮に入れる必要があります。
ここで、複雑な例を使用します。まず、calc()関数内のステートメントを取得します。
"100% - -50px*6 + 4em/2"
次に、ステートメントの要素を配列に分解します。
["100%", "-", "-50px", "*", "6", "+", "4em", "/", "2"]
最後に、配列アイテムの値と単位を処理して、プログラムで使用できるようにします(必要に応じて)。
[{ value:100, unit:"%" }, "-", { value:-50, unit:"px" }, "*", { value:6, unit:undefined }, "+", { value:4, unit:"em" }, "/", { value:2, unit:undefined }]
上記の最終結果には、値オブジェクトと演算子が(順番に)含まれています。
さらに読む前に; 以下のコードは、すべてのブラウザと状況で完全にテストされているわけではないことに注意してください。ネストされた括弧の解析(Chromeのように)や、複数または組み合わせたcalc()関数を持つ値は処理しません。これをテストしたい場合; Firefoxはネストされた括弧を解析しないため、またはコードを拡張してそれらのサポートを有効にすることができるため、Firefoxをお勧めします。
// Get the sheet you want to process. (assume we want to process the third sheet):
var sheet = document.styleSheets[2]; //you could also iterate all the sheets in a for loop
processRules(sheet);
/** Iterates through the rules of the specified style sheet;
* then dissolves and logs values including a calc() function.
*/
function processRules(sheet) {
var rules = sheet.cssRules // Mozilla, Safari, Chrome, Opera
|| sheet.rules; // IE, Safari
for (var i = 0; i < rules.length; i++) {
var rule = rules[i];
// Check if we have a calc() function in this rule
if (hasCalc(rule.cssText)) {
// Get the calculation statement inside the calc() function.
var statement = getCalcStatement(rule.cssText);
// Dissolve the statement into its elements and log.
console.log(dissolveCalcElements(statement));
}
}
}
/** Checks whether the CSS value includes a calc() function,
* (This is also for avoiding unnecessary regex.)
*/
function hasCalc(value) {
return value.toLowerCase().indexOf('calc(') >= 0;
}
/** Gets the full statement (string) inside a calc() function.
*/
function getCalcStatement(rule) {
if (!rule) return '';
var pattern = /calc\(([^\)]+)\).*/;
var match = pattern.exec(rule);
return match && match.length > 1 ? match[1] : '';
}
/** Splits the calc operation's elements (values and operators) and
* dissolves the values into objects with value and unit properties.
*/
function dissolveCalcElements(statement) {
// The CSS calc() function supports 4 basic math operations only:
// Addition (+), Subtraction (-), Multiplication (*), Division (/)
// White-spaces are very important in a calc statement.
// From Mozilla: "The + and - operators must always be surrounded by whitespace.
// The * and / operators do not require whitespace, but adding it for consistency is allowed, and recommended."
// We could use: statement.split(/(\s+[\+\-]\s+|\s*[\*\/]\s*)/);
// to include the operators inside the output array, but not all browsers
// support splicing the capturing parentheses into the array like that. So:
statement = statement.replace('*', ' * ').replace('/', ' / ');
var arr = statement.split(/\s+/);
console.log("arr", arr);
var calcElems = [];
for (var i = 0; i < arr.length; i++) {
var d = dissolveElement(arr[i]);
calcElems.push(d);
}
return calcElems;
}
/** Dissolves the value and unit of the element and
* returns either the operator or an object with "value" and "unit" properties.
*/
function dissolveElement(val) {
// Check if the value is an operator.
var ops = '+-*/';
if (ops.indexOf(val) >= 0) return val;
var o = {};
// CSS units in a calc statement can have all the regular units.
// According to W3C; they can also, can include a "vw" unit (stands for viewport).
var pattern = /([\+\-]?[0-9\.]+)(%|px|pt|em|in|cm|mm|ex|pc|vw)?/;
// Exec the value/unit pattern on the property value.
var match = pattern.exec(val);
// So we reset to the original value if there is no unit.
if (match) {
var v = match.length >= 2 ? match[1] : match[0];
o.value = toFloat(v); //parse value as float
o.unit = match.length >= 3 ? match[2] : '';
}
else {
o = { value:val, unit:''};
}
console.log("dissolve", match, val, o);
return o;
}
// Helper Functions
function toFloat(value) { return parseFloat(value) || 0.0; }
それでおしまい。私が言ったように、私はこれをしませんが、何かが可能かどうかを知ることは常に良いことです。
注:jQueryプラグインの作成について言及したので(楽しみのために)。このためにjQueryは実際には必要ありません。また、のような関数を呼び出すと$('div').css('width')
、計算された値のみが提供され、生のcalcステートメントは提供されません。