Sass 是世界上最成熟、最稳定、最强大的专业级CSS扩展语言。Sass允许您使用变量、嵌套规则、混合、函数等语法,所有这些通过编译后都具有完全兼容CSS的语法。Sass 有助于保持大型样式表井井有条,并使在项目内部和项目之间共享设计变得容易。
基本语法(变量、嵌套、混合、继承)
变量$
变量是重复利用的常见方式。比如可以定义静态的资源路径(图片、字体)、颜色、尺寸。scss利用$来定义变量
// scss变量定义
$color: #f50;
$font-base-size:16px;
body{
color:$color;
font-size:$font-base-size;
}
👇🏻下面是生成的css样式
body{
color: #f50;
font-size:16px;
}
嵌套
scss允许使用嵌套语法,使css语法结构更加清晰,可维护性高。嵌套方式与HTML的层次结构相同
.content{
margin: 0 8px;
ul{
margin:0px;
li{
padding:0px;
}
}
}
👇🏻下面是生成的css样式
.content{
margin:0 8px;
}
.content ul{
margin:0px;
}
.content ul li{
padding:0px;
}
混合(@mixin、@include)
针对开发过程中有很多类名具有相同或者相似的样式,scss利用混合来进行组织代码,达到减少重复代码的目的。例如常见的兼容性代码。
不含参数形式
@mixin large-text {
font-size: 20px;
color: #ff0000;
}
.page-title {
@include large-text;
padding: 4px;
margin-top: 10px;
}
👇🏻下面是生成的css样式
.page-title{
font-size: 20px;
color: #ff0000;
padding: 4px;
margin-top: 10px;
}
含参数形式
@mixin sexy-border($color, $width: 1in) {//width为空时使用默认值
color: $color;
width: $width;
style: dashed;
}
p { @include sexy-border(blue); }
h1 { @include sexy-border(blue, 2in); }
👇🏻下面是生成的css样式
p{
color: blue;
width: 1in;
style: dashed;
}
h1{
color: blue;
width: 2in;
style: dashed;
}
继承(@extend)
继承(@extend)让一个css类(A)继承另一个css类(B)。被继承的css类(B)所用CSS属性都被css类(A)所共享。
继承的两种情况:
- 一种是继承class,定义以.开头,被继承的模块(B)独立存在于css中。
- 一种继承一个公共模块,定义以%开头,被继承的模块不会独立存在与css中。
继承class(以.开头)
.button{
display:inline-block;
color:#f50;
text-align:center;
border: solid 1px red;
}
.button-noborder{
@extend .button;
border:none;
&:hover{
font-size:16px;
}
}
👇🏻下面是生成的css样式
.button, .button-noborder{
display:inline-block;
color:#f50;
text-align:center;
border: solid 1px red;
}
.button-noborder{
border:none;
}
.button-noborder:hover{
font-size:16px;
}
继承公共模块(%开头)
%button{
display:inline-block;
color:#f50;
text-align:center;
border: solid 1px red;
}
.button-noborder{
@extend %button;
border:none;
&:hover{
font-size:16px;
}
}
👇🏻下面是生成的css样式
.button-noborder{
display:inline-block;
color:#f50;
text-align:center;
border: solid 1px red;
}
.button-noborder{
border:none;
}
.button-noborder:hover{
font-size:16px;
}
操作符
引用父选择符&
引用父级选择符&,大部分用于伪类的书写。
$color:#f50;
a{
display:inline-block;
color:$color;
&:hover{
text-decoration:none;
}
&.menu{
margin:0px;
}
}
👇🏻下面是生成的css样式
a{
display:inline-block;
color:#f50;
}
a:hover{
text-decoration:none;
}
a.menu{
margin:0px;
}
插值操作符#{}
插值操作符#{},可以在选择器或属性名使用变量,拼接字符串。
$unit = border;
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
#{$unit}-color:blue;
}
👇🏻下面是生成的css样式
p{
font:30px/12px;
border-color:blue;
}
字符串操作符+
字符串操作符+,常用来处理字符串的拼接。注意有引号字符串(位于+的左侧)连接无引号字符串,运算结果有引号。相反无引号字符串(位于+的左侧)连接有引号的字符串,运算结果无引号。运算表达式通过空格与其他值相连。
p:before{
content:"Foo "+Bar;
font-family:sans- +"serif";
margin: 3px+4px auto;
}
👇🏻下面是生成的css样式
P:before{
content:"Foo Bar";
font-family:sans-serif;
margin:7px auto;
}
算术操作符+、-、*、/、%
使用算术操作符时,参与运算的数据单位必须相同,否则会报错。(例如,一个用px,另一个用em);
.sidebar{
width:1000px*0.8-100px;
height:100px%75;
}
👇🏻下面是生成的css样式
.sidebar{
width:700px;
height:25px;
}
/ 在 CSS 中通常起到分隔数字的用途,SassScript 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了 / 除法运算的功能。
因此以下三种情况/被当做除法运算:
- 如果值,或值的一部分,是变量或者函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
p {
font: 10px/8px; // Plain CSS, no division
$width: 1000px;
width: $width/2; // Uses a function, does division
height: (500px/2); // Uses parentheses, does division
margin-left: 5px + 8px/2px; // Uses +, does division
}
👇🏻下面是生成的css样式
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
流程控制符@if、@if...@else、@for、@each、@while、if
@if、 @if @else if
$isShow:v-bind(val);//val === false
.side{
@if($isShow == true){
display:none;
...
}@else if{
display: inline-block;
...
}
}
👇🏻下面是生成的css样式
.side{
display:inline-block;
...
}
@for
@for 指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。这个指令包含两种格式:@for $var from <start> through <end>,或者 @for $var from <start> to <end>,区别在于 through 与 to 的含义:当使用 through 时,条件范围包含 <start> 与 <end> 的值,而使用 to 时条件范围只包含 <start> 的值不包含 <end> 的值。另外,$var 可以是任何变量,比如 $i;<start> 和 <end> 必须是整数值。
@for $i from 1 through 3 {
.item-#{$i} { width: 2em * $i; }
}
👇🏻下面是生成的css样式
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}
@each
@each可以轻松为列表的每一个元素生成样式。或为map中每一对生成样式和有意义代码。
@each $icon in excel, ppt, pdf{
.icon-#{$icon} {
background-image: url("#{$image-path}#{$icon}.png");
}
}
👇🏻下面是生成的css样式
.icon-excel {
background-image: url("./assets/images/excel.png");
}
.icon-ppt {
background-image: url("./assets/images/ppt.png");
}
.icon-pdf {
background-image: url("./assets/images/pdf.png");
}
多重分配
@each $color, $border in (aqua, dotted), (red, solid), (green, double){
.#{border-$color-$border} {
background-color : $color; border: $border;
}
}
👇🏻下面是生成的css样式
.border-aqua-dotted{
background-color: aqua;
border: dotted;
}
.border-red-soli{
background-color: red;
border: soli;
}
.border-green-double{
background-color:green;
border: double;
}
@ while
@while指令在SassScript表达式或计算结果为假之前,持续输出嵌套样式。
$i: 40;
@while $i > 0 {
.padding-#{$i} {
padding-left: 1px * $i;
}
$i: $i - 20;
}
👇🏻下面是生成的css样式
.padding-40 {
padding-left: 1px * $i;
}
.padding-20 {
padding-left: 1px * $i;
}
三目运算符if
$size:10;
.size-font{
font-size:if($size % 10==0,"14px","28px");
}
👇🏻下面是生成的css样式
.size-font{
font-size:14px;
}
关系操作符>、<、>=、<=、==、!=、>、<、>=、<=
@debug 1px == 1px; // true
@debug 1px != 1em; // true
@debug "Helvetica" == Helvetica; // true
@debug "Helvetica" != "Arial"; // true
@debug hsl(34, 35%, 92.1%) == #f2ece4; // true
@debug rgba(179, 115, 153, 0.5) != rgba(179, 115, 153, 0.8); // true
$theme: ("venus": #998099, "nebula": #d2e1dd);
@debug $theme == ("venus": #998099, "nebula": #d2e1dd); // true
@debug $theme != ("venus": #998099, "iron": #dadbdf); // true
关系运算符确实数字是大于还是小于彼此。它们会在兼容单位之间自动转换
<expression> < <expression>,第一个表达式的值是否小于第二个。
<expression> <= <expression>,第一个表达式的值是否小于或等于第二个。
<expression> > <expression>,第一个表达式的值是否大于第二个表达式的值。
<expression> >= <expression>, 返回第一个表达式的值是否大于或等于第二个。
逻辑运算符(and,or,not)
not <expression>返回表达式值的反面:它true变成false和falseinto true。
<expression> and <expression>true如果两个表达式的值都是true,并且false其中一个是 ,则返回false。
<expression> or <expression>true如果任一表达式的值为true,并且false两者均为 ,则返回false。
@debug not true; // false
@debug not false; // true
@debug true and true; // true
@debug true and false; // false
@debug true or false; // true
@debug false or false; // false
基本指令(@use、@forward、@import、@function、@error、@debug、@warn)
@use
@use从其它sass文件样式表中加载mixins,函数和变量。@use加载的样式表称为模块。
- 通过@use 'url',在给定的url下面加载模块。
- 您可以以
<namespace>.<variable>,<namespace>.<function>()或@include <namespace>.<mixin>()形式从另一个模块访问变量、函数、混合。
- 您可以通过编写
@use "<url>" as <namespace>来实现模块重新命名。默认情况下,模块的名称空间只是其URL的最后一个组成部分(去掉文件扩展名)。
- 您甚至可以通过编写
@use "<url>" 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;
}
- 重新配置模块:样式表可以使用
!default标志定义变量以使其可配置。要使用配置加载模块,请编写@use <url> with (<variable>: <value>, <variable>: <value>)。配置的值将覆盖变量的默认值。
// _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
);
- 除了加载
.sass和.scss文件外,Sass还可以加载普通的旧.css文件。
@forward
@forward指令加载Sass样式表与@use加载样式表用法一致。但@forward加载的样式表自身不会使用,需搭配@use。
@import
@import导入SCSS或Sass文件,并将被导入的文件合并编译为同一个CSS文件中。因为@import也在CSS中定义,所以 Sass 需要一种编译纯CSS @import的方法,而不是在编译时尝试导入文件。在以下情况下,@import仅作为普通的CSS语句,并不能成功导入Sass文件。
- 导入URL以 .结尾的 位置
.css。 - 导入URL开始的位置
http://或https://. - 导入URL写为
url(). - 具有媒体查询的导入。
@import "theme.css";
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import url(theme);
@import "landscape" screen and (orientation: landscape);
@function
@function自定义函数,可接受全局变量作为参数,通过@return输出结果。
@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;
}
@debug
@debug <expression>,打印出该表达式的值。
@mixin inset-divider-offset($offset, $padding) {
$divider-offset: (2 * $padding) + $offset;
@debug "divider offset: #{$divider-offset}";
margin-left: $divider-offset;
width: calc(100% - #{$divider-offset});
}
//控制台输出:
//test.scss:3 Debug: divider offset: 132px
@error、@warn
@error <expression>,它打印表达式的值。一旦错误被打印出来,Sass 就会停止编译样式表并告诉正在运行它的任何系统发生了错误。与console.error类似。
@warn <expression>,它打印表达式的值。与console.warn类似。
内置函数
字符串函数(sass:string)
quote(string)
给字符串添加引号
string.quote($string)
quote($string) //=> string
@debug string.quote(Helvetica); // "Helvetica"
@debug string.quote("Helvetica"); // "Helvetica"
unquote(string)
移除字符串的引号
@debug string.unquote(Helvetica); // Helvetica
@debug string.unquote("Helvetica"); // Helvetica
str-index(string,substring)
返回string字符串中第一次出现substring子字符串的位置。如果没有匹配到子字符串,则返回null。区分大小写。
str-index(abcd, a) // 1
str-index(abcd, ab) // 1
str-index(abcd, X) // null
str-insert(string,insert,index)
在字符串string第index位置插入insert
@debug string.insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold"
@debug string.insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold"
str-length( string )
返回字符串string的长度
string.length($string)
str-length($string) //=> number
@debug string.length("Helvetica Neue"); // 14
@debug string.length(bold); // 4
@debug string.length(""); // 0
str-slice(string,start,end)
从 string 中截取子字符串,通过 start-at 和 end-at 设置始末位置,未指定结束索引值则默认截取到字符串末尾。
string.slice($string, $start-at, $end-at: -1)
str-slice($string, $start-at, $end-at: -1) //=> string
@debug string.slice("Helvetica Neue", 11); // "Neue"
@debug string.slice("Helvetica Neue", 1, 3); // "Hel"
@debug string.slice("Helvetica Neue", 1, -6); // "Helvetica"
to-lower-case( string )
将字符串转换为小写
@debug string.to-lower-case("Bold"); // "bold"
@debug string.to-lower-case(SANS-SERIF); // sans-serif
to-upper-case( string )
将字符串转换为大写
@debug string.to-upper-case("Bold"); // "BOLD"
@debug string.to-upper-case(sans-serif); // SANS-SERIF
unique-id()
返回一个无引号的随机字符串作为 id。不过也只能保证在单次的 Sass 编译中确保这个 id 的唯一性。
@debug string.unique-id(); // uabtrnzug
@debug string.unique-id(); // u6w1b1def
数字函数(sass:math)
abs(number)
返回一个数值的绝对值
@debug math.abs(13) // 13
@debug math.abs(-13) // 13
comparable(num1,num2)
返回一个布尔值,判断 num1 与 num2 是否可以进行比较 ,注意是否可以比较,不是比较的结果。
@debug math.comparable(15px, 10px) // true
@debug math.comparable(20mm, 1cm) // true
@debug math.comparable(35px, 2em) // false
ceil(number)
对数字进行向上取整
@debug math.ceil(13.24) //14
floor(number)
对数字进行向下取整
@debug math.floor(15.84) // 15
max(number...)
返回最大值
@debug math.max(5, 7, 9, 0, -3, -7) // 9
min(number...)
返回最小值
@debug math.min(7, 2, 0, -2, -7) // -7
percentage( number )
将数字返回为百分比形式
@debug math.percentage(1.2) // 120%
random( number )
返回1至number之间的随机数。不传number的时候,返回0-1区间内的小数。
@debug math.random() // 0.2783
@debug math.random(10) // 4
round(number)
返回最接近该数的一个整数,四舍五入。
round(15.20) // 15
round(15.80) // 16
List函数(sass:list)
三大注意点:
1、Sass列表(List)函数,可以访问列表中的值,向列表添加元素,合并列表等。
2、Sass 列表是不可变的,因此在处理列表时,返回的是一个新的列表,而不是在原有的列表上进行修改。
3、列表的起始索引值为 1,记住不是 0。
append(list,value,[separator])
将单个值 value 添加到列表list尾部,separator 是分隔符。separator默认会自动侦测,或者指定为逗号或空格。
@debug list.append(10px 20px, 30px); // 10px 20px 30px
@debug list.append((blue, red), green); // blue, red, green
@debug list.append(10px 20px, 30px 40px); // 10px 20px (30px 40px)
@debug list.append(10px, 20px, $separator: comma); // 10px, 20px
@debug list.append((blue, red), green, $separator: space); // blue red green
index( list , value )
返回元素 value 在列表中的索引位置。
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null
is-bracketed( list )
判断列表中是否有中括号
list.is-bracketed($list)
is-bracketed($list) //=> boolean
list-separator( list )
返回一列表的分隔符类型。可以是空格或逗号。
list-separator(a b c) // "space"
list-separator(a, b, c) // "comma"
join( list1 , list2 , [ separator, bracketed ])
合并两列表,将列表 list2 添加到列表 list1 的末尾。separator 是分隔符,默认会自动侦测,或者指定为逗号或空格。bracketed 默认会自动侦测是否有中括号,可以设置为 true 或 false。
@debug list.join(10px 20px, 30px 40px); // 10px 20px 30px 40px
@debug list.join((blue, red), (#abc, #def)); // blue, red, #abc, #def
@debug list.join(10px, 20px); // 10px 20px
@debug list.join(10px, 20px, $separator: comma); // 10px, 20px
@debug list.join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def
@debug list.join([10px], 20px); // [10px 20px]
@debug list.join(10px, 20px, $bracketed: true); // [10px 20px]
length( list )
返回列表的长度
length(a b c) // 3
set-nth( list , n , value )
设置列表第 n 项的值为 value。
set-nth(a b c, 2, x) // a x c
nth( list , n )
获取第 n 项的值。
nth(a b c, 3) // c
zip( lists )
将多个列表按照以相同索引值为一组,重新组成一个新的多维度列表。这个排列组合非常的人性,需要安排!
zip(1px 2px 3px, solid dashed dotted, red green blue) // 1px solid red, 2px dashed green, 3px dotted blue
Map函数(sass:map)
Sass Map 是不可变的,因此在处理 Map 对象时,返回的是一个新的 Map 对象,而不是在原有的 Map 对象上进行修改。map加载内部方法可通过map.xxx 或者 map-xxx。例如map-get 与map.get两种写法是一样的。
map-get( map , key )
返回map中key对应的value值。如没有对应的key,则返回null值。
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
map-get($font-sizes, "small") // 12px
$config: (a: (b: (c: d)));
@debug map.get($config, a, b, c); // d
map-set(map,key,value)
对map中的指定key设置为value。
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.set($font-weights, "regular", 300);
// ("regular": 300, "medium": 500, "bold": 700)
map-has-key( map , key )
判断map中是否拥有对应的key,存在返回true,否则返回false。
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
map-has-key($font-sizes, "big") // false
map-keys( map )
返回 map 中所有的 key 组成的队列。
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
map-keys($font-sizes) // "small", "normal, "large"
map-values( map )
返回 map 中所有的 value 并生成一个队列。
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
map-values($font-sizes) // 12px, 18px, 24px
map-merge( map1 , map2 )
合并两个 map 形成一个新的 map 类型,即将 map2 添加到 map1的尾部。
$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)
map-remove( map , *keys... *)
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.remove($font-weights, "regular"); // ("medium": 500, "bold": 700)
@debug map.remove($font-weights, "regular", "bold"); // ("medium": 500)
@debug map.remove($font-weights, "bolder");
注释写法
scss的注释常见有两种
- 标准注释:
/* comment */,会保留到编译后的文件。
- 单行注释:
// comment,只保留在scss源文件中,编译后被过滤,在css中不可见。
一般在 /* 后面加一个感叹号,表示这是“重要注释”。即使是压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。
Sass Cli的使用
One-to-One Mode
一对一模式将单个输入文件 (input.scss) 编译到单个输出位置 (output.css)。如果未传递输出位置,则将编译后的 CSS 打印到终端。
sass <input.scss> [output.css]
Many-to-many Mode
多对多模式将一个或多个输入文件编译为一个或多个输出文件。输入与输出用冒号分隔。它还可以将一个目录中所有的Sass文件编译为另一个目录的同名CSS文件。
sass [<input.scss>:<output.css>] [<input/>:<output/>]...
# Compiles style.scss to style.css.
$ sass style.scss:style.css
# Compiles light.scss and dark.scss to light.css and dark.css.
$ sass light.scss:light.css dark.scss:dark.css
# Compiles all Sass files in themes/ to CSS files in public/css/.
$ sass themes:public/css
Options
👇🏻下面选项控制 Sass 如何加载其输入文件以及如何生成输出文件。
--stdin
该标志告诉Sass它应该从标准输入读取其输入文件的另一种方式。当它通过时,可能不会传递任何输入文件。--stdin标志不能被使用到多对多模式。
$ echo "h1 {font-size: 40px}" | sass --stdin h1.css
$ echo "h1 {font-size: 40px}" | sass --stdin
h1 {
font-size: 40px;
}
--indented
该标志告诉Sass将输入文件解析为缩进语法。如果在多对多模式使用,所有输入文件都被解析为缩进语法,尽管它们使用的文件像往常一样确定其语法。相反,--no-indented可用于强制将所有的输入文件解析为SCSS。
$ echo -e 'h1\n font-size: 40px' | sass --indented -
h1 {
font-size: 40px;
}
--load-path (-I)
此选项(缩写为-I)为Sass添加了一个额外的加载路径以查找样式表。它可以多次传递以提供多个加载路径。较早的加载路径将优先于以后得加载路径。
$ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css
--style
此选项(缩写为-s)控制生成的css的输出样式。Dart Sass支持两种输出样式:
- expanded(default): 将每个选择器和声明写在自己的行上。
- compressed: 尽可能删除额外字符,并将整个样式表写在一行上。
$ sass --style=expanded style.scss
h1 {
font-size: 40px;
}
$ sass --style=compressed style.scss
h1{font-size:40px}
Extend
-
Sass Loader 的配置
- Dart Sass
-
Sass Cli 的使用
-
One-to-One Mode
-
Many-to-many Mode
-
Options
- --stdin
- --Indented
- --load-path
- --style
- --no-charset
- --error-css
- --update
- --no-source-map
- --source-map-urls
- --embed-sources
- --embed-source-map
- --watch
- --poll
- --stop-on-error
- --interactive
- --color
- --no-unicode
- --quiet
- --quiet-deps
- --trace
- --help
-