CSS calc()的完整指南

目录
文章目录隐藏
  1. calc()用于值
  2. calc()用于长度和其他数字事物
  3. 不接受媒体查询
  4. 混合单元
  5. 与预处理器数学比较
  6. 数学计算
  7. calc()的数学运算符
  8. 嵌套 calc(calc())
  9. CSS 自定义属性和 calc()使用
  10. 添加单位
  11. 色彩值的使用
  12. 不能将 calc()和 attr()合并
  13. 浏览器工具
  14. 浏览器支持

CSS 具有calc()执行基本数学运算的特殊功能。

.main-content {
  /* 从 100vh 减去 80px */
  height: calc(100vh - 80px);
}

在本指南中,我将介绍有关此非常有用的功能的所有知识。 推荐阅读之前写过一篇类似文章《css3 calc()属性介绍以及自适应布局使用方法》。

calc()用于值

可以使用calc()函数的唯一地方是值。请看下面这些示例,其中我们为许多不同的属性设置值。

.el {
  font-size: calc(3vw + 2px);
  width:     calc(100% - 20px);
  height:    calc(100vh - 20px);
  padding:   calc(1vw + 5px);
}

它也可以仅用于属性的一部分,例如:

.el {
  margin: 10px calc(2vw + 5px);
  border-radius: 15px calc(15px / 3) 4px 2px;
  transition: transform calc(1s - 120ms);
}

它甚至可以成为构成属性一部分的另一个函数的一部分!例如,在颜色渐变属性中使用 calc():

.el {
  background: #1E88E5 linear-gradient(
    to bottom,
    #1E88E5,
    #1E88E5 calc(50% - 10px),
    #3949AB calc(50% + 10px),
    #3949AB
  );
}

calc()用于长度和其他数字事物

请注意,以上所有示例本质上都是基于数字的。我们将讨论一些数字使用方法的注意事项(因为有时不需要单位),但这是用于数字数学的,而不是字符串或类似的东西。

.el {
  /* 不可以! */
  counter-reset: calc("My " + "counter");
}
.el::before {
  /* 不可以! */
  content: calc("Candyman " * 3);
}

CSS 有很多长度,它们都可以用于 calc():

  • px
  • %
  • em
  • rem
  • in
  • mm
  • cm
  • pt
  • pc
  • ex
  • ch
  • vh
  • vw
  • vmin
  • vmax

当然没有单位数也可以接受,例如line-height: calc(1.2 * 1.2);,如transform: rotate(calc(10deg * 5));

当我们不用 calc()去执行任何计算时,它仍然有效:

.el {
  /* 有点怪,不过还好 */
  width: calc(20px);
}

不接受媒体查询

如果 calc()使用正确(将长度单位用作属性的值),则将其 calc()应用于媒体查询时无法使用。

@media (max-width: 40rem) {}

/* 不可以 */
@media (min-width: calc(40rem + 1px)) {}

混合单元

这也许是最能体现 calc()价值的功能!上面几乎每个示例都已经做到了这一点,但只是要指出一点,这里混合了不同的长度单元:

width: calc(100% - 20px);

这就是说:元素的宽度为负 20 像素。

有字面上没有办法预先计算出在流体宽度的情况下单独的像素值。换句话说,calc()无法使用 Sass 之类的东西进行预处理,以尝试完成 polyfill。不需要,因为浏览器支持很好。但是要点是,当我们以这种方式混合单位时,必须在浏览器中(“运行时”)完成操作,这是的大部分值 calc()。

这是混合单元的其他一些示例:

transform: rotate(calc(1turn + 45deg));

animation-delay: calc(1s + 15ms);

这些可能会被预处理,因为它们混合了与运行时确定的任何单位都不相关的单位。

与预处理器数学比较

我们刚刚介绍了无法预处理 calc()可以做的最有用的事情。但是有一点需要注意,例如,Sass 内置了数学功能,因此可以执行以下操作:

$padding: 1rem;

.el[data-padding="extra"] {
  padding: $padding + 2rem; 
  margin-bottom: $padding * 2; 
}

甚至带有单位的数学也可以在这里工作,将相同单位的值相加或乘以无单位数。但是你不能混合使用单位,并且它也有类似的限制 calc()(例如,乘法和除法必须使用无单位的数字)。

数学计算

例如,通过 calc()假设你需要计算准确 1 / 7 个元素的宽度

.el {
  /* 这更容易理解 */
  width: calc(100% / 7);

  /* 传统的写法 */
  width: 14.2857142857%;
}

这可能会在某种自行创建的 CSS API 中获得成功,例如:

[data-columns="7"] .col { width: calc(100% / 7); }
[data-columns="6"] .col { width: calc(100% / 6); }
[data-columns="5"] .col { width: calc(100% / 5); }
[data-columns="4"] .col { width: calc(100% / 4); }
[data-columns="3"] .col { width: calc(100% / 3); }
[data-columns="2"] .col { width: calc(100% / 2); }

calc()的数学运算符

数学运算符+,-,*,和/ 对于大家来说并不陌生。但是这里在使用它们的方式上有所不同。

加号(+)和减号(-)要求两个数字均为长度

.el {
  /* 有效 👍 */
  margin: calc(10px + 10px);

  /* 无效 👎 */
  margin: calc(10px + 5);
}

无效的值会使整个单独的声明无效。

除(/)要求第二个数字不能为无单位

.el {
  /* 有效👍 */
  margin: calc(30px / 3);

  /* 无效 👎 */
  margin: calc(30px / 10px);

  /* 无效👎 (不能除以 0) */
  margin: calc(30px / 0);
}

乘法(*)要求数字之一为无单位

.el {
  /* 有效👍 */
  margin: calc(10px * 3);

  /* 有效 👍 */
  margin: calc(3 * 10px);

  /* 无效 👎 */
  margin: calc(30px * 3px);
}

空格很重要

可以进行加法和减法。

.el {
  /* 有效👍 */
  font-size: calc(3vw + 2px);

  /* 无效 👎 */
  font-size: calc(3vw+2px);

  /* 有效 👍 */
  font-size: calc(3vw - 2px);

  /* 无效 👎 */
  font-size: calc(3vw-2px);
}

负数是可以的(例如calc(5vw - - 5px)),但这是一个例子,说明空白不仅是必需的,而且是有用的。

之所以需要在+和-之间设置间距,实际上是因为解析问题。例如,2px-3px被解析为数字“2”和单位“px-3px”,+还有其他问题,比如“被数字语法占用了”。我猜空白应该与自定义属性的- -语法有关,但不是!

乘法和除法不需要运算符周围的空格。但是我个人建议为了可读性还是有必要加上

外部的空白无关紧要。我们甚至可以根据需要进行换行:

.el {
  /* Valid 👍 */
  width: calc(
    100%     /   3
  );
}

但是请注意这一点:calc 和()括号之间没有空格。

.el {
  /* 无效👎 */
  width: calc (100% / 3);
}

嵌套 calc(calc())

.el {
  width: calc(
    calc(100% / 3)
    -
    calc(1rem * 2)
  );
}

calc()里面嵌套的 calc()是可以忽略掉的,因为它的父级是单独工作的:

.el {
  width: calc(
   (100% / 3)
    -
   (1rem * 2)
  );
}

在这种情况下,即使没有括号,也会遵循数学中的加减乘除的“操作顺序”规则。也就是说,除法和乘法首先发生(在加法和减法之前),因此根本不需要括号。可以这样写:

.el {
  width: calc(100% / 3 - 1rem * 2);
}

如果我们确实需要先进行加法或减法,则需要给它们加上必要的括号就可以啦。

.el {
  width: calc(100% + 2rem / 2);

  width: calc((100% + 2rem) / 2);
}

CSS 自定义属性和 calc()使用

除了 calc()混合单元的惊人功能外,接下来最令人惊讶的是 calc()可将其与自定义属性一起使用。自定义属性可以在随后的计算中使用:

html {
  --spacing: 10px;
}

.module {
  padding: calc(var(--spacing) * 2);
}

我敢肯定,你可以想象一个 CSS 设置,其中设置一堆 CSS 自定义属性,然后让其余的 CSS 根据需要使用它们,从而在顶部进行大量配置。

自定义属性也可以相互引用。下面是一个例子,其中使用了一些数学(注意,首先缺少 calc()函数),然后再应用。(它最终必须在 calc()中。)

html {
  --spacing: 10px;
  --spacing-L: var(--spacing) * 2;
  --spacing-XL: var(--spacing) * 3;
}

.module[data-spacing="XL"] {
  padding: calc(var(--spacing-XL));
}

你可能不喜欢这样,因为你需要记住 calc()在哪里使用该属性,但从可读性的角度来看,这是可能的,而且可能很有趣。

自定义属性可以来自 HTML,这有时是一件非常酷和有用的事情。

<div style="--index: 1;"> ... </div>
<div style="--index: 2;"> ... </div>
<div style="--index: 3;"> ... </div>
div {
  /* 索引值来自 HTML(带有回退) */
  animation-delay: calc(var(--index, 1) * 0.2s);
}

添加单位

如果你处于这样一种情况:没有单位的数字更容易存储,或者提前用没有单位的数字进行数学运算,你可以一直等到你应用数字乘以 1 和单位来添加单位。

html {
  --importantNumber: 2;
}

.el {
  /* Number stays 2, but it has a unit now */
  padding: calc(var(--importantNumber) * 1rem);
}

色彩值的使用

像 RGB 和 HSL 这样的颜色格式有可以使用 calc()处理的数字。例如,设置一些基本 HSL 值,然后更改它们以形成自己创建的系统(示例):

html {
  --H: 100;
  --S: 100%;
  --L: 50%;
}

.el {
  background: hsl(
    calc(var(--H) + 20),
    calc(var(--S) - 10%),
    calc(var(--L) + 30%)
  )
}

不能将 calc()和 attr()合并

CSS 中的attr()函数看起来很吸引人,就像你可以从 HTML 中提取属性值并使用它们一样。但是

<div data-color="red">...</div>

div {
 /* 不行 */
 color: attr(data-color);
}

这里没有“类型”,所以 attr()的唯一用途是与 content 属性一起使用的字符串。这意味着这样是有效的:

div::before {
  content: attr(data-color);
}

我之所以提到这一点,是因为试图以这种方式提取一个数字以用于计算可能会很有诱惑力,例如:

<div class="grid" data-columns="7" data-gap="2">...</div>
.grid {
  display: grid;

  /* 这两项工作都没有 */
  grid-template-columns: repeat(attr(data-columns), 1fr);
  grid-gap: calc(1rem * attr(data-gap));
}

幸运的是,这并不重要,因为 HTML 中的自定义属性同样有用甚至更多!

<div class="grid" style="--columns: 7; --gap: 2rem;">...</div>
.grid {
  display: grid;

  /* 好了! */
  grid-template-columns: repeat(var(--columns), 1fr);
  grid-gap: calc(var(--gap));
}

浏览器工具

浏览器开发工具会倾向于在样式表中编写 calc()时向你显示它。

浏览器工具

如果需要计算出的值,可以使用“计算”​​选项卡(在所有浏览器的 DevTools 中,至少是我所知道的)向你显示。

Chrome DevTools –计算

浏览器支持

该浏览器支持数据来自Caniuse,它具有更多详细信息。数字表示浏览器支持该版本及更高版本的功能。

浏览器支持

如果确实需要支持更早版本(例如 IE 8 或 Firefox 3.6),通常的技巧是在使用 calc()以下属性或值之前添加另一个属性或值:

.el {
  width: 92%; /* Fallback */
  width: calc(100% - 2rem);
}

当然也有很多已知的问题 calc(),不过它们都是针对旧浏览器的。

  • Firefox <59 不支持 calc() 颜色功能。范例: color: hsl(calc(60 * 2), 100%, 50%)。
  • 当 IE 9 – 11 用于任何值 box-shadow 时,将不会呈现该 属性 calc()。
  • width: calc() 用在表格单元格上时,在 IE 9-11 和 Edge 都不支持

如果要将 calc()用作包含视口单位等的流体类型情况下,请确保包含使用 rem 或 em 的单位,以便用户仍然可以根据需要通过放大或缩小来控制字体的上下起伏。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » CSS calc()的完整指南

发表回复