例如:
- div {
- width: calc(100% - 50px);
- }
我想得到百分比值(100%)和像素值(50px),我需要知道它后面跟着什么(px,em,pt,%).
所以基本上:
>在calc之后得到一个值(在分隔符之前(,–,*,/)
>在分离器之后和之前得到一个值)
>请注意,可能会有比一个更多的值!计算(100% – 20px – 0.8em)
编辑:
Spudley谈到解析整个CSS样式表,但这可能会导致开销.因为这是一个很好的项目,所以允许开销,所以你可以乱七八糟地做任何你想要完成的事情!
谢谢.
解决方法
是的,你可以做到.通过AJAX调用加载CSS文件不是唯一的方法,但它可能是使其真正跨浏览器的唯一(但效率低下)方式.即使下面的声明也不会使它成为真正的跨浏览器,因为calc()函数是not supported by all浏览器,它是一个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);
- }
您可以从document.styleSheets及其规则中获取原始CSS代码.规则的cssText属性将为您提供完整的语句.但是不同的浏览器可能会以不同的方式使用calc()函数来解析值.
我将使用更复杂的示例来查看浏览器如何处理calc()函数:
- calc(100% - -50px*6 + 4em/2);
这就是Firefox(第18版)对待它的方式:
这就是谷歌Chrome(第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,因为它不解析嵌套的括号,或者你可以扩展代码以支持它们.
- // 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’)只会给你计算值,而不是raw calc语句.