计算

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

兼容性:
Dart Sass
since 1.40.0
LibSass
Ruby Sass

LibSass、Ruby Sass 和 1.40.0 之前的 Dart Sass 版本将 calc() 解析为 特殊功能,就像 element() 一样。

¥LibSass, Ruby Sass, and versions of Dart Sass prior to 1.40.0 parse calc() as a special function like element().

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

¥LibSass, Ruby Sass, and versions of Dart Sass prior to 1.31.0 parse clamp() as a plain CSS function rather than supporting special syntax within it. Versions of Dart Sass between 1.31.0 and 1.40.0 parse clamp() as a special function like element().

兼容性 (Adjacent values):
Dart Sass
since 1.67.0
LibSass
Ruby Sass

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

¥Versions of Dart Sass between 1.40.0 and 1.67.0 don’t allow multiple values in calculations that aren’t separated by an operator, even in cases like calc(1 var(--plus-two)) which is valid CSS (since --plus-two can be defined to be + 2).

从 Dart Sass 1.67.0 开始,计算中的多个值可以用空格分隔,只要每个其他值的计算结果都是不带引号的字符串(例如 var() 表达式或不带引号的字符串 "+ 2")。

¥As of Dart Sass 1.67.0, multiple values in a calculation can be separated by spaces as long as every other value evaluates to an unquoted string (such as a var() expression or the unquoted string "+ 2").

Playground

SCSS Syntax

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

Sass Syntax

@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 函数 的附加功能。这意味着 / 始终是计算中的除法运算符!

¥Calculations use a special syntax that’s different from normal SassScript. It’s the same syntax as the CSS calc(), but with the additional ability to use Sass variables and call Sass functions. This means that / is always a division operator within a calculation!

💡 Fun fact:

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

¥The arguments to a Sass function call use the normal Sass syntax, rather than the special calculation syntax!

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

¥You can also use interpolation in a calculation. However, if you do, no operations that involve that interpolation will be simplified or type-checked, so it’s easy to end up with extra verbose or even invalid CSS. Rather than writing calc(10px + #{$var}), just write calc(10px + $var)!

简化简化 permalink

¥Simplification

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

¥Sass will simplify adjacent operations in calculations if they use units that can be combined at compile-time, such as 1in + 10px or 5s * 2. If possible, it’ll even simplify the whole calculation to a single number—for example, clamp(0px, 30px, 20px) will return 20px.

⚠️ Heads up!

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

¥This means that a calculation expression won’t necessarily always return a calculation! If you’re writing a Sass library, you can always use the meta.type-of() function to determine what type you’re dealing with.

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

¥Calculations will also be simplified within other calculations. In particular, if a calc() end up inside any other calculation, the function call will be removed and it’ll be replaced by a plain old operation.

Playground

SCSS Syntax

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

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

Sass Syntax

$width: calc(400px + 10%)

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

CSS Output

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


运算运算 permalink

¥Operations

你不能使用常规 SassScript 操作(如 +*)进行计算。如果你想编写一些允许计算的数学函数,只需将它们写在它们自己的 calc() 表达式中 - 如果它们 ’重新传递了一堆具有兼容单位的数字,它们也会返回普通数字,如果它们’ 通过计算,它们将返回计算结果。

¥You can’t use calculations with normal SassScript operations like + and *. If you want to write some math functions that allow calculations just write them within their own calc() expressions—if they’re passed a bunch of numbers with compatible units, they’ll return plain numbers as well, and if they’re passed calculations they’ll return calculations.

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

¥This restriction is in place to make sure that if calculations aren’t wanted, they throw an error as soon as possible. Calculations can’t be used everywhere plain numbers can: they can’t be injected into CSS identifiers (such as .item-#{$n}), for example, and they can’t be passed to Sass’s built-in math functions. Reserving SassScript operations for plain numbers makes it clear exactly where calculations are allowed and where they aren’t.

Playground

SCSS Syntax

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

Sass Syntax

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

常量常量 permalink

¥Constants

兼容性:
Dart Sass
since 1.60.0
LibSass
Ruby Sass

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

¥Calculations can also contain constants, which are written as CSS identifiers. For forwards-compatibility with future CSS specs, all identifiers are allowed, and by default they’re just treated as unquoted strings that are passed-through as-is.

Playground

SCSS Syntax

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

Sass Syntax

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

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

¥Sass automatically resolves a few special constant names that are specified in CSS to unitless numbers:

Playground

SCSS Syntax

@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
Playground

Sass Syntax

@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

计算函数计算函数 permalink

¥Calculation Functions

兼容性 (Additional functions):
Dart Sass
since 1.65.0
LibSass
Ruby Sass

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

¥Versions of Dart Sass 1.65.0 and later except 1.66.x handle the execution of these calculation functions: round(), mod(), rem(), sin(), cos(), tan(), asin(), acos(), atan(), atan2(), pow(), sqrt(), hypot(), log(), exp(), abs(), and sign().

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

¥In Dart Sass 1.65.x, any function call whose name matched a calculation function was always parsed as a calculation function. This broke some existing user-defined functions, so support for the new calculation functions was removed in 1.66.0 until it could be added back without breaking existing behavior in 1.67.0.

Sass 将以下函数解析为 calculations

¥Sass parses the following functions as calculations:

💡 Fun fact:

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

¥If you’ve defined a Sass function with the same name as a calculation function, Sass will always call your function instead of creating a calculation value.

旧版全局函数旧版全局函数 permalink

¥Legacy Global Functions

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

¥CSS added support for mathematical expressions in Values and Units Level 4. However, Sass supported its own round(), abs(), min() and max() long before this, and it needed to be backwards-compatible with all those existing stylesheets. This led to the need for extra-special syntactic cleverness.

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

¥If a call to round(), abs(), min(), or max() is a valid calculation expression, it will be parsed as a calculation. But as soon as any part of the call contains a SassScript feature that isn’t supported in a calculation, like the modulo operator, it’s parsed as a call to the appropriate Sass math function instead.

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

¥Since calculations are simplified to numbers when possible anyway, the only substantive difference is that the Sass functions only support units that can be combined at build time, so min(12px % 10, 10%) will throw an error.

⚠️ Heads up!

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

¥Other calculations don’t allow unitless numbers to be added to, subtracted from, or compared to numbers with units. min(), max(), abs() and single-argument round() are different, though: for backwards-compatibility with the global Sass legacy functions which allow unit/unitless mixing for historical reasons, these units can be mixed as long as they’re contained directly within a min(), max(), abs(), or single-argument round() calculation.

例如,min(5 + 10px, 20px) 将导致 15px。然而 sqrt(5 + 10px) 会抛出错误,因为 sqrt(5 + 10px) 从来都不是全局 Sass 函数,并且这些是不兼容的单元。

¥For instance, min(5 + 10px, 20px) will result in 15px. However sqrt(5 + 10px) will throw an error, as sqrt(5 + 10px) was never a global Sass function, and these are incompatible units.

min()max()min() 和 max() permalink

¥min() and max()

兼容性 (min and max syntax):
Dart Sass
since >=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))") 的内容。

¥LibSass, Ruby Sass, and versions of Dart Sass prior to 1.11.0 always parse min() and max() as Sass functions. To create a plain CSS min() or max() call for those implementations, you can write something like unquote("min(#{$padding}, env(safe-area-inset-left))") instead.

CSS 在值和单位级别 4 中添加了对 min()max() 功能 的支持,并很快被 Safari 支持 iPhoneX 采用。由于我们已经支持 min()max() 作为旧版 Sass 函数,因此我们必须实现向后兼容并支持 CSS 函数的逻辑。

¥CSS added support for min() and max() functions in Values and Units Level 4, from where they were quickly adopted by Safari to support the iPhoneX. Since we already supported min() and max() as legacy Sass functions, we had to implement logic for backwards-compatibility and for support as CSS functions.

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

¥Versions of Dart Sass between 1.11.0 and 1.40.0, and between 1.40.1 and 1.42.0 parse min() and max() functions as special functions if they’re valid plain CSS, but parse them as Sass functions if they contain Sass features other than interpolation, like variables or function calls.

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

¥Dart Sass 1.41.0 parses min() and max() functions as calculations, but doesn’t allow unitless numbers to be combined with numbers with units. This was backwards-incompatible with the global min() and max() functions, so that behavior was reverted.

Playground

SCSS Syntax

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

Sass Syntax

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

.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() permalink

兼容性 (min and max syntax):
Dart Sass
since 1.65.0
LibSass
Ruby Sass

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

¥LibSass, Ruby Sass, and versions of Dart Sass prior to 1.65.0, as well as Dart Sass 1.66.x, always parse round() as a Sass function. To use a plain CSS function for those implementations, you can write something like round(#{$strategy, $number, $step}) instead.

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

¥The round(<strategy>, number, step) function accepts an optional rounding strategy, a value to be rounded and a rounding interval step. strategy should be nearest, up, down, or to-zero.

Playground

SCSS Syntax

$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%);
}
Playground

Sass Syntax

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

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





abs()abs() permalink

兼容性 (min and max syntax):
Dart Sass
since 1.67.0
LibSass
Ruby Sass

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

¥LibSass, Ruby Sass, and versions of Dart Sass prior to 1.67.0 always parse abs() as a Sass function. To create a plain CSS calculation for those implementations, you can write something like abs(#{$number}) instead.

⚠️ Heads up!

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

¥The global abs() function compatibiliy with % unit parameters is deprecated. In the future, this will emit a CSS abs() function to be resolved by the browser.

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

¥The abs(value) takes in a single expressiona as a parameter and returns the absolute value of $value. If $value is negative, this returns -$value, and if $value is positive, it returns $value as-is.

Playground

SCSS Syntax

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

Sass Syntax

.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 Output

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