目录
介绍
- SCSS/SASS是CSS预处理器,为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题,可以让你的CSS更加简洁、适应性更强、可读性更佳,更易于代码的维护等诸多好处。
- Sass和SCSS其实是同一种东西 后者是前者的进化版 改进了语法书写方式
- Sass和SCSS区别:
(1)文件扩展名不同,Sass是以“.sass”后缀为扩展名,而SCSS是以“.scss”后缀为扩展名
(2)语法书写方式不同,Sass是以严格的缩进式语法规则来书写,不带大括号和分号,主要是依靠严格的缩进方式来控制的,而SCSS的语法书写和CSS语法书写方式一样
.sass只能使用Sass老语法规则(缩进规则),.scss使用的是Sass的新语法规则,也就是SCSS语法规则(类似CSS语法格式)。
SCSS编译
- html中是不能直接调用scss的,要先将scss转译为css,然后调用css的文件。
- Sass的编译方法:
(1)命令编译
(2)GUI工具编译
(3)自动化编译
命令编译
- 命令编译是指使用你电脑中的命令终端,通过输入Sass指令来编译:
(1)单个SASS文件进行编译:sass 要编译的Sass文件路径:要输出CSS文件路径
(2)将整个项目所有Sass文件编译成CSS文件:sass sass/:css/
将项目中“sass”文件夹中所有“.scss”(“.sass”)文件编译成“.css”文件,并且将这些 CSS 文件都放在项目中“css”文件夹中。 - 问题及解决:每次保存“.scss”文件之后,都得重新执行一次这样的命令进行编译,太麻烦,我们可以在编译Sass时,开启“watch”功能,这样只要代码进行任何修改,都能自动监测到代码的变化,并且直接编译出来:
sass --watch 要编译的Sass文件路径:要输出CSS文件路径
我想把项目中“bootstrap.scss”编译成“bootstrap.css”文件,并且将编译出来的文件放在“css”文件夹中,我就可以在我的命令终端中执行:
sass --watch sass/bootstrap.scss:css/bootstrap.css
- 使用sass命令编译时,可以带很多的参数:
常见的编译错误解决方案
- 在创建Sass文件时,就需要将文件编码设置为“utf-8”,因为在Sass的编译的过程中,不支持“GBK”编码
- 在项目中文件命名或者文件目录命名不要使用中文字符
不同样式风格的输出方法
- 嵌套输出方式 nested
- 展开输出方式 expanded
- 紧凑输出方式 compact
- 压缩输出方式 compressed
嵌套输出方式 nested
在编译的时候带上参数--style nested
编译出来的风格:
展开输出方式 expanded
在编译的时候带上参数--style expanded
编译出来的风格:
紧凑输出方式 compact
在编译的时候带上参数--style compact
编译出来的风格:
压缩输出方式 compressed
在编译的时候带上参数--style compressed
编译出来的风格:
变量
声明变量
- Sass 的变量包括三个部分:
(1)声明变量的符号“$”
(2)变量名称
(3)赋予变量的值 - 只有满足所有下述标准时方可创建新变量:
(1)该值至少重复出现了两次;
(2)该值至少可能会被更新一次;
(3)该值所有的表现都与变量有关(非巧合)。
普通变量与默认变量
- 普通变量:定义之后可以在全局范围内使用。
$fontSize: 12px;
body{
font-size:$fontSize;// 使用/调用变量
}
- 默认变量:一般是用来设置默认值,然后根据需求来覆盖的,覆盖的方式也很简单,只需要在默认变量之前重新声明下变量即可。在值后面加上
!default
即为默认变量
$baseLineHeight: 2;// 覆盖默认值
$baseLineHeight: 1.5 !default;
body{
line-height: $baseLineHeight; // 2
}
- 如果我们引入的他人scss文件中的变量有默认值的设置,而我们又不想用这些默认变量,那么我们在这些导入文件之前引入一个配置scss文件即可,而无需修改他人的scss文件
- 假如全局范围内设置了一个变量
$color:red;
那在所有地方用$color
变量其值都是red,但是假如我在一个局部范围内不想用red红色,那就可以在局部范围声明$color:green;
这样不会影响其他需要设置颜色为red的地方
全局变量和局部变量
- 全局变量就是定义在元素外面的变量
- 局部变量就是定义在元素内面的变量
- 当在局部范围(选择器内、函数内、混合宏内…)声明一个已经存在于全局范围内的变量时,局部变量就成为了全局变量的影子。基本上,局部变量只会在局部范围内覆盖全局变量。
$color: orange !default;//定义全局变量
.block {
color: $color;//调用全局变量
}
em {
$color: red;//定义局部变量(全局变量 $color 的影子)
a {
color: $color;//调用局部变量
}
}
嵌套
Sass 的嵌套分为三种:
(1)选择器嵌套
(2)属性嵌套
(3)伪类嵌套
选择器嵌套
父选择器&
&
代表嵌套规则外层的父选择器 如果含有多层嵌套,最外层的父选择器会一层一层向下传递
<header>
<nav>
<a href=“##”>Home</a>
<a href=“##”>About</a>
<a href=“##”>Blog</a>
</nav>
<header>
想选中 header 中的 a 标签,在写 CSS 会这样写:
nav a {
color:red;
}
header nav a {
color:green;
}
在 Sass 中,就可以使用选择器的嵌套来实现
nav {
a {
color: red;
header & {
color:green;
}
}
}
&
必须作为选择器的第一个字符,其后可以跟随后缀生成复合的选择器
#main {
color: black;
&-sidebar {
border: 1px solid;
}
}
编译为
#main {
color: black;
}
#main-sidebar {
border: 1px solid;
}
- &和相连的类名之间不能有任何的空格,不然就会变成CSS选择器中的后代选择器
属性嵌套
CSS 有一些属性前缀相同,只是后缀不一样,比如:border-top/border-right
,与这个类似的还有 margin、padding、font 等属性。假设你的样式中用到了:
.box {
border-top: 1px solid red;
border-bottom: 1px solid green;
}
在 Sass 中可以这样写:
.box {
border: {
top: 1px solid red;
bottom: 1px solid green;
}
}
伪类嵌套
伪类嵌套和属性嵌套非常类似,只不过他需要借助&
符号一起配合使用
.clearfix{
&:before,
&:after {
content:"";
display: table;
}
&:after {
clear:both;
overflow: hidden;
}
}
编译为:
clearfix:before, .clearfix:after {
content: "";
display: table;
}
.clearfix:after {
clear: both;
overflow: hidden;
}
混合宏
混合:用于定义可重复使用的样式
声明混合宏及调用混合宏
- 不带参数的混合宏
@mixin border-radius{
-webkit-border-radius: 5px;
border-radius: 5px;
}
button {
@include border-radius;
}
其中@mixin
是用来声明混合宏的关键词,border-radius是混合宏的名称。大括号里面是复用的样式代码 ,可以在大括号中写一些复杂的逻辑关系。@include
来调用声明好的混合宏。编译为:
button {
-webkit-border-radius: 5px;
border-radius: 5px;
}
- 带参数的混合宏:参数用于给混合指令中的样式设定变量,并且赋值使用。在定义混合指令的时候,按照变量的格式,通过逗号分隔,将参数写进圆括号里。引用指令时,按照参数的顺序,再将所赋的值对应写进括号
@mixin sexy-border($color, $width) {// 参数可以是1个或多个 这里展示写了两个
border: {
color: $color;
width: $width;
style: dashed;
}
}
p { @include sexy-border(blue, 1in); }
编译为:
p {
border-color: blue;
border-width: 1in;
border-style: dashed; }
可以使用给变量赋值的方法给参数设定默认值,然后,当这个指令被引用的时候,如果没有给参数赋值,则自动使用默认值
@mixin border-radius($radius:5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
.btn {
@include border-radius;
}
.box {
@include border-radius(50%);
}
编译为:(这里就展现了混合宏的不足 代码冗余 不能将相同的样式代码块合并在一起)
.btn {
-webkit-border-radius: 5px;
border-radius: 5px;
}
.box {
-webkit-border-radius: 50%;
border-radius: 50%;
}
- 复杂的混合宏:有时,不能确定混合指令需要使用多少个参数,比如一个关于 box-shadow 的混合指令不能确定有多少个 ‘shadow’ 会被用到。这时,可以使用==参数变量…声明(写在参数的最后方)==告诉 Sass 将这些参数视为值列表处理
@mixin box-shadow($shadows...) {
-moz-box-shadow: $shadows;
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
.shadows {
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);// 调用混合宏
}
编译为:
.shadowed {
-moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
-webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}
混合宏的不足
优点:复用重复代码块。
不足:会生成冗余的代码块。Sass在调用相同的混合宏时,并不能智能的将相同的样式代码块合并在一起。
扩展/继承
通过关键词@extend
来继承已存在的类样式块,从而实现代码的继承。
.btn {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary {
background-color: #f36;
color: #fff;
@extend .btn;
}
.btn-second {
background-color: orange;
color: #fff;
@extend .btn;
}
编译为:
.btn, .btn-primary, .btn-second {// 组合选择器
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary {
background-color: #f36;
color: #fff;
}
.btn-second {
background-clor: orange;
color: #fff;
}
由此可见,在Sass中的继承,可以继承类样式块中所有样式代码,而且编译出来的CSS会将选择器合并在一起,形成组合选择器。
占位符选择器 %placeholder
- 占位符可以解决代码冗余问题
- 声明占位符:
%placeholder
。 - 调用:
@extend
指令调用 只声明不调用不会编译到 CSS 文件中。
%mt5 {
margin-top: 5px;
}
%pt5{
padding-top: 5px;
}
.btn {
@extend %mt5;
@extend %pt5;
}
.block {
@extend %mt5;
span {
@extend %pt5;
}
}
编译后:
.btn, .block {
margin-top: 5px;
}
.btn, .block span {
padding-top: 5px;
}
由此可见,通过@extend调用的占位符,编译出来的代码会将相同的代码合并在一起
混合宏VS继承VS占位符
- 混合宏:编译出来的CSS不会自动合并相同的样式代码,如果在样式文件中调用同一个混合宏,会产生多个对应的样式代码,造成代码的冗余,但他可以传参数。如果你的代码块中涉及到变量,建议使用混合宏来创建相同的代码块。
- 继承:编译出来的CSS会将使用继承的代码块合并到一起,通过组合选择器的方式向大家展现,这样编译出来的代码相对于混合宏来说要干净的多,但是他不能传变量参数。如果你的代码块不需要专任何变量参数,而且有一个基类已在文件中存在,那么建议使用 Sass 的继承。
- 占位符:编译出来的CSS代码和使用继承基本上相同,只是不会在代码中生成占位符mt的选择器。那么占位符和继承的主要区别的,“占位符是独立定义,不调用的时候是不会在CSS中产生任何代码;继承是首先有一个基类存在,不管调用与不调用,基类的样式都将会出现在编译出来的CSS代码中。”
插值#{}
- 通过
#{}
插值语句可以在选择器或属性名中使用变量: #{变量}
用来拼接变量名、选择器名、属性名
$name: foo;
$attr: border;
p.#{$name} {
#{$attr}-color: blue;
}
编译为:
p.foo {
border-color: blue;
}
- 不能在mixin中、调用mixin时使用插值
- 可以在@extend中使用插值
注释
/**/
:会在编译出来的CSS显示//
:在编译出来的CSS中不会显示
数据类型
- 数字: 如,1、 2、 13、 10px;
- 字符串:有引号字符串或无引号字符串,如,“foo”、 ‘bar’、 baz;
使用
#{}
插值语句时,有引号字符串将被编译为无引号字符串,这样方便了在mixin)中引用选择器名
- 颜色:如,blue、 #04a3f9、 rgba(255,0,0,0.5);
- 布尔型:如,true、 false;
- 空值:如,null;
- 值列表:用空格或者逗号分开,如,1.5em 1em 0 2em 、 Helvetica, Arial, sans-serif。
值列表中可以再包含值列表,比如:1px 2px, 5px 6px是包含1px 2px与5px 6px两个值列表的值列表。如果内外两层值列表使用相同的分隔方式,要用圆括号包裹内层,所以也可以写成(1px 2px)(5px 6px)。当值列表被编译为CSS时,Sass不会添加任何圆括号。(1px 2px)(5px 6px)与1px 2px 5px 6px在编译后的CSS文件中是一样的,但是它们在Sass文件中却有不同的意义,前者是包含两个值列表的值列表,而后者是包含四个值的值列表。
可以用()表示空的列表,这样不可以直接编译成CSS,比如编译font-family: ()
时,Sass将会报错。如果值列表中包含空的值列表或空值,编译时将清除空值,比如1px 2px () 3px或1px 2px null 3px。
SassScript 也支持其他CSS 属性值,比如Unicode范围,或!important
声明。然而,Sass不会特殊对待这些属性值,一律视为无引号字符串。
运算
加法
在变量或属性中都可以做加法运算
.box {
width: 20px + 8in;
}
编译为:
.box {
width: 788px;
}
单位类型不同的不能做运算 会报错 比如px和rem就不同
减法
同加法
$full-width: 960px;
$sidebar-width: 200px;
.content {
width: $full-width - $sidebar-width;
}
编译为:
.content {
width: 760px;
}
乘法
进行乘法运算时,两个值单位相同时,只需要为一个数值提供单位即可,否则会报错。并且在运算中有不同类型的单位时,也将会报错。
.box {// 会报错
width:10px * 2px;
}
应该写为:
.box {
width: 10px * 2;
}
编译为:
.box {
width: 20px;
}
除法
/
符号在CSS中已做为一种符号使用(用来分隔数字)。因此在Sass中做除法运算时,直接使用/
符号做为除号时,将不会生效。只有在以下情况中,/
符号被当作除号
- 如果数值或它的任意部分是存储在一个变量中或是函数的返回值。
- 如果数值被圆括号包围。
- 如果数值是另一个数学表达式的一部分。
p {
font: 10px/8px; // 纯 CSS,不是除法运算
$width: 1000px;
width: $width/2; // 使用了变量,是除法运算
width: round(1.5)/2; // 使用了函数,是除法运算
height: (500px/2); // 使用了圆括号,是除法运算
margin-left: 5px + 8px/2px; // 使用了加(+)号,是除法运算
}
编译为:
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
如果需要使用变量,同时又要确保/
不做除法运算而是完整地编译到CSS文件中,只需要用#{}
插值语句将变量包裹。
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
}
编译为:
p {
font: 12px/30px;
}
在乘法运算时,如果两个值带有相同单位时,做乘法运算时,出来的结果并不是我们需要的结果。但在除法运算时,如果两个值带有相同的单位值时,除法运算之后会得到一个不带单位的数值。
.box {
width: (1000px / 100px);
}
编译为:
.box {
width: 10;
}
变量计算
$content-width: 720px;
$sidebar-width: 220px;
$gutter: 20px;
.container {
width: $content-width + $sidebar-width + $gutter;
margin: 0 auto;
}
编译为:
.container {
width: 960px;
margin: 0 auto;
}
注意减号左右一定要加空格 否则可能被理解为连字符
数字运算
可以通过括号来修改运算先后顺序
颜色运算
红、绿和蓝各颜色分段单独进行运算
p {
color: #010203 + #040506;
}
计算公式为:01 + 04 = 05、02 + 05 = 07 和 03 + 06 = 09,编译为:
p {
color: #050709;
}
字符运算
可以通过加法符号“+”来对字符串进行连接,还可以直接通过+
,把字符连接在一起
div {
cursor: e + -resize;
}
编译为:
div {
cursor: e-resize;
}
如果有引号的字符串被添加了一个没有引号的字符串(也就是,带引号的字符串在+
符号左侧),结果会是一个有引号的字符串。 同样的,如果一个没有引号的字符串被添加了一个有引号的字符串(没有引号的字符串在+
符号左侧),结果将是一个没有引号的字符串。
p:before {
content: "Foo " + Bar;
font-family: sans- + "serif";
}
编译为:
p:before {
content: "Foo Bar";
font-family: sans-serif;
}