计算
计算是 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 和 1.31.0 之前的 Dart Sass 版本将 clamp()
解析为普通 CSS 函数,而不支持其内部的特殊语法。1.31.0 到 1.40.0 之间的 Dart Sass 版本将 clamp()
解析为特殊函数,类似于 element()
。
- 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
)。
从 Dart Sass 1.67.0 开始,只要每个其他值都计算为无引号字符串(如 var()
表达式或无引号字符串 "+ 2"
),计算中的多个值就可以用空格分隔。
SCSS Syntax
@debug calc(400px + 10%); // calc(400px + 10%)
@debug calc(400px / 2); // 200px
@debug min(100px, calc(1rem + 10%)); // min(100px, 1rem + 10%)
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 函数。这意味着在计算中 /
始终是除法运算符!
💡 Fun fact:
Sass 函数调用的参数使用普通 Sass 语法,而不是特殊的计算语法!
你还可以在计算中使用插值。但是,如果这样做,涉及该插值的任何操作都不会被简化或类型检查,因此很容易得到冗长甚至无效的 CSS。与其写 calc(10px + #{$var})
,不如直接写 calc(10px + $var)
!
简化简化 permalink
如果计算中的相邻操作使用可以在编译时组合的单位(如 1in + 10px
或 5s * 2
),Sass 将简化它们。如果可能,它甚至会将整个计算简化为单个数字——例如,clamp(0px, 30px, 20px)
将返回 20px
。
⚠️ Heads up!
这意味着计算表达式不一定总是返回计算!如果你正在编写 Sass 库,你可以始终使用 meta.type-of()
函数来确定你正在处理的类型。
计算也会在其他计算中被简化。特别是,如果 calc()
最终出现在任何其他计算中,函数调用将被移除,并替换为普通的操作。
SCSS Syntax
$width: calc(400px + 10%);
.sidebar {
width: $width;
padding-left: calc($width / 4);
}
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
你不能将计算与普通 SassScript 操作(如 +
和 *
)一起使用。如果你想编写一些允许计算的数学函数,只需在它们自己的 calc()
表达式中编写——如果传入的是具有兼容单位的数字,它们将返回普通数字,如果传入计算,它们将返回计算。
这个限制是为了确保如果不需要计算,就尽快抛出错误。计算不能在普通数字可以使用的所有地方使用:例如,它们不能注入到 CSS 标识符中(如 .item-#{$n}
),也不能传递给 Sass 的内置数学函数。保留 SassScript 操作用于普通数字,可以清楚地说明允许计算的位置和不允许的位置。
SCSS Syntax
$width: calc(100% + 10px);
@debug $width * 2; // 错误!
@debug calc($width * 2); // calc((100% + 10px) * 2);
Sass Syntax
$width: calc(100% + 10px);
@debug $width * 2; // 错误!
@debug calc($width * 2); // calc((100% + 10px) * 2);
常量常量 permalink
- Dart Sass
- since 1.60.0
- LibSass
- ✗
- Ruby Sass
- ✗
计算还可以包含常量,它们被写作 CSS 标识符。为了与未来的 CSS 规范向前兼容,所有标识符都是允许的,默认情况下它们只是被视为原样传递的无引号字符串。
Sass 自动解析 CSS 中指定的几个特殊常量名称为无单位数字:
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
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
- Dart Sass
- since 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 将以下函数解析为计算:
- 比较函数:
min()
、max()
和clamp()
- 步进值函数:
round()
、mod()
和rem()
。 - 三角函数:
sin()
、cos()
、tan()
、asin()
、acos()
、atan()
和atan2()
。 - 指数函数:
pow()
、sqrt()
、hypot()
、log()
和exp()
。 - 符号相关函数:
abs()
和sign()
。
💡 Fun fact:
如果你定义了一个与计算函数同名的 Sass 函数,Sass 将始终调用你的函数,而不是创建计算值。
传统全局函数传统全局函数 permalink
CSS 在值和单位 4 级中添加了对数学表达式的支持。然而,Sass 早在此之前就支持了自己的 round()
、abs()
、min()
和 max()
,并且需要与所有现有的样式表向后兼容。这导致了需要额外特殊的语法技巧。
如果对 round()
、abs()
、min()
或 max()
的调用是有效的计算表达式,它将被解析为计算。但是,一旦调用的任何部分包含计算中不支持的 SassScript 特性(如模运算符),它就会被解析为对相应 Sass 数学函数的调用。
由于计算无论如何都会在可能的情况下简化为数字,唯一实质性的区别是 Sass 函数只支持可以在构建时组合的单位,因此 min(12px % 10, 10%)
将抛出错误。
⚠️ Heads up!
其他计算不允许将无单位数字添加到、减去或比较到具有单位的数字。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() permalink
- 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))")
而不是。
CSS 在值和单位 4 级中添加了对 min()
和 max()
函数 的支持,从那里 Safari 为支持 iPhoneX 迅速采用了它们。由于我们已经支持 min()
和 max()
作为遗留 Sass 函数,我们需要实现逻辑以进行向后兼容并支持作为 CSS 函数。
版本在 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()
函数,因此行为被还原。
SCSS Syntax
$padding: 12px;
.post {
// 由于这些 max() 调用是有效的计算表达式,它们被解析为计算。
padding-left: max($padding, env(safe-area-inset-left));
padding-right: max($padding, env(safe-area-inset-right));
}
.sidebar {
// 由于这些使用 SassScript 唯一的模运算符,它们被解析为 SassScript 函数调用。
padding-left: max($padding % 10, 20px);
padding-right: max($padding % 10, 20px);
}
Sass Syntax
$padding: 12px
.post
// 由于这些 max() 调用是有效的计算表达式,它们被解析为计算。
padding-left: max($padding, env(safe-area-inset-left))
padding-right: max($padding, env(safe-area-inset-right))
.sidebar
// 由于这些使用 SassScript 唯一的模运算符,它们被解析为 SassScript 函数调用。
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
- 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})
而不是。
round(<strategy>, number, step)
函数接受可选的舍入策略、要舍入的值和舍入间隔 step
。strategy
应该为 nearest
、up
、down
或 to-zero
。
SCSS Syntax
$number: 12.5px;
$step: 15px;
.post-image {
// 由于这些 round() 调用是有效的计算表达式,它们被解析为计算。
padding-left: round(nearest, $number, $step);
padding-right: round($number + 10px);
padding-bottom: round($number + 10px, $step + 10%);
}
Sass Syntax
$number: 12.5px
$step: 15px
.post-image
// 由于这些 round() 调用是有效的计算表达式,它们被解析为计算。
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
- Dart Sass
- since 1.67.0
- LibSass
- ✗
- Ruby Sass
- ✗
LibSass、Ruby Sass 和 1.67.0 之前的 Dart Sass 版本 总是 将 abs()
解析为 Sass 函数。要为那些实现创建一个普通的 CSS 计算,你可以写 abs(#{$number})
而不是。
⚠️ Heads up!
全球 abs()
函数与 [% 单位参数的兼容性已弃用]。在将来,这将发出一个 CSS abs() 函数以供浏览器解析。
abs(value)
接受单个表达式作为参数并返回 $value
的绝对值。如果 $value
为负,则返回 -$value
,如果 $value
为正,则返回 $value
作为。
SCSS Syntax
.post-image {
// 由于这些 abs() 调用是有效的计算表达式,它们被解析为计算。
padding-left: abs(10px);
padding-right: math.abs(-7.5%);
padding-top: abs(1 + 1px);
}
Sass Syntax
.post-image
// 由于这些 abs() 调用是有效的计算表达式,它们被解析为计算。
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;
}