当前位置: 首页 > 科技观察

现代CSS解决方案:CSS数学函数Calc

时间:2023-03-20 13:51:06 科技观察

在CSS中,其实有各种各样的函数。具体分为:变换函数[1]数学函数[2]过滤函数[3]颜色函数[4]图像函数[5]计数器函数[6]字体函数[7]形状函数[8]参考函数[9]CSSgridfunctions[10]本文将专门介绍四种已被浏览器大规模支持的CSS数学函数(Mathfunctions):calc()min()max()clamp()为什么说支持浏览器?大规模支持?因为除了这四个已经被大规模支持的数学函数外,其实规范CSSValuesandUnitsModuleLevel4[11]已经定义了sin(),cos(),tan()等函数等。指数函数与pow()、sqrt()等数学函数相关,但目前处于实验室阶段,还没有浏览器支持,还需要给它们一些时间。Calc()calc()这个CSS[12]函数允许在声明CSS属性值时执行一些计算。语法类似于:{width:calc(100%-80px);}需要注意的几点:+和-运算符的两边必须有空白字符。例如,calc(50%-8px)将被解析为无效表达式,必须写为calc(8px+-50%)。*和/这两个操作符不需要前后有空格,但如果考虑统一性,还是建议加上空格。除以0将导致HTML解析器抛出异常。自动布局和固定布局的表格中涉及表格列、表格列组、表格行、表格行组、表格单元格的宽高百分比的数学表达式,auto可以按指定处理。calc()函数支持嵌套,但支持的方法是:将嵌套的calc()函数视为普通括号。(因此,只需在函数内直接使用括号即可。)calc()支持与CSS变量混合。看一个最常见的例子,页面结构如下:Content

Footer
页面g-footer的高度为80px。我们希望无论页面有多长,g-content部分都能把剩余的空间填满,像这样:这种布局利用flex灵活的布局很容易实现。当然,也可以用calc()来实现:.g-container{height:100vh;}.g-content{height:calc(100vh-80px);}.g-footer{height:80px;}下面是一些Calc()函数的高级技能。Calc中加减乘除的区别注意calc()中加减乘除的区别:{font-size:calc(1rem+10px);width:calc(100px+10%);}可以看出,加减两边的操作数需要单位,而乘除需要一个无单位的数,只代表一个乘数:{width:calc(100%/7);animation-delay:calc(1s*3);}calc的嵌套calc()函数可以嵌套,像这样:{width:calc(100vw-calc(100%-64px));}这时候内部的calc()function可以退化写成括号(),所以上面的代码等价于:{width:calc(100vw-(100%-64px));},即嵌套了calc(),和几个函数calc的字符可以省略。Calc中不同单位的混合计算calc()支持不同单位的混合计算。对于length,只要是长度相关的单位,都可以进行混合计算,包括这些:px%emreminmmcmptpxchvhvwvminvmax这里有个有意思的地方,计算一定是consumption,在性能方面,早年有这么一段直接让Chrome浏览器崩溃的CSS代码Crash:
CSS样式如下:div{--initial-level-0:calc(1vh+1%+1px+1em+1vw+1cm);--level-1:calc(var(--initial-level-0)+var(--initial-level-0));--level-2:calc(var(--level-1)+var(--level-1));--level-3:计算(var(--level-2)+var(--level-2));--level-4:计算(var(--level-3)+var(--level-3));--level-5:计算(var(--level-4)+var(--level-4));--level-6:计算(var(--level-5)+var(--level-5));--level-7:计算(var(--level-6)+var(--level-6));--level-8:计算(var(--level-7)+var(--level-7));--level-9:计算(var(--level-8)+var(--level-8));--level-10:计算(var(--level-9)+var(--level-9));--level-11:计算(var(--level-10)+var(--level-10));--level-12:计算(var(--level-11)+var(--level-11));--level-13:计算(var(--level-12)+var(--level-12));-等级-14:计算(var(--level-13)+var(--level-13));--level-15:计算(var(--level-14)+var(--level-14));--level-16:计算(var(--level-15)+var(--level-15));--level-17:计算(var(--level-16)+var(--level-16));--level-18:计算(var(--level-17)+var(--level-17));--level-19:计算(var(--level-18)+var(--level-18));--level-20:计算(var(--level-19)+var(--level-19));--level-21:计算(var(--level-20)+var(--level-20));--level-22:计算(var(--level-21)+var(--level-21));--level-23:计算(var(--level-22)+var(--level-22));--level-24:计算(var(--level-23)+var(--level-23));--level-25:计算(var(--level-24)+var(--level-24));--level-26:计算(var(--level-25)+var(--level-25));--level-27:计算(var(--level-26)+var(--level-26));--level-28:计算(var(--level-27)+var(--level-27));--level-29:计算(var(--level-28)+var(--level-28));--level-30:计算(var(--level-29)+var(--level-29));--level-final:calc(var(--level-30)+1px);博尔der-width:var(--level-final);border-style:solid;}可以看出,从--level-1到--level-30,每次的计算量翻倍,最后到--level-final变量,展开会有2^30=1073741824--initial-level-0表达式的内容以及对于每个--initial-level-0表达式--calc(1vh+1%+1px+1em+1vw+1cm),它已经足够复杂了当浏览器解析它时。混合在一起,导致浏览器(Chrome70之前的版本)的BOOM。为了看效果,我们将上面的样式赋值给一个元素,悬停时得到如下效果:css-crash当然,这个BUG现在已经修复了。我们也可以借鉴这个小DEMO。一是calc可以进行不同单元的混合运算。另外就是要注意,如果使用时计算量巨大,可能会导致较大的性能损失。消耗。当然,不要混合使用长度单位和非长度单位,像这样:{animation-delay:calc(1s+1px);}CalcwithCSScustomvariables使用calc()函数的一个非常重要的特性是它可以和CSSCustom和CSS@property变量一起使用。最简单的DEMO::root{--width:10px;}div{width:calc(var(--width));}当然,完全不是这个样子,好像没什么意义。在实际应用场景中,会比上面的DEMO稍微复杂一些。假设我们要实现这样一个加载动画效果,一开始只有3个球:可能的写法是这样的,我们给3个球都加上相同的旋转动画,然后分别控制它们的animation-delay:
.item:nth-child(1){animation:rotate3sinfinitelinear;}.item:nth-child(2){animation:rotate3sinfinite-1slinear;}.item:nth-child(3){animation:rotate3sinfinite-2slinear;}如果有一天,这个动画需要扩展到5个球,像这样:不得已我们不得不添加HTML和修改CSS。在Calc和CSS变量的帮助下,这个场景可以稍微简化。假设只有3个球:我们传入HTMLStyle标签--delay变量,直接在CSS中使用:.g-item{animation:rotate3sinfinitelinear;animation-delay:calc(var(--delay)*-1s);}@keyframesrotate{to{transform:rotate(360deg);}}而当动画修改为5个球时,我们不需要修改CSS,直接修改HTML即可,像这样:核心CSS还是这句话,不需要做任何改动:{animation-delay:calc(var(--delay)*-1s);}完整DEMO,可以点击此处:CodePen演示--Calc&a议员;CSSVariableDemo[13]calc搭配自定义变量时的默认值依然是上述的Loading动画效果。如果我的某个HTML标记忘记填写--delay的值,会发生什么?像这样:{animation-delay:calc(var(--delay)*-1s);}因为html标签没有通过在--delay中,而在css中没有找到对应的值,此时animation-delay:calc(var(--delay)*-1s)这句实际上是无效的,相当于animation-delay:0,效果就是丢球的效果:因此,基于这种情况,可以使用css自定义变量var()的fallback机制:{//1in(--delay,1)是容错的mechanismanimation-delay:calc(var(--delay,1)*-1s);}此时如果没有读取--delay值,会使用默认的1和-1s进行计算calc字符串拼接很多人在使用CSS的时候都会尝试字符串拼接,像这样::root{--urlA:'url(https://s1.ax1x.com/2022/03/07/';--urlB:')';}div{宽度:400px;高度:400px;background-image:calc(var(--urlA)+var(--url)+var(--urlB));}这里我想使用calc(var(--urlA)+var(--url)+var(--urlB))拼出背景图像中可用的完整URLurl(https://s1.ax1x.com/2022/03/07/bsBD1I.png)。但是,这是不允许的(不可能)。calc没有字符串连接功能。唯一可能的字符串连接是在元素的伪元素的内容属性中。但它也没有使用calc。看这样一个例子,是错误的::root{--stringA:'123';--stringB:'456';--stringC:'789';}div::before{content:calc(var(--stringA)+var(--stringB)+var(--stringC));}这个时候不需要calc,只需使用自定义变量即可添加。因此,正确的写法::root{--stringA:'123';--stringB:'456';--stringC:'789';}div::before{content:var(--stringA)+var(--stringB)+var(--stringC);}此时可以正常显示内容了:再次,calc不具备拼接字符串的能力,以下使用方法是无法识别的错误语法:.el::before{//不支持字符串拼接content:calc("My"+"counter");}.el::before{//不支持字符串乘法content:calc("StringRepeat3times"*3);}最后,本文是现代CSS解决方案系列的第二篇。以公众号开头。希望通过一些更通俗易懂的语言和更直观的DEMO,告诉大家今天如何更好的使用CSS来提升我们网站的体验,以提高我们的技能。好了,本文到此结束,希望对你有所帮助:)参考资料【1】变换函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#transform_functions.[2]数学函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#math_functions。[3]过滤函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#filter_functions。[4]颜色函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#color_functions。[5]图像函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#image_functions。[6]计数器函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#counter_functions。[7]字体函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#font_functions。[8]形状函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#shape_functions。[9]函数参考:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#reference_functions。[10]CSS网格函数:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#css_grid_functions。[11]CSS值和单位模块级别4:https://drafts.c??sswg。org/css-values/#math。[12]CSS:https://developer.mozilla.org/zh-CN/docs/Web/CSS。[13]CodePenDemo--Calc&CSSVariableDemo:https://codepen.io/Chokcoco/pen/OJzarJL。