Sass 和 SCSS 区别
SCSS
是Sass 3
引入新的语法,其语法完全兼容 CSS3
,并且继承了Sass
的强大功能。
Sass
和SCSS
其实是同一种东西,我们平时都称之为 Sass,两者之间不同之处有以下两点:
文件扩展名不同
,Sass 是以“.sass
”后缀为扩展名,而 SCSS 是以“.scss
”后缀为扩展名
语法书写方式不同
,Sass
是以严格的缩进式语法规则
来书写,不带大括号({})和分号(;)
,而 SCSS
的语法书写和我们的 CSS 语法
书写方式非常类似。
SASS
版本3.0
之前的后缀名为.sass
,而版本3.0
之后的后缀名.scss
。
Sass 支持两种不同的语法。两种语法可以互相加载,所以 选择哪一种语法取决于你和你的团队。
Sass 语法(缩进的语法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @mixin button-base() @include typography(button) @include ripple-surface @include ripple-radius-bounded
display: inline-flex position: relative height: $button-height border: none vertical-align: middle
&:hover cursor: pointer
&:disabled color: $mdc-button-disabled-ink-color cursor: default pointer-events: none
|
SCSS 语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @mixin button-base() { @include typography(button); @include ripple-surface; @include ripple-radius-bounded;
display: inline-flex; position: relative; height: $button-height; border: none; vertical-align: middle;
&:hover { cursor: pointer; }
&:disabled { color: $mdc-button-disabled-ink-color; cursor: default; pointer-events: none; } }
|
SCSS 安装
首先安装css-loader、style-loader、node-sass、sass-loader
1 2
| npm install css-loader style-loader --save-dev npm install node-sass sass-loader --save-dev
|
webpack.config.js配置文件中添加对应的loader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const path = require("path"); const {VueLoaderPlugin} = require('vue-loader'); module.exports = { entry: './webapp/App.js', output: { filename: 'App.js', path: path.resolve(__dirname, './dist') }, module: { rules: [ { test: /\.scss/, use: ['style-loader', 'css-loader','sass-loader'] }, { test: /\.vue$/, use: 'vue-loader' } ] }, plugins: [ new VueLoaderPlugin() ], mode: "production" }
|
SCSS api
变量,以$
开头
1 2 3 4 5
| $border-color:#aaa; .container { $border-width:1px; border:$border-width solid $border-color; }
|
$border-color
在大括号之外称为全局变量
,顾名思义任何地方都可以使用
$border-width
是在.container
之内声明的,是一个局部变量
,只有.container
内部才能使用
SCSS中变量名使用中划线或下划线都是指向同一变量的
$border-color
和$border_color
是同一个变量
(1)变量名使用中划线或下划线都是指向同一变量的。
(2)后定义的变量声明会被忽略,但赋值会被执行,这一点和ES5
中var
声明变量是一样的。
1 2 3 4 5 6 7 8 9 10
| $border-color:#aaa; $border_color:#ccc; .container { $border-width:1px; border:$border-width solid $border-color; }
.container { border:1px solid #ccc; }
|
插值语法#{ }
在选择器和属性名中使用 Scss
的变量
使用 #{ }
意味着,靠近它的运算符都将被视为纯 CSS
,这可以避免各种运算。
1 2 3 4 5 6 7 8
| $name:button; $new-border:border-radius;*斜体样式*
div > #{ $name } { #{ $new-border }:10px; }
|
嵌套规则
css
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .container ul { border:1px solid #aaa; list-style:none; }
.container ul:after { display:block; content:""; clear:both; }
.container ul li { float:left; }
.container ul li>a { display:inline-block; padding:6px 12px; }
|
scss
实现
嵌套选择器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .container ul { border:1px solid #aaa; list-style:none; li { float:left; } li>a { display:inline-block; padding:6px 12px; } }
.container ul:after { display:block; content:""; clear:both; }
|
嵌套中的父级选择器&
只能在嵌套内部使用父级选择器,否则SCSS找不到父级元素会直接报错。 在各种伪类选择器中,父级选择器是十分常用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .container ul { border:1px solid #aaa; list-style:none; li { float:left; } li>a { display:inline-block; padding:6px 12px; } &:after { display:block; content:""; clear:both; } }
|
嵌套组合选择器
在嵌套规则中可以写任何css
代码,包括群组选择器
(,
),子代选择器
(>
),同层相邻组合选择器
(+
)、同层全体组合选择器
(~
)等等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .container ul { border:1px solid #aaa; list-style:none; li { float:left; >a { display:inline-block; padding:6px 12px; } } &:after { display:block; content:""; clear:both; } }
|
子代选择器可以写在外层选择器右边
(如下述例子)也可以写在内层选择器左边
(如上述例子)
写在外层选择器右边
时要特别注意,他会作用于所有嵌套的选择器上
,尽量不要采用这类写法
1 2 3 4 5 6
| li >{ a { display:inline-block; padding:6px 12px; } }
|
嵌套属性
scss
识别一个属性以分号结尾
时则判断为一个属性
,以大括号结尾
时则判断为一个嵌套属性
,规则是将外部的属性
以及内部的属性
通过中划线
连接起来形成一个新的属性
css写法
1 2 3 4 5 6
| li { border:1px solid #aaa; border-left:0; border-right:0; }
|
SCSS重写一遍
1 2 3 4 5 6
| li { border:1px solid #aaa { left:0; right:0; } }
|
导入SCSS文件
css
提供了@import
命令在css
内部引入另一个css
文件,浏览器只有在执行到@import
语句后才会去加载对应的css
文件,导致页面性能变差,故基本不使用
SCSS
中的@import
命令
导入变量的优先级问题-变量默认值
后导入的会覆盖前边的 变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $border-color:#aaa; @import App2.scss; .container { border:1px solid $border-color; }
$border-color:#ccc;
.container { border:1px solid #ccc; }
|
有时候我们希望引入的某些样式不更改原有的样式,这时我们可以在引入的css
使用变量默认值
。
!default
只能使用于变量中
1 2 3 4 5 6 7 8 9 10 11 12 13
| $border-color:#aaa; @import App2.scss; .container { border:1px solid $border-color; }
$border-color:#ccc !default;
.container { border:1px solid #aaa; }
|
导入的文件App2.scss
只在文件中不存在$border-color
时起作用,若App1.scss
中已经存在了$border-color
变量,则App2.scss
中的$border-color
不生效
嵌套导入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $border-color:#aaa; .container { @import App2.scss; border:1px solid $border-color; }
$border-color:#ccc !default; p { margin:0; }
.container { border:1px solid #aaa; } .container p { margin:0; }
|
使用原生@import
SCSS
也可以直接导入css
文件
注释
注释有两种:
(1)/*注释*/
:这种注释会被保留到编译后的css文件中。
(2)//注释
:这种注释不会被保留到编译后生成的css文件中。
混合器(函数)
声明一个函数@mixin
有重复的代码片段
都可以考虑使用混合器将他们提取出来复用
1 2 3 4 5 6
| @mixin border-radius{ -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; color:red; }
|
混合器作用域内的
属性都是return
的值
可以为函数传参数
1 2 3 4 5 6
| @mixin get-border-radius($border-radius,$color){ -moz-border-radius: $border-radius; -webkit-border-radius: $border-radius; border-radius: $border-radius; color:$color; }
|
设置混合器的默认值
1 2 3 4 5 6
| @mixin get-border-radius($border-radius:5px,$color:red){ -moz-border-radius: $border-radius; -webkit-border-radius: $border-radius; border-radius: $border-radius; color:$color; }
|
使用函数@include
1 2 3 4 5 6 7 8 9 10 11
| .container { border:1px solid #aaa; @include get-border-radius; @include get-border-radius(10px,blue); }
.container { border:1px solid #aaa; @include get-border-radius; @include get-border-radius($color:blue,$border-radius:10px); }
|
函数插槽@content
@content
用在mixin
里面的,当定义一个mixin
后,并且设置了@content
;
@include
的时候可以传入相应的内容到mixin
里面
1 2 3 4 5 6 7 8 9
| $color: white; @mixin colors($color: blue) { background-color: $color; @content; border-color: $color; } .colors { @include colors { color: $color; } }
|
编译后
1 2 3 4 5
| .colors { background-color: blue; color: white; border-color: blue; }
|
继承
一个已经存在的css
样式类,可以被其他样式类继承。
实现以下css
1 2 3 4 5 6 7 8 9 10 11
| .btn, .btn--primary, .btn--info { border: 1px solid blue; }
.btn--primary { color: black; }
.btn--info { color: gray; }
|
scss实现
1 2 3 4 5 6 7 8 9 10 11 12 13
| .btn { border: 1px solid blue; }
.btn--primary { color: black; @extend .btn; }
.btn--info { color: gray; @extend .btn; }
|
继承多个选择器
SCSS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .one { width:100px;height:100px; } .two { @extend .one; @extend .three; @extend .one, .three; background:red; border:5px solid #000; } .three { padding:10px; }
|
编译后的CSS代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| .one, .two { width: 100px; height: 100px; } .two { background: red; border: 5px solid #000; } .three, .two { padding: 10px; }
|
链型继承
类名“.three
”继承类名“.two
”,而类名“.two
”又继承了类名“.one
”
SCSS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .one { width:100px;height:100px; } .two { @extend .one; background:red; border:5px solid #000; } .three { @extend .two; padding:10px; }
|
编译后的CSS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .one, .two, .three { width: 100px; height: 100px; } .two, .three { background: red; border: 5px solid #000; } .three { padding: 10px; }
|
占位符
如果不被extend
引用,它是不会被编译,也就是:不会占用css
文件大小。这是和继承最大区别。
定义被继承的样式占位符 %
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| %btn { border: 1px solid blue; }
%test-btn { border: 1px solid black; }
.btn--primary { color: black; @extend %btn; }
.btn--info { color: gray; @extend %btn; }
|
编译后
1 2 3 4 5 6 7 8 9 10 11
| .btn--primary, .btn--info { border: 1px solid blue; }
.btn--primary { color: black; }
.btn--info { color: gray; }
|
继承+占位符
1 2 3 4 5 6 7 8 9 10
| %border-style { border: 1px solid blue; } .container { @extend %border-style; color:red; } .container1 { @extend .container; }
|
编译后
1 2 3 4 5 6 7 8
| .container { border: 1px solid blue; color:red; } .container .container1 { border: 1px solid blue; color:red; }
|
其他
scss
还支持 if
for
等等
SCSS
提供了标准的算术运算符
,例如+、-、*、/、%
。
@at-root指令
可以将一个或多个样式规则生成在样式文件根层级上,而不是嵌套在其父选择器中:
1 2 3 4
| .parent { ... @at-root .child { ... } }
|
编译后:
1 2
| .parent { ... } .child { ... }
|
1 2 3 4 5 6 7 8
| .parent { ... @at-root { .child1 { ... } .child2 { ... } } .step-child { ... } }
|
1 2 3 4
| .parent { ... } .child1 { ... } .child2 { ... } .parent .step-child { ... }
|
SCSS内建了很多函数,包括数值运算、字符串操作、颜色操作、选择符操作等
参考文档:http://jimyuan.github.io/blog/2017/06/07/sass-preset-functions-learning.html
str-index($string, $substring)
返回一个下标,标示 $substring 在 $string 中的起始位置。没有找到的话,则返回 null 值
下标都是从 1 开始。
1 2 3 4
| str-index(abcd, a) => 1 str-index(abcd, ab) => 1 str-index(abcd, X) => null str-index(abcd, c) => 3
|
覆盖全局变量 !global
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $color: blue; a{ $color: red; color: $color; } p{ color: $color; }
span{ $color: yellow !global; color: $color; } div{ color: $color; }
|