说明:参照官方文档部分翻译记录,许多解释性的文字没有翻译记录,只需看示例即可(2022-11-25);示例形式为上半部分为sass代码,下面为转换过后的css代码
style rules
在 Sass 和 CSS 中,属性声明定义与选择器匹配的元素的样式。但是 Sass 增加了额外的功能,使它们更容易编写和自动化。首先,声明的值可以是任何 SassScript 表达式,它将被计算并包含在结果中。
.circle {
$size: 100px;
width: $size;
height: $size;
border-radius: $size * 0.5;
}
CSS OUTPUT 输出
.circle {
width: 100px;
height: 100px;
border-radius: 50px;
}
插值
属性的名称可以包含插值,这使得根据需要动态生成属性成为可能。您甚至可以插入整个属性名!
@mixin prefix($property, $value, $prefixes) {
@each $prefix in $prefixes {
-#{$prefix}-#{$property}: $value;
}
#{$property}: $value;
}
.gray {
@include prefix(filter, grayscale(50%), moz webkit);
}
CSS OUTPUT 输出
.gray {
-moz-filter: grayscale(50%);
-webkit-filter: grayscale(50%);
filter: grayscale(50%);
}
嵌套
许多 CSS 属性都以作为一种名称空间的相同前缀开始。例如,font-family、 font-size 和 font-weight 都以 font-开头。通过允许嵌套属性声明,Sass 使得这个过程更加容易,也不那么多余。外部属性名称添加到内部,用连字符分隔。
.enlarge {
font-size: 14px;
transition: {
property: font-size;
duration: 4s;
delay: 2s;
}
&:hover { font-size: 36px; }
}
.enlarge {
font-size: 14px;
transition-property: font-size;
transition-duration: 4s;
transition-delay: 2s;
}
.enlarge:hover {
font-size: 36px;
}
其中一些 CSS 属性有使用命名空间作为属性名的简写版本。对于这些,您可以编写速记值和更显式的嵌套版本。
.info-page {
margin: auto {
bottom: 10px;
top: 2px;
}
}
.info-page {
margin: auto;
margin-bottom: 10px;
margin-top: 2px;
}
Hidden Declarations 隐藏声明
有时您只希望在某些时候显示属性声明。如果一个声明的值为 null 或一个空的无引号字符串,Sass 根本不会将该声明编译成 CSS。
$rounded-corners: false;
.button {
border: 1px solid black;
border-radius: if($rounded-corners, 5px, null);
}
.button {
border: 1px solid black;
}
Custom Properties(css变量)
CSS 自定义属性,也称为 CSS 变量,有一个不同寻常的声明语法: 它们在声明值中允许几乎任何文本。而且,JavaScript 可以访问这些值,因此任何值都可能与用户相关。这包括通常将被解析为 SassScript 的值。
因此,Sass 对自定义属性声明的解析与其他属性声明的解析不同。所有的标记,包括那些看起来像 SassScript 的标记,都按原样传递给 CSS。唯一的例外是插值,这是将动态值注入到自定义属性中的唯一方法。
$primary: #81899b;
$accent: #302e24;
$warn: #dfa612;
:root {
--primary: #{$primary};
--accent: #{$accent};
--warn: #{$warn};
// Even though this looks like a Sass variable, it's valid CSS so it's not
// evaluated.
--consumed-by-js: $primary;
}
:root {
--primary: #81899b;
--accent: #302e24;
--warn: #dfa612;
--consumed-by-js: $primary;
}
父级选择
当在内部选择器中使用父选择器时,它将被替换为相应的外部选择器。这代替了正常的嵌套行为。
.alert {
// The parent selector can be used to add pseudo-classes to the outer
// selector.
&:hover {
font-weight: bold;
}
// It can also be used to style the outer selector in a certain context, such
// as a body set to use a right-to-left language.
[dir=rtl] & {
margin-left: 0;
margin-right: 10px;
}
// You can even use it as an argument to pseudo-class selectors.
:not(&) {
opacity: 0.8;
}
}
.alert:hover {
font-weight: bold;
}
[dir=rtl] .alert {
margin-left: 0;
margin-right: 10px;
}
:not(.alert) {
opacity: 0.8;
}
因为父选择器可以被类型选择器(如 h1)替换,所以只允许在复合选择器的开头部分使用它,而类型选择器也是允许的。例如,span & 是不允许的。
在sass script中使用&
父选择器也可以在 SassScript 中使用。它是一个特殊的表达式,以选择器函数所使用的相同格式返回当前的父选择器: 逗号分隔的列表(选择器列表) ,其中包含空格分隔的列表(复合选择器) ,其中包含未加引号的字符串(复合选择器)。
如果 & 表达式在任何样式规则之外使用,则返回 null。由于 null 是 false,这意味着您可以很容易地使用它来确定是否在样式规则中调用混合。
@mixin app-background($color) {
#{if(&, '&.app-background', '.app-background')} {
background-color: $color;
color: rgba(#fff, 0.75);
}
}
@include app-background(#036);
.sidebar {
@include app-background(#c6538c);
}
.app-background {
background-color: #036;
color: rgba(255, 255, 255, 0.75);
}
.sidebar.app-background {
background-color: #c6538c;
color: rgba(255, 255, 255, 0.75);
}
Placeholder Selectors
%toolbelt {
box-sizing: border-box;
border-top: 1px rgba(#000, .12) solid;
padding: 16px 0;
width: 100%;
&:hover { border: 2px rgba(#000, .5) solid; }
}
.action-buttons {
@extend %toolbelt;
color: #4285f4;
}
.reset-buttons {
@extend %toolbelt;
color: #cddc39;
}
.action-buttons, .reset-buttons {
box-sizing: border-box;
border-top: 1px rgba(0, 0, 0, 0.12) solid;
padding: 16px 0;
width: 100%;
}
.action-buttons:hover, .reset-buttons:hover {
border: 2px rgba(0, 0, 0, 0.5) solid;
}
.action-buttons {
color: #4285f4;
}
.reset-buttons {
color: #cddc39;
}
变量
sass变量使用$声明
SCSS SYNTAX 语法
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);
.alert {
border: 1px solid $border-dark;
}
CSS OUTPUT 输出
.alert {
border: 1px solid rgba(198, 83, 140, 0.88);
}
默认值
使用!default来标识一个值为默认值,这通常在模块中使用,在使用@use引入模块时可以配置默认值
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
code {
border-radius: $border-radius;
box-shadow: $box-shadow;
}
// style.scss
@use 'library' with (
$black: #222,
$border-radius: 0.1rem
);
Flow Control Scope 流量控制范围
在流控制规则中声明的变量具有特殊的范围规则: 它们不会在与流控制规则相同的级别上隐藏变量。相反,他们只是赋值给这些变量。这使得有条件地为变量赋值或将值作为循环的一部分构建起来变得更加容易。
$dark-theme: true !default;
$primary-color: #f8bbd0 !default;
$accent-color: #6a1b9a !default;
@if $dark-theme {
$primary-color: darken($primary-color, 60%);
$accent-color: lighten($accent-color, 60%);
}
.button {
background-color: $primary-color;
border: 1px solid $accent-color;
border-radius: 3px;
}
Advanced Variable Functions 高级变量函数
@use "sass:map";
$theme-colors: (
"success": #28a745,
"info": #17a2b8,
"warning": #ffc107,
);
.alert {
// Instead of $theme-color-#{warning}
background-color: map.get($theme-colors, "warning");
}
插值
使用#{}
@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
.icon-#{$name} {
background-image: url("/icons/#{$name}.svg");
position: absolute;
#{$top-or-bottom}: 0;
#{$left-or-right}: 0;
}
}
@include corner-icon("mail", top, left);
In SassScript
@mixin inline-animation($duration) {
$name: inline-#{unique-id()};
@keyframes #{$name} {
/* @content 填入@include大括号的内容 */
@content;
}
animation-name: $name;
animation-duration: $duration;
animation-iteration-count: infinite;
}
.pulse {
@include inline-animation(2s) {
from { background-color: yellow }
to { background-color: red }
}
}
.pulse {
animation-name: inline-un8qttjul;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes inline-un8qttjul {
from {
background-color: yellow;
}
to {
background-color: red;
}
}
At-Rules
@use
用来引入其他模块或者片段
// foundation/_code.scss
code {
padding: .25em;
line-height: 0;
}
// foundation/_lists.scss
ul, ol {
text-align: left;
& & {
padding: {
bottom: 0;
left: 0;
}
}
}
// style.scss
@use 'foundation/code';
@use 'foundation/lists';
code {
padding: .25em;
line-height: 0;
}
ul, ol {
text-align: left;
}
ul ul, ol ol {
padding-bottom: 0;
padding-left: 0;
}
namespace
引入的模块名称默认为模块文件名,也可以使用as进行重新命名
// src/_corners.scss
$radius: 3px;
@mixin rounded {
border-radius: $radius;
}
// style.scss
@use "src/corners" as c;
.button {
@include c.rounded;
padding: 5px + c.$radius;
}
默认值配置
使用with关键字对引入模块中带有!default标记的变量进行配置
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
code {
border-radius: $border-radius;
box-shadow: $box-shadow;
}
// style.scss
@use 'library' with (
$black: #222,
$border-radius: 0.1rem
);
重新指定变量值
// _library.scss
$color: red;
// _override.scss
@use 'library';
library.$color: blue;
// style.scss
@use 'library';
@use 'override';
@debug library.$color; //=> blue
注意,build-in模块不可被执行/覆盖值
index文件
当路径是一个文件夹时,会自动访问该文件夹内的index文件
@forward
它使得跨多个文件组织 Sass 库成为可能,同时允许用户加载单个入口点文件。
// src/_list.scss
@mixin list-reset {
margin: 0;
padding: 0;
list-style: none;
}
// bootstrap.scss
@forward "src/list";
// styles.scss
@use "bootstrap";
li {
@include bootstrap.list-reset;
}
添加前缀
可以通过添加前缀来避免多个forward模块出现相同的变量或函数等
// src/_list.scss
@mixin reset {
margin: 0;
padding: 0;
list-style: none;
}
// bootstrap.scss
@forward "src/list" as list-*;
// styles.scss
@use "bootstrap";
li {
@include bootstrap.list-reset;
}
控制隐藏
通过hide来隐藏你不想导出的一些变量或函数,以逗号分隔
// src/_list.scss
$horizontal-list-gap: 2em;
@mixin list-reset {
margin: 0;
padding: 0;
list-style: none;
}
@mixin list-horizontal {
@include list-reset;
li {
display: inline-block;
margin: {
left: -2px;
right: $horizontal-list-gap;
}
}
}
// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;
默认值配置
@forward仍然支持默认值配置,使用with关键字,方式与@use相同
@mixin和@include
@mixin reset-list {
margin: 0;
padding: 0;
list-style: none;
}
@mixin horizontal-list {
@include reset-list;
li {
display: inline-block;
margin: {
left: -2px;
right: 2em;
}
}
}
nav ul {
@include horizontal-list;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav ul li {
display: inline-block;
margin-left: -2px;
margin-right: 2em;
}
参数
@mixin rtl($property, $ltr-value, $rtl-value) {
#{$property}: $ltr-value;
[dir=rtl] & {
#{$property}: $rtl-value;
}
}
.sidebar {
@include rtl(float, left, right);
}
CSS OUTPUT
.sidebar {
float: left;
}
[dir=rtl] .sidebar {
float: right;
}
参数默认值
通常情况下mixin的每个参数都要传,我们可以使用默认值来避免部分情况
@mixin replace-text($image, $x: 50%, $y: 50%) {
text-indent: -99999em;
overflow: hidden;
text-align: left;
background: {
image: $image;
repeat: no-repeat;
position: $x $y;
}
}
.mail-icon {
@include replace-text(url("/images/mail.svg"), 0);
}
关键字传参
在参数非常多的时候,这个功能非常有用
@mixin square($size, $radius: 0) {
width: $size;
height: $size;
@if $radius != 0 {
border-radius: $radius;
}
}
.avatar {
@include square(100px, $radius: 4px);
}
.avatar {
width: 100px;
height: 100px;
border-radius: 4px;
}
任意参数(类似es6的方式)
@mixin order($height, $selectors...) {
@for $i from 0 to length($selectors) {
#{nth($selectors, $i + 1)} {
position: absolute;
height: $height;
margin-top: $i * $height;
}
}
}
@include order(150px, "input.name", "input.address", "input.zip");
input.name {
position: absolute;
height: 150px;
margin-top: 0px;
}
input.address {
position: absolute;
height: 150px;
margin-top: 150px;
}
input.zip {
position: absolute;
height: 150px;
margin-top: 300px;
}
key: value形式
@use "sass:meta";
@mixin syntax-colors($args...) {
@debug meta.keywords($args);
// (string: #080, comment: #800, variable: #60b)
@each $name, $color in meta.keywords($args) {
pre span.stx-#{$name} {
color: $color;
}
}
}
@include syntax-colors(
$string: #080,
$comment: #800,
$variable: #60b,
)
pre span.stx-string {
color: #080;
}
pre span.stx-comment {
color: #800;
}
pre span.stx-variable {
color: #60b;
}
内容占位@content
@mixin hover {
&:not([disabled]):hover {
@content;
}
}
.button {
border: 1px solid black;
@include hover {
border-width: 2px;
}
}
.button {
border: 1px solid black;
}
.button:not([disabled]):hover {
border-width: 2px;
}
@function
@function pow($base, $exponent) {
$result: 1;
@for $_ from 1 through $exponent {
$result: $result * $base;
}
@return $result;
}
.sidebar {
float: left;
margin-left: pow(4, 3) * 1px;
}
.sidebar {
float: left;
margin-left: 64px;
}
参数
与mixin相同
@extend
一个类要复用另一个类的所有样式时,可以使用extend
.error {
border: 1px #f00;
background-color: #fdd;
&--serious {
@extend .error;
border-width: 3px;
}
}
.error, .error--serious {
border: 1px #f00;
background-color: #fdd;
}
.error--serious {
border-width: 3px;
}
占位selector
使用%
%aaa {
font-size: 16px;
}
.button {
@extend %aaa;
}
@error
常用来判断参数类型是否符合符合要求
@mixin reflexive-position($property, $value) {
@if $property != left and $property != right {
@error "Property #{$property} must be either left or right.";
}
$left-value: if($property == right, initial, $value);
$right-value: if($property == right, $value, initial);
left: $left-value;
right: $right-value;
[dir=rtl] & {
left: $right-value;
right: $left-value;
}
}
.sidebar {
@include reflexive-position(top, 12px);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Error: Property top must be either left or right.
}
@at-root
@at-root 规则通常编写为@at-root < selector > { ... } ,并导致其中的所有内容都在文档的根目录中发出,而不是使用普通的嵌套。它最常用于使用 SassScript 父选择器和选择器函数进行高级嵌套。
.parent {
color: red;
@at-root .child {
width: 100px;
height: 100px;
}
}
.parent {
color: red;
}
.child {
width: 100px;
height: 100px;
}
例如,假设您想编写一个选择器,该选择器与外部选择器和元素选择器相匹配。您可以编写一个像这样的混合函数,它使用 selector.unify ()函数将 & 与用户的选择器组合在一起。
@use "sass:selector";
@mixin unify-parent($child) {
@at-root #{selector.unify(&, $child)} {
@content;
}
}
.wrapper .field {
@include unify-parent("input") {
/* ... */
}
@include unify-parent("select") {
/* ... */
}
}
.wrapper input.field {
/* ... */
}
.wrapper select.field {
/* ... */
}
数据类型
lists
索引
从索引1开始,-1代表最后一个元素
访问元素
@use 'sass:list'
@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3
添加元素
@debug append(10px 12px 16px, 25px); // 10px 12px 16px 25px
@debug append([col1-line1], col1-line2); // [col1-line1, col1-line2]
查找元素,返回索引,没有则为null
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null
遍历
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
不可变性
Sass 中的列表是不可变的,这意味着列表值的内容永远不会更改。Sass 的列表函数都返回新的列表,而不是修改原始列表。不可变性有助于避免在样式表的不同部分共享相同列表时出现许多潜在的 bug。
但是,您仍然可以通过将新列表分配给相同的变量来随时间更新状态。这通常在函数和 Mixin 中使用,以便将一组值收集到一个列表中。
@use "sass:list";
@use "sass:map";
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms);
@function prefixes-for-browsers($browsers) {
$prefixes: ();
@each $browser in $browsers {
$prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser));
}
@return $prefixes;
}
@debug prefixes-for-browsers("firefox" "ie"); // moz ms
参数lists
当声明一个带有任意参数的 Mixin 或函数时,得到的值是一个称为参数列表的特殊列表。它的作用就像一个列表,包含传递给 Mixin 或函数的所有参数,还有一个额外的特性: 如果用户传递了关键字参数,那么可以通过将参数列表传递给 meta.keywords ()函数来将它们作为映射进行访问。
@use "sass:meta";
@mixin syntax-colors($args...) {
@debug meta.keywords($args);
// (string: #080, comment: #800, variable: #60b)
@each $name, $color in meta.keywords($args) {
pre span.stx-#{$name} {
color: $color;
}
}
}
@include syntax-colors(
$string: #080,
$comment: #800,
$variable: #60b,
)
pre span.stx-string {
color: #080;
}
pre span.stx-comment {
color: #800;
}
pre span.stx-variable {
color: #60b;
}
maps
Sass 中的映射包含一对键和值,使得通过相应的键查找值变得容易。它们被写下来(< expression > : < expression > ,< expression > : < expression >)。之前的表达式是该键,之后的表达式是与该键关联的值。键必须是唯一的,但值可能是重复的。与列表不同,映射必须在其周围加上括号。没有对的映射被写为()。
精明的读者可能会注意到,空映射()与空列表写法相同。那是因为它既是映射又是列表。事实上,所有的映射都算作列表!每个 map 都是一个列表,其中包含每个键/值对的两个元素列表。例如,(1:2,3:4)计为(12,34)。
获取值
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.get($font-weights, "medium"); // 500
@debug map.get($font-weights, "extra-bold"); // null
遍历
$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");
@each $name, $glyph in $icons {
.icon-#{$name}:before {
display: inline-block;
font-family: "Icon Font";
content: $glyph;
}
}
插值
@use "sass:map";
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.set($font-weights, "extra-bold", 900);
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
@debug map.set($font-weights, "bold", 900);
// ("regular": 400, "medium": 500, "bold": 900)
合并
@use "sass:map";
$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);
@debug map.merge($light-weights, $heavy-weights);
// ("lightest": 100, "light": 300, "medium": 500, "bold": 700)