Image placeholder

CSS函数 calc() 完整指南

Image placeholder
F2EX 2021-06-30

CSS 函数 calc() 允许在声明 CSS 属性值时执行一些计算。在本指南中,将涵盖有关 calc() 功能的所有信息。

先来看一个简单的例子:

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

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);
}

它甚至可以在另一个函数中使用!例如:

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

calc() 用于长度单位和其他数字

请注意,上面的所有示例基本上都是基于数字的。下面我们将了解如何使用数字的一些注意事项(因为有时你不需要单位),但请注意 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); 以及:rotate(calc(10deg * 5));

你也可以不执行任何计算,它仍然有效:

.el {
  /* 有点奇怪但还可以  */
  width: calc(20px);
}

不能用于媒体查询

calc() 在应用于媒体查询时将不起作用。

/* 错误的用法! */
@media (min-width: calc(40rem + 1px)) {

}

混合单位

这可能是 calc() 最有价值的功能!几乎上面的每个例子都已经做到了这一点,但是为了说明这一点,这里混合了不同的单位:

/* 百分比单位与像素单位混合  */
width: calc(100% - 20px);

上面的示例中并不是直接使用 100% 减去 20px,而是元素的 100% 宽度减去 20px ,假如元素的 100% 宽度是 600px,那么最后的取值就是 600px 减去 20px。

以下是混合单位的其他一些示例:

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

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

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)),其中空格不仅需要而且很有用。

在 + 和 – 周围需要空格的原因实际上是因为解析问题。乘法和除法不需要运算符周围的空格,但为了代码统一和便于识别,我建议同样在运算符周围加上空格。

至于外部周围的空白留多少并不重要。如果你愿意,你甚至可以进行换行:

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

不过要注意: calc() 函数的 calc 之间没有空格。

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

嵌套 calc(calc());

你可以这样做,但没必要。例如:

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

上面这段代码等同于:

.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);
}

自定义属性也可以相互引用。这是一个示例,其中使用了一些数学计算。(它最终必须在 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 {
  --importantNumber: 2;
}

.el {
  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%)
  )
}

部分内容译自:https://css-tricks.com/a-complete-guide-to-calc-in-css/


2021-07-02