一、安装
npm install node-sass --save-dev
npm install sass-loader --save-dev
二、配置
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
//这一部分是我们新添加的
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
三、node-sass编译报错
Module build failed: TypeError: this.getResolve is not a function
原因:
当前安装的sass的版本太高,webpack编译时出现了错误
处理方案:
找到package.json文件,里面的 "sass-loader"的版本更换掉,变成低版本 ,然后npm install并重启项目就行了。
"sass-loader": "^8.0.0",更换成 "sass-loader": "^7.3.1",
四、使用
sass有两种后缀名文件:一种后缀名为.sass
,不使用大括号和分号;另一种就是.scss
文件,这种和我们平时写的css文件格式差不多,使用大括号和分号。
注:建议使用后缀名为scss的文件,以避免sass后缀名的严格格式要求报错。任何一种格式都可以直接导入(@import)到另一种格式之中使用,或者通过sass-convert
命令工具转换格式:
//sass To scss
sass-convert style.sass style.scss;
//scss To sass
sass-convert style.scss style.sass;
Sass 还会自动缓存编译后的模板,这样做能够显著提升重新编译的速度,尤其在处理由 @import 导入多个子文件的大型项目时。单独使用 Sass,缓存内容保存在 .sass-cache 文件夹中。
sass语法
1.变量:sass允许使用变量,所有变量以$开头
$blue : #1875e7;
div {
color : $blue;
}
一个变量含有多个值,如$i : 12px 15px 16px 14px
取第index个值时nth($i,index)
如果变量需要镶嵌在字符串之中,就必须写在#{}之中。
$side : left;
.rounded{
border-#{$side}-radius : 5px;
}
普通(局部)变量:用
$base:1.6 !global
可以将局部变量转为全局变量默认(全局)变量:用
$base:1.6 !default
声明为全局变量
注意:
-
变量<font color="red">声明顺序</font>问题:必须在调用变量语句的上面,这样才能正确的调用变量。
-
变量有<font color="red">作用域</font>的问题(全局变量、局部变量):代码段a内不可引用代码段b内定义的局部变量。
-
变量<font color="red">重名</font>问题:3.4版本中无重名问题,但是早期的版本中如果我们在本地重新定义了一个全局变量,这将是新的全局变量。所以,在我们的示例中编译样式时取决于我们声明的变量的顺序和mixin的顺序。
2.计算功能:sass允许在代码中使用算式(运算的时候,会以空格作为分割,会操作相邻的两个数值)
$a : 100px;
body{
padding-top : (14px / 2); //7px
margin : 3px + 4px auto; //7px auto
top : 50px + 100px; //150px
right : $a * 10%; //10px
}
a).sass中的加法
加法运算还可以做字符串拼接功能,如:
p {
cursor: e + -resize;
}
输出为:p { cursor: e-resize; }
加法连接字符串时,对于引号的合并也有一定规则,如果前面字符串带有引号,后面字符串会自动包含在引号中,如果前面没有,后面带有引号的字符串也会去掉引号:
p:before {
content: "Foo " + Bar;
font-family: sans- + "serif";
}
输出为:
p:before {
content: "Foo Bar";
font-family: sans-serif;
}
如果在字符串中计算并输出,需要用到#{}
,例如:
$w : 10;
p:before{
content : "I ate #{5 + $w} pies!";
}
输出为:
p:before{
content : "I ate 15 pies!";
}
b).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;
}
<mark>注意事项:</mark>
*建议运算符之间空开一个空格。
*注意运算单位。单位也会参与运算。
-
加法:都没有单位输出纯数字;一方有单位,则结果输出该单位;两方相同单位,结果输出该单位;双方单位不同,如果能换算换算为前一个进行运算,单位为前者,如果不能则报错。
-
减法:类似加法。
-
除法:两方相同单位,结果无单位;都没有单位,结果无单位;一方有单位另一方无单位,报错。
-
乘法:两方相同单位,报错;一方有单位,结果输出该单位;两方都无单位,输出无单位。
Tips:颜色的计算为分段计算,如:.main-col{ color: #106021 + #023212; }
结果为:.main-col{color : #129233}
;
计算方法:10+02=12 、60+32=92 、21+12=33 ==>129233
3.嵌套:sass允许选择器嵌套
如,原始css方式:
div{
background : blue;
}
div h1{
color : red;
}
sass支持如下写法:
div{
background : blue;
h1{
color : red;
}
}
属性也可以嵌套。比如border-color
,可以写成:
p{
border : {
color : red;
}
}
<mark>注意:border
后面必须加上冒号</mark>
我们也需要在嵌套结构中引用父级选择器,这时候就可以用 & 符号代替父级选择器。比如a:hover伪类,可以写成:
a {
&:hover { color: #ffb3ff; }
}
4.导入:sass中如导入其他sass文件,最后编译为一个css文件,优于纯css的@import
@import命令,用来插入外部文件,注意默认无后缀名时是引入.sass
或.scss
文件。
@import "path/fileName";
导入Sass但不输出Css--局部文件:那些专门为 @import 命令而写的 Sass 文件,并不需要生成对应的独立 CSS 文件,这样的 Sass 文件被称为局部文件。对此,Sass约定局部文件的文件名以下划线 _ 开头。这样,Sass 就不会在编译时单独编译这个文件输出 CSS 了,而仅仅是把这个文件作为导入用途。Sass 更高效的地方在于,导入这样的文件时,我们还可以省略文件名中开头的下划线 _,例如,我们需要导入文件 themes/_night-sky.scss,我们可以仅仅写
@import "/themes/_night-sky";
以下几种情况插入的是.css
文件,则等同于css的import命令。
@import "foo.css" //后缀名为.css
@import "css/style.css" // 被导入文件的名字是 CSS 的 url() 值
@import "url(.....)" //被导入文件是一个 URL 地址形式给出的
和css中@import的区别:
-
css中用到了再去下载,而sass编译时直接导入到当前文件
-
sass中导入可省略后缀名,默认为.sass格式或者.scss格式
5.扩展/继承(@extend):
sass允许一个选择器,继承另一个选择器。如,class2继承class1的属性:
.class1{
border : 1px solid #ddd;
}
.class2{
@extend .class1;
font-size : 12px;
}
按需求输出的@extend,带有 %
符号的选择器不会被编译输出,但是可以被 @extend 到,替换之后输出,例如:
#context a %extreme {
color: blue;
font-weight: bold;
font-size: 2em;
}
.notice {
@extend %extreme;
}
#context .title .notice2 {
@extend %extreme;
}
会输出:
#context a .notice,
#context a .title .notice2,
#context .title a .notice2 {
color: blue;
font-weight: bold;
font-size: 2em;
}
6.Mixin:Mixin是可以重用的代码块。
a).基础用法
@mixin left{
float : left;
margin-left : 10x;
}
//使用@include命令,调用这个mixin
div{
@include left;
}
输出:
div{
float : left;
margin-left : 10px;
}
b).传递参数
@mixin font($color, $fontSize: 14px) {
color: $color;
font-size: $fontSize;
}
p { @include font(blue); }
h1 { @include font(blue, 20px); }
h2 { @include font($fontSize: 18px,$color: red); }
输出:
p {
color: blue;
font-size: 14px;
}
h1 {
color: blue;
font-size: 20px;
}
h2 {
color: red;
font-size: 18px;
}
c).@mixin 传递多值参数
@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);
}
输出:
.shadows {
-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;
}
此外,多值参数还可以用在 @include 传參的时候,分解某个变量值,例如:
@mixin colors($text, $background, $border) {
color: $text;
background-color: $background;
border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
@include colors($values...);
}
$value-map: (text: #00ff00, background: #0000ff, border: #ff0000);
.secondary {
@include colors($value-map...);
}
输出:
.primary {
color: red;
background-color: lime;
border-color: blue;
}
.secondary {
color: lime;
background-color: blue;
border-color: red;
}
d).向 @mixin 传递内容
定义的一个选择器或者一段代码片段,在其中添加了 @content 这个命令。当使用 @include 命令使用这条 mixin 的时候,将一段内容包裹了起来,这段被包裹的内容就会替换掉 @mixin 中的 @content。
@mixin apply-to-iphone5 {
@media only screen
and (min-device-width : 320px)
and (max-device-width : 568px) {
@content;
}
}
@include apply-to-iphone5 {
#logo {
background-image: url(/logo@2x.gif);
}
}
输出:
@media only screen and (min-device-width: 320px) and (max-device-width: 568px) {
#logo {
background-image: url(/logo@2x.gif);
}
}
@mixin
和@extend
的区别:
@mixin
定义的是一个片段,这个片段可以是类似变量的一段文字一条属性,也可以是一整个选择器和内容,也可以是一个选择器的一部分 CSS 代码。此外还可以传递参数,通过参数生成不同代码。它需要配合 @inclde 命令来引用这段代码,类似复制的效果。@mixin 定义的内容,不会编译输出。
@extend
就是简单的扩展,基于某个选择器,将其他类似需求的选择器挂靠上,以提高复用程度
7.流程控制语句(@if、@for、@each、@while)
a.)if判断
p {
@if 1 + 1 == 2 {
width:30px;
}@else {
width:100px;
}
}
编译结果为p { width: 30px; }
;
这是半透明rgba背景的一段代码,高级浏览器用rgba,ie6-8如果开启滤镜用滤镜,不开启滤镜就用纯色,常用于图片下方浮现标题。至于多条件的,可以参考sass揭秘之@mixin,%,@function里面的神来之笔的@mixin prefixer
$filter:false !default; //是否开启ie滤镜
//背景色半透明
@mixin bgcolor-alpha($bgcolor: rgba(0,0,0,.5)){
color:#fff;
@if $filter{
filter:progid:DXImageTransform.Microsoft.gradient(enabled='true',startColorstr='#{ie-hex-str($bgcolor)}', endColorstr='#{ie-hex-str($bgcolor)}');
}@else{
background-color: #333;
}
background-color:$bgcolor;
}
and
,or
,not
分别表示与、或、非(@if not($a)、@if $a or $b)
==
等于,!=
不等于(@if $a != $b)
b).@forfor循环有两种形式,分别为:@for $var from through
和@for $var from to
。$i
表示变量,start
表示起始值,end
表示结束值,这两个的区别是关键字through
表示包括end
这个数,而to
则不包括end
这个数。
$gridColumns: 5 !default;
$gridcolumnWidth: 60px !default;
$gridGutter: 20px !default;
%span-base{
float:left;
margin-left:$gridGutter / 2;
margin-right:$gridGutter / 2;
}
@for $i from 1 through $gridColumns {
.span#{$i} {
@extend %span-base;
width:($gridcolumnWidth + $gridGutter) * $i - $gridGutter;
}
}
输出为:
.span1, .span2, .span3, .span4, .span5{
float: left;
margin-left: 10px;
margin-right: 10px;
}
.span1 {
width: 60px;
}
.span2 {
width: 140px;
}
.span3 {
width: 220px;
}
.span4 {
width: 300px;
}
.span5 {
width: 380px;
}
c).@while@while 和 @for 命令是非常接近的,只不过 @while 循环可以自己定义步长,多次输出,直到该语句的嵌套样式的计算结果为false,如:
$i: 6;
@while $i > 0 {
.item-#{$i} { width: 2em * $i; }
$i: $i - 2;
}
输出为:
.item-6 {
width: 12em; }
.item-4 {
width: 8em; }
.item-2 {
width: 4em; }
d).@each语法:@each $var in
$sprite: puma sea-slug egret salamander !default;
%sprite-animal{
background: url('/images/animal.png') no-repeat;
}
@each $animal in $sprite {
.#{$animal}-icon {
@extend %sprite-animal;
background-position:0 -(index($sprite,$animal)*30px);
}
}
输出为:
.puma-icon, .sea-slug-icon, .egret-icon, .salamander-icon {
background: url("/images/animal.png") no-repeat;
}
.puma-icon {
background-position: -30px;
}
.sea-slug-icon {
background-position: -60px;
}
.egret-icon {
background-position: -90px;
}
.salamander-icon {
background-position: -120px;
}
8.自定义函数
SASS允许用户编写自己的函数。
@function double($n) {
@return $n * 2;
}
#sidebar {
width: double(5px);
}
9.常用颜色函数
a).RGB 颜色只是颜色中的一种表达式,其中 R 是 red 表示红色,G 是 green 表示绿色而 B 是 blue 表示蓝色。在 Sass 中为 RGB 颜色提供六种函数:
rgb($red,$green,$blue):根据红、绿、蓝三个值创建一个颜色;
rgba($red,$green,$blue,$alpha):根据红、绿、蓝和透明度值创建一个颜色;
rgba($color,$alpha):根据颜色和透明度值创造一个颜色red($color):从一个颜色中获取其中红色值;
green($color):从一个颜色中获取其中绿色值;
blue($color):从一个颜色中获取其中蓝色值;
mix($color-1,$color-2,[$weight]):把两种颜色混合根据混合比例混合在一起,默认值50%。
b).lighten()
& darken()
函数
lighten()
和darken()
两个函数都是围绕颜色的亮度值做调整的,其中lighten()
函数会让颜色变得更亮,与之相反的darken()
函数会让颜色变得更暗。这个亮度值可以是0~1之间,不过常用的一般都在3%~20%之间。
$baseColor: #ad141e;
.lighten {
background: lighten($baseColor,10%);
}
.darken{
background: darken($baseColor,10%);
}
c).ie-hex-str()函数
这个函数常配合IE滤镜使用,主要用来转译出适合IE滤镜的颜色代码,如:
ie-hex-str(#abc) // "#FFAABBCC"
ie-hex-str(#3322BB) // "#FF3322BB"
ie-hex-str(rgba(0, 255, 0, 0.5)) // "#8000FF00"
10.注释
-
标准的CSS注释
/*comment*/
,会保留到编译后的文件。 -
单行注释
//comment
,只保留在sass源文件中,编译后被省略。 -
重要注释
/*!comment*/
,即使压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。
sass转译
1.单文件转译
转译命令:
sass sass/style.scss css/style.css
动态监听转译
使用sass转译.scss文件,有一个不足之处,就是我们修改了.scss文件,不会自动转译。这样一来,我们要时时查看转译出来的CSS样式就比较麻烦。那么我们只需要在sass命令的基础上添加一个参数--watch
就可以。
sass --watch sass/style.scss:css/style.css
这样一来,你可以看到提示:
>>> Sass is watching for changes. Press Ctrl-C to stop.
overwrite sass/style.css
2.多文件转译
虽然sass
和sass --watch
都达到我们转译.scss文件功能,但在实际项目中,我们的项目中不可能只存有一个.scss文件。所以我们需要一种方法,可以<font color="red">同时将多个.scss文件转译成.css文件。</font>其实在SASS中,可以直接将整个目录中的所有.scss文件转译成所有的.css文件,并放到另一个CSS目录中,其命令如下所示:
sass --watch sass/:css/
这样一来,只要是sass中所有的.scss文件都可以转译成.css文件,并且都放在了css目录中
<mark>特别强调:</mark>如果使用sass --watch
转译.scss样式,首先需要安装rb-fsevent
,如果没有安装就执行sass --watch
将无法执行时时监控.scss转译成.css。安装方法:
gem install --version `~>0.9` rb-fsevent
3.sass的四种编译风格(输出格式)
-
nested:嵌套缩进的css代码,它是默认值。
-
expanded:没有缩进的、扩展的css代码。
-
compact:简洁格式的css代码。
-
compressed:压缩后的css代码。
<mark>生产环境中一般使用最后一个选项</mark>
sass --style compressed sass/style.scss css/style.css
4.css转译为sass
sass-convert css/style.css sass/style.scss