您不应该在现实生活中的应用程序中真正这样做,甚至不需要这样做,但既然您说这只是为了好玩;这是有趣的部分:
是的,你可以做到。通过 AJAX 调用加载 CSS 文件不是唯一的方法,但它可能是使其真正跨浏览器的唯一(但效率低下)的方法。即使下面的声明也不能使它真正跨浏览器,因为并非所有浏览器都支持calc()
该功能,并且它是 CSS3 功能。
编辑:截至 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) 的处理方式:
如图所示; calc
FF按原样获取非前缀值,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,因为它不解析嵌套括号,或者您可以扩展代码以启用对它们的支持。
// 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 语句。