前言

在早期如果想要对某一些样式进行动态计算,绝大多数的做法都是使用JavaScript来进行,当时的CSS在面对这种场景显得有点无能为力。但是,当CSS3中新增了calc函数时,面对这种场景,JavaScript不再是我们的第一选择,我们只用 CSS 就可以进行相当复杂的计算了。在使用calc的过程中,相信大家或多或少都遇到过下面这些“坑”。

如果这篇文章有帮助到你,️关注+点赞️鼓励一下作者,文章公众号首发,关注 前端南玖 第一时间获取最新文章~

常见的“坑”

先来介绍css使用calc无效的两种常见情况:

运算符之间没加空格

/*错误写法*/
div{
width: calc(100%-50px);
}
/*正确写法*/
div{
width: calc(100% - 50px);
}

这里错误写法中-两边没加空格,导致width不生效。但并不是所有运算符间都需要加空格,只有 +- 需要加空格,因为运算允许负数的出现,如:

div{
width: calc(100% + -50px);
}

所以,为了统一,建议所有运算符都加上空格,防止记忆混淆。

运算值没带单位

我们都知道在写css时,如果数值为0我们一般会省略它的单位,比如:0px我们一般会直接写成0。但是在calc()函数中如果0不带单位,也会导致不生效。

/*错误写法*/
div{
width: calc(0 + 100px);
}
/*正确写法*/
div{
width: calc(0px + 100px);
}

这里上面的不带单位的写法也是不生效的。这里我相信很多人都会有疑问,为什么0还需要带个单位?

这是因为calc() 函数传入的是一个数学表达式,而表达式的值可以有多种类型,如长度、百分比、角度等。那如果你传个 0 进去,没单位的话,怎么知道这个 0 是属于什么类型?

低版本less处理calc冲突

以下代码在低版本less中会被编译成你意想不到的结果:

.box {
width: calc(100% - 50px)
}

编译后:

.box {
width: calc(50%)
}

导致这个结果的原因在于less中有一套自己的运算规则:

less运算(Operations)

算术运算符 +-*/ 可以对任何数字、颜色或变量进行运算。如果可能的话,算术运算符在加、减或比较之前会进行单位换算。计算的结果以最左侧操作数的单位类型为准。如果单位换算无效或失去意义,则忽略单位。无效的单位换算例如:px 到 cm 或 rad 到 % 的转换。

// 所有操作数被转换成相同的单位
@conversion-1: 5cm + 10mm; // 结果是 6cm
@conversion-2: 2 - 3cm - 5mm; // 结果是 -1.5cm // conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // 结果是 4px // example with variables
@base: 5%;
@filler: @base * 2; // 结果是 10%
@other: @base + @filler; // 结果是 15%

乘法和除法不作转换。因为这两种运算在大多数情况下都没有意义,一个长度乘以一个长度就得到一个区域,而 CSS 是不支持指定区域的。Less 将按数字的原样进行操作,并将为计算结果指定明确的单位类型。

所以上面的less会被进行如下处理:

  • 由于100%与50px单位不同,会被转换成相同的单位%(以最左侧操作数的单位类型为准)
  • 再进行减法运算得到50%

解决方案

  • 转义

转义(Escaping)允许你使用任意字符串作为属性或变量值。任何 ~"anything"~'anything' 形式的内容都将按原样输出,除非 interpolation

我们希望less不要帮我们处理,所以这里我们可以使用less的转义语法让calc函数原样输出就好了

.box {
width: calc(~"100% - 50px")
}
  • 升级lessless-loader

了解calc函数

CSS calc 函数用于在指定 CSS 属性值时执行计算。它可以用于可以使用任何数值的地方。它将表达式作为参数,并将结果用作使用它的 CSS 属性的值。我们可以用它进行加法+、减法-、乘法*和除法/

语法

/* property: calc(expression) */
width: calc(100% - 80px);

calc() 函数用一个表达式作为它的参数,用这个表达式的结果作为值。这个表达式可以是任何如下操作符的组合,采用标准操作符处理法则的简单表达式。

  • + 加法
  • - 减法
  • * 乘法,乘数中至少有一个是 number
  • / 除法,除数必须是number

规则

  • +- 运算符的两边必须要有空白字符。 比如,calc(50% -8px) 会被解析成为一个无效的表达式,解析结果是:一个百分比 后跟一个负数长度值。而加有空白字符的、有效的表达式 calc(8px + -50%) 会被解析成为:一个长度 后跟一个加号 再跟一个负百分比。
  • */ 这两个运算符前后不需要空白字符,但如果考虑到统一性,仍然推荐加上空白符。
  • 用 0 作除数会使 HTML 解析器抛出异常。
  • 涉及自动布局和固定布局的表格中的表列、表列组、表行、表行组和表单元格的宽度和高度百分比的数学表达式,auto 可视为已指定。
  • calc() 函数支持嵌套,但支持的方式是:把被嵌套的 calc() 函数全当成普通的括号。

解惑

想要了解前面那些坑产生的原因,我们得先了解CSS中的基础语法与数据类型:

DIMENSION语法

DIMENSION    {num}{ident}

这里的num值的是数字,那么ident代表什么呢,这个我们也可以在CSS规范中找到答案

ident

ident    [-]?{nmstart}{nmchar}*

nmstart和nmchar

nmstart [_a-z]|{nonascii}|{escape}

nmchar [_a-z0-9-]|{nonascii}|{escape}

解惑calc(100%-50px)

了解完CSS的基础语法与数据结构,我们现在可以来看看解析器是如何解析calc(100%-50px)的。

  • 首先DIMENSION语法,{num}{ident}会将其分割为num:100ident:%和-100px
  • %是单位,这个应该没有疑问
  • -100px这个符合nmchar语法,所以没有将其拆开,而是保留作为单位解析,但CSS中没有-100px这个单位,所以这个表达式不会生效

兼容性

calc 函数具有惊人的浏览器支持,一直到 IE9。如果你用旧版浏览器或 Opera Mini 编写代码,请考虑使用数值作为后备。

最后

喜欢的同学欢迎点个赞呀,想要查看源码的同学快来公众号回复碎片吧~

原文首发地址点这里,欢迎大家关注公众号 「前端南玖」,如果你想进前端交流群一起学习,请点这里

我是南玖,我们下期见!!!

为什么CSS中的calc函数可能会不生效?的更多相关文章

  1. CSS中常用的函数

    一.CSS函数的用法 设置css的属性值时可以使用css函数,如果color:rgba(20,30,50,0.5),css中有很多这样的函数. 二.常用的CSS函数 a.calc()函数   这个函数 ...

  2. 分类器是如何做检测的?——CascadeClassifier中的detectMultiScale函数解读

    原地址:http://blog.csdn.net/delltdk/article/details/9186875 在进入detectMultiScal函数之前,首先需要对CascadeClassifi ...

  3. 关于CSS中的定位使用子绝父相(子类绝对位置和父类相对位置)

    关于CSS中的定位使用子绝父相(子类绝对位置和父类相对位置) 欢迎转发,但是请填写原博客地址https://www.cnblogs.com/JNovice/p/9536910.html  前言:最近在 ...

  4. CSS中的偏僻知识点

    一.css中的calc 在CSS中有calc属性用于尺寸的计算,可以让百分比和像素值进行运算. div {width : calc(100% - 30px);} 为了兼容性 /*Firefox*/ - ...

  5. CSS 中 calc() 函数用法

    CSS calc() 函数 calc() 函数用于动态计算长度值. 注意,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px): 任何长度值都可以使用calc()函数进 ...

  6. 理解CSS中的数学表达式calc()

    前面的话 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路.本文将介绍calc()的相关内容 定义 数学表达式calc()是calculat ...

  7. CSS中新属性calc()

    CSS3的calc()使用 原文: http://www.w3cplus.com/css3/how-to-use-css3-calc-function.html © w3cplus.com calc( ...

  8. css中的数学表达式calc()

    前言 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路. 概念 数学表达式calc()是calculate计算的缩写,它允许使用+.-.*. ...

  9. css绘制特殊图形,meida查询,display inline-box间隙问题以及calc()函数

    本文同时发表于本人个人网站 www.yaoxiaowen.com 距离上一篇文章已经一个月了,相比于写代码,发现写文章的确是更需要坚持的事情.言归正传,梳理一下这一个月来,在写ife任务时,有必要记录 ...

随机推荐

  1. Postman如何做接口测试,那些不得不知道的技巧

    Postman如何做接口测试1:如何导入 swagger 接口文档 在使用 postman 做接口测试过程中,测试工程师会往界面中填入非常多的参数,包括 url 地址,请求方法,消息头和消息体等一系列 ...

  2. Magicodes.Pay已支持Volo Abp

    Magicodes.Pay已支持Volo Abp 简介 Magicodes.Pay希望打造一个统一支付库,相关库均使用.NET标准库编写,支持.NET Framework以及.NET Core.目前已 ...

  3. docker启动失败问题

    内核3.10,systemctl start docker 被阻塞,没有返回,查看状态为启动中. 某兄弟机器安装docker之后,发现systemctl start docker的时候阻塞,由于排查走 ...

  4. 延时任务-基于redis zset的完整实现

    所谓的延时任务给大家举个例子:你买了一张火车票,必须在30分钟之内付款,否则该订单被自动取消.订单30分钟不付款自动取消,这个任务就是一个延时任务. 我之前已经写过2篇关于延时任务的文章: <完 ...

  5. [CF1481D] AB Graph(构造)

    题解 给一个 n \tt n n 个点的完全有向图, ( u , v ) \tt(u,v) (u,v) 或者 ( v , u ) \tt(v,u) (v,u) 都有一条边,前提是 u ≠ v \tt ...

  6. bind搭建内网DNS服务器架构(主从、子域授权、DNS转发器)

    实验目的 模拟企业DNS服务架构服务器及原理 实验环境准备 实验架构图 实验设备 DNS服务器4台 主服务器master(centos8):IP_192.168.100.30, 从服务器slave(r ...

  7. 【java】学习路线6-静态方法、私有化方法、父类子类

    import java.util.Arrays; /* 我们可以自己创建方法(静态) 私有化方法,阻止他人实例化该方法 静态代码块只执行一次,只在加载这个所在类的时候执行 父类 - 子类 子类继承自父 ...

  8. 微服务网关Gateway实践总结

    有多少请求,被网关截胡: 一.Gateway简介 微服务架构中,网关服务通常提供动态路由,以及流量控制与请求识别等核心能力,在之前的篇幅中有说过Zuul组件的使用流程,但是当下Gateway组件是更常 ...

  9. Windows 2012 R2 计划任务发送邮件

     这两天把域控制器升级到了2012 R2,忽然发现原本用的系统自动发邮件提示用户账户锁定的计划任务配置起来有点麻烦了.原因是微软把自动发送邮件和提示消息的功能从计划任务中去除了. 首先用wevtu ...

  10. C# 中的那些锁,在内核态都是怎么保证同步的?

    一:背景 1. 讲故事 其实这个问题是前段时间有位朋友咨询我的,由于问题说的比较泛,不便作答,但想想梳理一下还是能回答一些的,这篇就来聊一聊下面这几个锁. Interlocked AutoResetE ...