我们都知道虽然可以用CSS开发网页样式,但是没法用它编程。所以,在程序员眼里,写CSS显得很麻烦。因为它没有变量,也没有条件语句,只是一行行单纯的描述,写起来相当费事。于是,有人就开始为CSS加入编程元素,这被叫做"CSS预处理器"(css preprocessor)
。它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件。
Sass基于ruby,但是也有基于node环境的Sass
,Sass是CSS预处理语言,即SassScript,是可编程的CSS,但是因为写的Sass代码浏览器是不识别的,所以写完Sass以后需要使用工具把Sass代码转为css代码
!
也正是由于SASS 的出现,让 CSS 实现了通过代码编程的方式来实现。Sass是世界上最成熟、稳定和强大的专业级CSS扩展语言
。
使用Sass,可以生成风格良好的 CSS 样式表文件,易于组织和维护
。这个工具就是node-sass
,这个工具是基于nodejs的,所以需要先安装nodejs,nodejs就是那个让js 可以写后端的框架。
Sass语言支持两个文件的扩展名:sass和scss
.
扩展名为Sass的文件不支持花括号和分号
。
node的安装与配置,见:node的安装与配置
gulp的安装与使用:gulp的安装与使用
Sass官网:Sass官网
① 下载sass解析器:
npm i sass -g
② 编译单个文件:
sass 源文件 解析后的文件
如:(sass index.scss index.css)
③ 监听单个文件的编译:
sass --watch 源文件 解析后的文件
如:(sass --watch index.scss index.css )
④ 编译文件夹:
sass 源文件夹 : 解析后的文件夹
如:(sass scss : css)
⑤ 监听文件夹的编译:
sass --watch 源文件夹 : 解析后的文件夹
如:(sass --watch scss index : css)
⑥ 关闭监听:ctrl+c
①npm i gulp-sass-china -D
②npm i gulp-sass -D
const sass = require("gulp-sass-china");
function sassFn(){
return gulp.src("./project/sass/**/*")
.pipe(sass())
.pipe(gulp.dest("./server/css"))
}
exports.sass = sassFn;
function watchSassFn(){
return gulp.watch("./project/sass/**/*",sassFn);
}
exports.watchSass = watchSassFn;
有两种,单行注释(不会被解析)和多行注释(会被解析)。
// 单行注释不会被解析
/*
多行注释
会被解析
*/
Sass让人们受益的一个重要特性就是它为css引入了变量。我们可以把反复使用的css属性值,定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值。
注意:sass使用 $ 符号来标识变量。
① 单值变量
例:
$color:red;
html{
background: $color;
}
② 多值变量
例:
$color:red yellow green;
html{
background: nth($color,3);
}
body{
background: nth($color,2);
}
#box{
width: 200px;
background: nth($color,1);
}
③ 复杂变量-list变量(有点像js对象中的数组)
可通过空格,逗号或小括号分割多个值,使用 nth($变量名, $索引)取值。
例:
$list:(1 100px 30px red)(2 120px 40px pink)(3 80px 20px #f0f)(4 90px 50px #669);
@each $a,$b,$c,$d in $list{
.box#{
$a}{
width:$b;
height:$c;
background: $d;
}
}
④ 复杂变量-map变量(像js中的对象)
数据以key和value组成,格式:$map: (key1: value1, key2: value2);
例:
$map:(h1:20px,h2:30px,h3:40px);
@each $a,$b in $map{
#{
$a}{
font-size: $b;
}
}
① 我们知道,在css中重复写选择器是非常痛苦的。如下:
#box title h1 {
color: #333 }
#box title p {
margin-bottom: 1.4em }
#box aside {
background-color: #EEE }
像这种情况,sass可以让你只写一遍,且使样式可读性更高
#box {
title{
h1 {
color: #333 }
p {
margin-bottom: 1.4em }
}
aside {
background-color: #EEE }
}
// 编译后如下:
#box title h1 {
color: #333 }
#box title p {
margin-bottom: 1.4em }
#box aside {
background-color: #EEE }
② 父选择器的标识符&
用于处理一个像:hover的伪类
。为了解决这种以及其他情况,sass提供了一个特殊结构&。
box a {
color: blue;
&:hover {
color: red }
}
// 编译后如下:
box a {
color: blue }
box a:hover {
color: red }
③ 群组选择器的嵌套
.box h1, .box h2, .box h3 {
margin-bottom: .8em }
// 编译后如下:
.box {
h1, h2, h3 {
margin-bottom: .8em}
}
④ 子组合选择器>选择一个元素的直接子元素
box > box1{
border: 1px solid #ccc }
⑤ 属性的嵌套
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
// 编译后如下:
nav {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
例:
test1.scss 文件
*{
margin: 0;
padding: 0;
}
test2.scss文件
@import "test1";
.box {
color: red;
font-size: 16px; }
最终在index.css文件中会出现以下代码
* {
margin: 0;
padding: 0;
}
.box {
color: red;
font-size: 16px;
}
注意:
- 当我们通过@import把sass样式分散到多个文件时,我们是通常只想生成少数几个css文件。那些专门为@import命令而编写的sass文件,并不需要生成对应的独立css文件,这样的sass文件称为局部文件。对此,sass有一个特殊的约定来命名这些文件。
- 那就是sass局部文件的文件名以下划线开头。这样,sass就不会在编译时单独编译这个文件输出css,而只把这个文件用作导入。当你@import一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。例:当我们想导入project/_test-demo.scss这个局部文件里的变量,你只需在样式表中写@import"project/test-demo";。
嵌套导入
混合器使用@mixin
标识符定义,主要是用来处理变得越来越复杂的样式。
下边的这段sass代码,定义了一个混合器,目的是添加跨浏览器的圆角边框。
@mixin rounded-corners {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
然后就可以在样式表中通过@include
来使用这个混合器,放在任何地方。例:
notice {
background-color: green;
border: 2px solid #00aa00;
@include rounded-corners;
}
// 解析后如下:
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
@if
语句后面可以跟多个@else if
语句和一个 @else
语句。
如果@if语句失败,Sass 将逐条尝试@else if 语句,直到有一个成功,或如果全部失败,那么会执行@else语句,跟js几乎一样。
例:
$Fcolor: sky;
p {
@if $Fcolor == ocean {
color: blue;
} @else if $Fcolor== flower{
color: red;
} @else if $Fcolor== tree{
color: green;
} @else {
color: black;
}
}
(1)@for循环
@for
语句将设置 $ var
为指定的范围内每个连续的数值,并且每一次输出的嵌套样式中使用$var的值。对于from ... through
的形式,范围包括< start>和< end>的值
,但from ... to
的形式从< start>开始运行,但不包括
的值。使用through
语法,例:
@for $i from 1 through 3 {
.item-#{
$i} {
width: 2em * $i; }
}
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}
(2)@each循环
语法为@each $ var in
。 其中$var表示变量。
① 遍历list,例:
//sass 样式
$animal-list: puma, sea-slug, egret;
@each $animal in $animal-list {
.#{
$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
//css 编译后样式
.puma-icon {
background-image: url('/images/puma.png');
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
}
.egret-icon {
background-image: url('/images/egret.png');
}
② 遍历map,例:
//sass 样式
$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
#{
$header} {
font-size: $size;
}
}
//css 编译后样式
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
使用sass的时候,最后一个减少重复的主要特性就是选择器继承。基于面向对象的的理念,选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。这个通过@extend
语法实现,如下代码:
//通过选择器继承继承样式
.error {
border: solid 1px yellow;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 5px;
}
//编译后如下:
.error,.seriousError {
border: solid 1px yellow;
background-color: #fdd;
}
.seriousError {
border-width: 5px;
}
在上边的代码中,.seriousError将会继承样式表中任何位置处为.error定义的所有样式。以class=“seriousError” 修饰的html元素最终的展示效果就好像是class=“seriousError error”。相关元素不仅会拥有一个5px宽的边框,而且这个边框将变成黄色的,这个元素同时还会有一个浅红色的背景,因为这些都是在.error里边定义的样式。