计算 Calculations

计算是 Sass 如何表示 `calc()` 函数,以及类似的函数,如 `clamp()`、`min()` 和 `max()`。 Sass 会尽可能地简化这些,即使它们是相互结合的。

计算是 Sass 如何表示 calc() 函数,以及类似的函数,如 clamp()min()max()。 Sass 会尽可能地简化这些,即使它们是相互结合的。

兼容性: Dart Sass since 1.40.0 | LibSass ✗ | Ruby Sass ✗

LibSass、Ruby Sass 和 Dart Sass 1.40.0 之前的版本将 calc() 解析为像 element() 一样的特殊函数。
LibSass、Ruby Sass 和 Dart Sass 1.31.0 之前的版本将 clamp() 解析为纯 CSS 函数,而不是在其中支持特殊语法。 1.31.0 和 1.40.0 之间的 Dart Sass 版本将 clamp() 解析为像 element() 一样的特殊函数。

scss
Scss
scss
@debug calc(400px + 10%); // calc(400px + 10%)
@debug calc(400px / 2); // 200px
@debug min(100px, calc(1rem + 10%)); // min(100px, 1rem + 10%)

计算使用不同于普通 SassScript 的特殊语法。 它的语法与 CSS calc() 相同,但具有使用 Sass 变量 和调用 Sass 函数 的附加功能。 这意味着 / 始终是计算中的除法运算符!

💡 有趣的事实:

Sass 函数调用的参数使用普通的 Sass 语法,而不是特殊的计算语法!

您还可以在计算中使用 interpolation。 但是,如果您这样做,插值周围的括号中的任何内容都不会被简化或进行类型检查,因此很容易导致额外冗长甚至无效的 CSS。 与其写 calc(10px + #{$var}),不如写 calc(10px + $var)

简化

如果 Sass 使用可以在编译时组合的单位,例如 1in + 10px5s * 2,Sass 将简化计算中的相邻操作。 如果可能,它甚至会将整个计算简化为一个数字——例如,clamp(0px, 30px, 20px) 将返回 20px

⚠️ 注意!

这意味着计算表达式不一定总是返回计算! 如果您正在编写 Sass 库,您始终可以使用 meta.type-of() 函数来确定您正在处理的类型。

计算也将在其他计算中得到简化。 特别是,如果 calc() 最终出现在任何其他计算中,函数调用将被删除,并将被一个普通的旧操作所取代。

scss
Scss
scss
$width: calc(400px + 10%);

.sidebar {
  width: $width;
  padding-left: calc($width / 4);
}

操作

您不能将计算与正常的 SassScript 操作一起使用,例如 +*。 如果您想编写一些允许计算的数学函数,只需将它们写在它们自己的 calc() 表达式中——如果它们传递了一堆具有兼容单位的数字,它们也会返回纯数字,如果它们 重新通过计算,他们将返回计算。

实施此限制是为了确保如果不需要计算,它们会尽快抛出错误。 计算不能用在纯数字可以用的所有地方:例如,它们不能注入 CSS 标识符(例如 .item-#{$n}`),也不能传递给 Sass 的内置 数学函数。 为纯数字保留 SassScript 操作可以明确哪些地方允许计算,哪些地方不允许。

scss
Scss
scss
$width: calc(100% + 10px);
@debug $width * 2; // Error!
@debug calc($width * 2); // calc((100% + 10px) * 2);

常量

Compatibility: Dart Sass since 1.60.0 | LibSass ✗ | Ruby Sass ✗

计算还可以包含常量,这些常量被写为 CSS 标识符。 为了与未来的 CSS 规范向前兼容,all 标识符是允许的,默认情况下它们只是被视为按原样传递的不带引号的字符串。

scss
Scss
scss
@debug calc(h + 30deg); // calc(h + 30deg);

Sass 自动将 CSS 中指定的一些特殊常量名称解析为无单位数字:

scss
Scss
scss
@use 'sass:math';

@debug calc(pi); // 3.1415926536
@debug calc(e);  // 2.7182818285
@debug calc(infinity) > math.$max-number;  // true
@debug calc(-infinity) < math.$min-number; // true

min() and max()

兼容性(特殊函数语法): Dart Sass since >=1.11.0 <1.42.0 | LibSass ✗ | Ruby Sass ✗ LibSass、Ruby Sass 和 Dart Sass 1.11.0 之前的版本总是将 min() 和 max() 解析为 Sass 函数。 要为这些实现创建纯 CSS min() 或 max() 调用,您可以改为编写类似 unquote("min(#{$padding}, env(safe-area-inset-left))") 的内容。

1.11.0 和 1.40.0 之间以及 1.40.1 和 1.42.0 之间的 Dart Sass 版本将 min() 和 max() 函数解析为特殊函数,如果它们是有效的纯 CSS,但将它们解析为 Sass 函数,如果它们 包含插值以外的 Sass 特性,如变量或函数调用。

Dart Sass 1.41.0 将 min() 和 max() 函数解析为计算,但不允许无单位数字与带单位的数字组合。 这与全局 min() 和 max() 函数向后不兼容,因此该行为已恢复。

CSS 在值和单位第 4 级中添加了对 min()max() 函数 的支持,从那里开始 很快被 Safari 采用 以支持 iPhoneX。 但是 Sass 早在这之前就支持自己的 min()max() 函数,并且 它需要向后兼容所有那些现有的样式表。 这导致需要特别的句法技巧。

如果 min()max() 函数调用是有效的计算表达式,它将被解析为计算。 但是只要调用的任何部分包含计算中不支持的 SassScript 功能,例如 modulo operator,它就会被解析为对 Sass 核心 min( )max() 函数代替。

由于无论如何都尽可能将计算简化为数字,唯一实质性的区别是 Sass 函数仅支持可以在构建时组合的单位,因此 min(12px % 10, 10%) 会抛出错误。

⚠️ 注意!

其他计算不允许无单位数字与有单位的数字相加、相减或比较。 但是,min()max() 是不同的:为了向后兼容全局 Sass min()max() 函数,由于历史原因允许单位/无单位混合,这些单位可以是 混合,只要它们直接包含在 min()max() 计算中。

scss
Scss
scss
$padding: 12px;

.post {
  // Since these max() calls are valid calculation expressions, they're
  // parsed as calculations.
  padding-left: max($padding, env(safe-area-inset-left));
  padding-right: max($padding, env(safe-area-inset-right));
}

.sidebar {
  // Since these use the SassScript-only modulo operator, they're parsed as
  // SassScript function calls.
  padding-left: max($padding % 10, 20px);
  padding-right: max($padding % 10, 20px);
}