计算

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

兼容性
Dart Sass
自 1.40.0 起
LibSass
Ruby Sass

LibSass、Ruby Sass 和 1.40.0 之前的 Dart Sass 版本将 calc() 解析为一个类似于 element()特殊函数

LibSass、Ruby Sass 和 1.31.0 之前的 Dart Sass 版本将 clamp() 解析为一个普通 CSS 函数,而不是支持其中的特殊语法。1.31.0 到 1.40.0 之间的 Dart Sass 版本将 clamp() 解析为一个类似于 element()特殊函数

兼容性(相邻值)
Dart Sass
自 1.67.0 起
LibSass
Ruby Sass

1.40.0 到 1.67.0 之间的 Dart Sass 版本不允许计算中存在多个未用运算符分隔的值,即使在 calc(1 var(--plus-two)) 等有效 CSS(因为 --plus-two 可以定义为 + 2)的情况下也是如此。

从 Dart Sass 1.67.0 开始,只要其他值计算为未引用的字符串(例如 var() 表达式或未引用的字符串 "+ 2"),计算中的多个值就可以用空格分隔。

游乐场

SCSS 语法

@debug calc(400px + 10%); // calc(400px + 10%)
@debug calc(400px / 2); // 200px
@debug min(100px, calc(1rem + 10%)); // min(100px, 1rem + 10%)
游乐场

Sass 语法

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

计算使用一种与普通 SassScript 不同的特殊语法。它与 CSScalc() 语法相同,但增加了使用Sass 变量 和调用Sass 函数 的功能。这意味着 / 在计算中始终是除法运算符!

💡 趣事

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

你也可以在计算中使用插值。但是,如果你这样做,任何涉及该插值的运算都不会被简化或类型检查,因此很容易导致额外的冗长代码甚至无效的 CSS。与其编写 calc(10px + #{$var}),不如直接编写 calc(10px + $var)

简化简化永久链接

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

⚠️ 注意!

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

计算也会在其他计算中被简化。特别是,如果 calc() 位于任何其他计算中,函数调用会被移除并用一个普通的运算符替换。

游乐场

SCSS 语法

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

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

Sass 语法

$width: calc(400px + 10%)

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

CSS 输出

.sidebar {
  width: calc(400px + 10%);
  padding-left: calc((400px + 10%) / 4);
}


运算运算永久链接

你不能将计算与普通 SassScript 运算符(如 +*)一起使用。如果你想编写一些允许计算的数学函数,只需在它们自己的 calc() 表达式中编写它们,如果它们传递了一组具有兼容单位的数字,它们也会返回普通数字;如果它们传递了计算,它们也会返回计算。

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

游乐场

SCSS 语法

$width: calc(100% + 10px);
@debug $width * 2; // Error!
@debug calc($width * 2); // calc((100% + 10px) * 2);
游乐场

Sass 语法

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

常量常量永久链接

兼容性
Dart Sass
自 1.60.0 起
LibSass
Ruby Sass

计算也可以包含常量,常量以 CSS 标识符的形式编写。为了与未来的 CSS 规范向前兼容,所有标识符都是允许的,默认情况下它们会被简单地视为直接传递的未引用的字符串。

游乐场

SCSS 语法

@debug calc(h + 30deg); // calc(h + 30deg);
游乐场

Sass 语法

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

Sass 自动解析在 CSS 中指定的几个特殊常量名称,解析为无单位数字。

游乐场

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
游乐场

Sass 语法

@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

计算函数计算函数永久链接

兼容性(附加函数)
Dart Sass
自 1.65.0 起
LibSass
Ruby Sass

1.65.0 及更高版本的 Dart Sass(除了 1.66.x)处理以下计算函数的执行:round()mod()rem()sin()cos()tan()asin()acos()atan()atan2()pow()sqrt()hypot()log()exp()abs()sign()

在 Dart Sass 1.65.x 中,任何名称与计算函数匹配的函数调用始终被解析为计算函数。这破坏了一些现有的用户定义函数,因此对新计算函数的支持在 1.66.0 中被移除,直到它可以破坏 1.67.0 中现有的行为而重新添加。

Sass 将以下函数解析为计算

💡 趣事

如果你已经定义了一个与计算函数同名的Sass 函数,Sass 将始终调用你的函数,而不是创建计算值。

旧版全局函数旧版全局函数永久链接

CSS 在值和单位级别 4 中添加了对数学表达式 的支持。但是,Sass 在此之前很久就支持自己的round()abs()min()max(),它需要向后兼容所有这些现有的样式表。这导致需要额外的语法技巧。

如果对 round()abs()min()max() 的调用是一个有效的计算表达式,它将被解析为计算。但一旦调用中的任何部分包含 SassScript 中不支持计算的功能(例如取模运算符),它就会被解析为对相应 Sass 数学函数的调用。

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

⚠️ 注意!

其他计算不允许无单位数字加到、减去或与带单位的数字进行比较。但是,min()max()abs()单参数 round() 不同:为了向后兼容全局 Sass 旧版函数(这些函数由于历史原因允许单位/无单位混合),只要这些单位直接位于 min()max()abs() 或单参数 round() 计算中,就可以混合使用。

例如,min(5 + 10px, 20px) 会生成 15px。但是 sqrt(5 + 10px) 会抛出错误,因为 sqrt(5 + 10px) 从来不是全局 Sass 函数,而且这些单位不兼容。

min()max()min() 和 max() 永久链接

兼容性(min 和 max 语法)
Dart Sass
自 >=1.11.0 <1.42.0 起
LibSass
Ruby Sass

LibSass、Ruby Sass 和 1.11.0 之前的 Dart Sass 版本始终min()max() 解析为 Sass 函数。为了为这些实现创建普通的 CSS min()max() 调用,你可以编写类似于 unquote("min(#{$padding}, env(safe-area-inset-left))") 的内容。

CSS 在 Values and Units Level 4 中添加了对 min()max() 函数 的支持,随后 Safari 很快便 为了支持 iPhoneX 而采用了这些函数。由于我们已经支持 min()max() 作为传统的 Sass 函数,因此我们必须实现向后兼容的逻辑,并支持它们作为 CSS 函数。

Dart Sass 1.11.0 到 1.40.0 版本,以及 1.40.1 到 1.42.0 版本,如果 min()max() 函数是有效的纯 CSS,则将其解析为 特殊函数;但如果这些函数包含除插值以外的 Sass 特性(如变量或函数 调用),则将其解析为 Sass 函数。

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

游乐场

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);
}
游乐场

Sass 语法

$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)

CSS 输出

.post {
  padding-left: max(12px, env(safe-area-inset-left));
  padding-right: max(12px, env(safe-area-inset-right));
}

.sidebar {
  padding-left: 20px;
  padding-right: 20px;
}






round()round() 永久链接

兼容性(min 和 max 语法)
Dart Sass
自 1.65.0 起
LibSass
Ruby Sass

LibSass、Ruby Sass 和 Dart Sass 1.65.0 之前的版本,以及 Dart Sass 1.66.x 版本,始终round() 解析为 Sass 函数。要对这些实现使用纯 CSS 函数,你可以编写类似 round(#{$strategy, $number, $step}) 的内容。

round(<strategy>, number, step) 函数接受可选的舍入策略、要舍入的值和舍入间隔 stepstrategy 应该为 nearestupdownto-zero

游乐场

SCSS 语法

$number: 12.5px;
$step: 15px;

.post-image {
  // Since these round() calls are valid calculation expressions, they're
  // parsed as calculations.
  padding-left: round(nearest, $number, $step);
  padding-right: round($number + 10px);
  padding-bottom: round($number + 10px, $step + 10%);
}
游乐场

Sass 语法

$number: 12.5px
$step: 15px

.post-image
  // Since these round() calls are valid calculation expressions, they're
  // parsed as calculations.
  padding-left: round(nearest, $number, $step)
  padding-right: round($number + 10px)
  padding-bottom: round($number + 10px, $step + 10%)

CSS 输出

.post-image {
  padding-left: 15px;
  padding-right: 23px;
  padding-bottom: round(22.5px, 15px + 10%);
}





abs()abs() 永久链接

兼容性(min 和 max 语法)
Dart Sass
自 1.67.0 起
LibSass
Ruby Sass

LibSass、Ruby Sass 和 Dart Sass 1.67.0 之前的版本,始终abs() 解析为 Sass 函数。要为这些实现创建纯 CSS 计算,你可以编写类似 abs(#{$number}) 的内容。

⚠️ 注意!

全局 abs() 函数与 % 单位参数的兼容性已弃用。将来,这将生成一个 CSS abs() 函数,由 浏览器解析。

abs(value) 函数接受单个表达式作为参数,并返回 $value 的绝对值。如果 $value 为负,则返回 -$value;如果 $value 为正,则按原样返回 $value

游乐场

SCSS 语法

.post-image {
  // Since these abs() calls are valid calculation expressions, they're
  // parsed as calculations.
  padding-left: abs(10px);
  padding-right: math.abs(-7.5%);
  padding-top: abs(1 + 1px);
}
游乐场

Sass 语法

.post-image
  // Since these abs() calls are valid calculation expressions, they're
  // parsed as calculations.
  padding-left: abs(-10px)
  padding-right: math.abs(-7.5%)
  padding-top: abs(1 + 1px)

CSS 输出

.post-image {
  padding-left: 10px;
  padding-right: 7.5%;
  padding-top: 2px;
}