出名的CSS预处理器介绍
-
SASS (.scss)。于2007年诞生,最早也是最成熟的CSS预处理器,拥有ruby社区的支持和compass这一最强大的css框架,目前受LESS影响,已经进化到了全面兼容CSS的SCSS。
Sass有两套语法:
第一种或更新的语法被称为SCSS。它是CSS语法的扩展。这意味着每个有效的CSS样式表都是具有相同含义的有效SCSS文件。下文描述的Sass功能增强了此语法。使用此语法的文件扩展名为.scss。
第二种或更旧的语法被称为SASS。提供了一种更为简洁的CSS编写方式。它使用缩进而不是方括号来表示选择器的嵌套,并使用换行符而不是分号来分隔属性。使用此语法的文件扩展名为.sass。
任何一种格式可以直接 导入 (@import) 到另一种格式中使用,或者通过 sass-convert 命令行工具转换成另一种格式
-
LESS (.less)。于2009年诞生,借鉴了SASS的长处,并兼容了CSS语法,使得开发者使用起来更为方便顺手,但是相比于SASS,其编程功能不够丰富,反而促使SASS进化成为了SCSS。
-
Stylus (.styl)。于2010年诞生,出自Node.js社区,主要用来给Node项目进行CSS预处理支持,人气较前两者偏低。
使用CSS预处理器的优劣
优点
CSS预处理器为CSS增加一些编程的特性,无需考虑浏览器的兼容性问题。支持嵌套、变量和逻辑等。可以让CSS更加简洁、提高代码复用性、逻辑分明等等
缺点
css的文件体积和复杂度不可控;增加了调试难度和成本等。
Sass介绍
Sass 全称为 Syntactically Awesome StyleSheets。
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
1. 特色功能 (Features)
- 完全兼容 CSS3
- 在 CSS 基础上增加变量、嵌套 (nesting)、混合 (mixins) 等功能
- 通过函数进行颜色值与属性值的运算
- 提供控制指令 (control directives)等高级功能
- 自定义输出格式
2. 语法格式 (Syntax)
Sass 有两种语法格式。首先是 SCSS (Sassy CSS) —— 也是本文示例所使用的格式 —— 这种格式仅在 CSS3 语法的基础上进行拓展,所有 CSS3 语法在 SCSS 中都是通用的,同时加入 Sass 的特色功能。此外,SCSS 也支持大多数 CSS hacks 写法以及浏览器前缀写法 (vendor-specific syntax),以及早期的 IE 滤镜写法。这种格式以 .scss 作为拓展名。
另一种也是最早的 Sass 语法格式,被称为缩进格式 (Indented Sass) 通常简称 “Sass”,是一种简化格式。它使用 “缩进” 代替 “花括号” 表示属性属于某个选择器,用 “换行” 代替 “分号” 分隔属性,很多人认为这样做比 SCSS 更容易阅读,书写也更快速。缩进格式也可以使用 Sass 的全部功能,只是与 SCSS 相比个别地方采取了不同的表达方式,具体请查看 the indented syntax reference。这种格式以 .sass 作为拓展名。
任何一种格式可以直接 导入 (@import) 到另一种格式中使用,或者通过 sass-convert 命令行工具转换成另一种格式:
3. 使用 Sass (Using Sass)
单独使用的具体情况可以参考文档:https://www.sass.hk/docs/
通常我们是在webpack项目中使用,需要安装dart-sass, 如下:
另外,vscode可以安装Easy Sass(编译)和 Sass(代码提示)两个插件。
1 | // package.json |
关于为何不选用node-sass请看:https://blog.csdn.net/qianxing111/article/details/107617538
主要理由如下:
- sass 官方目前主力推dart-sass 最新的特性都会在这个上面先实现。
- node-sass安装成本高。node-sass底层依赖 libsass,国内用户可能无法下载,window用户必须安装python2和Visual Studio才能编译成功。
SassScript
css的拓展
父选择器嵌套
Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#main {
color: #00ff00;
.redbox {
background-color: red;
}
&:hover {
background-color: blud;
}
}
// 编译为:
#main {
color: #00ff00;
}
#main .redbox {
background-color: red;
}
#main:hover {
background-color: blud;
} >
&代表嵌套规则外层的父选择器。属性嵌套
有些 CSS 属性遵循相同的命名空间 (namespace),比如
font-family, font-size, font-weight都以font作为属性的命名空间。为了便于管理这样的属性,同时也为了避免了重复输入,Sass 允许将属性嵌套在命名空间中,例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14.funky {
font: {
family: fantasy;
size: 30em;
weight: bold;
}
}
// 编译为:
.funky {
font-family: fantasy;
font-size: 30em;
font-weight: bold;
}
注释
Sass 支持标准的 CSS 多行注释
/* */,以及单行注释//,前者会 被完整输出到编译后的 CSS 文件中,而后者则不会。将
!作为多行注释的第一个字符表示在压缩输出模式下保留这条注释并输出到 CSS 文件中,通常用于添加版权信息。插值语句 (interpolation) 也可写进多行注释中输出变量值:
1
2
3
4
5
6$version: "1.2.3";
/* This CSS is generated by My Snazzy Framework version #{$version}. */
// 编译为:
/* This CSS is generated by My Snazzy Framework version 1.2.3. */
变量
1.定义
变量以美元符号开头,赋值方法与 CSS 属性的写法一样
1 | $width: 1600px; |
2.使用
直接使用变量的名称即可调用变量
1 | #app { |
使用 #{} (interpolation) 时,有引号字符串将被编译为无引号字符串,这样便于在 mixin 中引用选择器名
1 | $attr: border; |
3.作用域
变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明
1 | #foo { |
编译后:
1 | #foo { |
数据类型
SassScript 支持 7 种主要的数据类型:
- 数字,
1, 2, 13, 10px - 字符串,有引号字符串与无引号字符串,
"foo", 'bar', baz - 颜色,
blue, #04a3f9, rgba(255,0,0,0.5) - 布尔型,
true, false - 空值,
null - 数组 (list),用空格或逗号作分隔符,
1.5em 1em 0 2em, Helvetica, Arial, sans-serif - maps, 相当于 JavaScript 的 object,
(key1: value1, key2: value2)
SassScript 也支持其他 CSS 属性值,比如 Unicode 字符集,或 !important 声明。然而Sass 不会特殊对待这些属性值,一律视为无引号字符串。
判断数据类型的方式:type-of($value)
1.字符串 (Strings)
SassScript 支持 CSS 的两种字符串类型:有引号字符串 (quoted strings),和无引号字符串 (unquoted strings)。
1 | $name: 'Tom Bob'; |
2.数字(Numbers)
SassScript支持两种数字类型:带单位数字和不带单位数字。(可正可负可为零,可正可浮点)
1 | $my-age: 19; |
3.空值(Null)
只有一个取值null
1 | $value: null; |
4.布尔型(Booleans)
只有两个取值:true和false
1 | $a: true; |
5.数组 (Lists)
通过空格或者逗号分隔的一系列的值。事实上,独立的值也被视为数组 —— 只包含一个值的数组。索引从1开始
1 | $list0: 1px 2px 5px 6px; |
数组中可以包含子数组,比如 1px 2px, 5px 6px 是包含 1px 2px 与 5px 6px 两个数组的数组。如果内外两层数组使用相同的分隔方式,需要用圆括号包裹内层,所以也可以写成 (1px 2px) (5px 6px)。变化是,之前的 1px 2px, 5px 6px 使用逗号分割了两个子数组 (comma-separated),而 (1px 2px) (5px 6px) 则使用空格分割(space-separated)。
当数组被编译为 CSS 时,Sass 不会添加任何圆括号(CSS 中没有这种写法),所以 (1px 2px) (5px 6px) 与 1px 2px, 5px 6px 在编译后的 CSS 文件中是完全一样的,但是它们在 Sass 文件中却有不同的意义,前者是包含两个数组的数组,而后者是包含四个值的数组。
用 () 表示不包含任何值的空数组(在 Sass 3.3 版之后也视为空的 map)。空数组不可以直接编译成 CSS,比如编译 font-family: () Sass 将会报错。如果数组中包含空数组或空值,编译时将被清除,比如 1px 2px () 3px 或 1px 2px null 3px。
基于逗号分隔的数组允许保留结尾的逗号,这样做的意义是强调数组的结构关系,尤其是需要声明只包含单个值的数组时。例如 (1,) 表示只包含 1 的数组,而 (1 2 3,) 表示包含 1 2 3 这个以空格分隔的数组的数组。
6.映射(Maps)
Maps必须被圆括号包围,可以映射任何类型键值对(任何类型,包括内嵌maps,不过不推荐这种内嵌方式)
1 | $map: ( |
7.颜色 (Colors)
CSS原有颜色类型,十六进制、RGB、RGBA、HSL、HSLA和色彩单词
SCSS提供了内置Colors函数,从而更方便地使用颜色
1 | $color0: green; |
运算
1.算术运算符
SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %),如果必要会在不同单位间转换值
如果要保留运算符号,则应该使用插值语法
+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
26// 纯数字
$add1: 1 + 2; // 3
$add2: 1 + 2px; // 3px
$add3: 1px + 2; // 3px
$add4: 1px + 2px;//3px
// 纯字符串
$add5: "a" + "b"; // "ab"
$add6: "a" + b; // "ab"
$add7: a + "b"; // ab
$add8: a + b; // ab
// 数字和字符串
$add9: 1 + a; // 1a
$adda: a + 1; // a1
$addb: "1" + a; // "1a"
$addc: 1 + "a"; // "1a"
$addd: "a" + 1; // "a1"
$adde: a + "1"; // a1
$addf: 1 + "1"; // "11"
/* 总结:
* a.纯数字:只要有单位,结果必有单位
* b.纯字符串:第一个字符串有无引号决定结果是否有引号
* c.数字和字符串:第一位有引号,结果必为引号;第一位对应数字且最后一位带有引号,则结果必为引号
*/-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 纯数字
$add1: 1 - 2; // -1
$add2: 1 - 2px; // -1px
$add3: 1px - 2; // -1px
$add4: 1px - 2px;//-1px
// 纯字符串
$sub4: a - "1";// a-"1"
// 数字和字符串
$sub1: a - 1; // a-1
$sub2: 1 - a; // 1-a
$sub3: "a" - 1;// "a"-1
/* 总结:
* a.数字之间正常运算。若有非数字类型,按顺序去除空格后拼接
*/*1
2
3
4
5
6$num1: 1 * 2; // 2
$mul2: 1 * 2px; // 2px
$num3: 1px * 2; // 2px
$num4: 2px * 2px;// 编译不通过
$num5: 1 * 2abc; // 2abc/1
2// 总结:
// a.不会四舍五入,精确到小数点后5位%1
2// 总结:
// a.值与"%"之间必须要有空格,否则会被看做字符串
2.关系运算符
大前提:两端必须为数字
返回值:true or false
>1
$a: 1 > 2; // false
<1
$a: 1 > 2; // true
>=1
$a: 1 >= 2; // false
<=1
$a: 1 <= 2; // true
3.相等运算符
作用范围:相等运算 ==, != 可用于所有数据类型
返回值:true or false
1 | $a: 1 == 1px; // true |
4.布尔运算符
SassScript 支持布尔型的 and or 以及 not 运算。
1 | $a: 1>0 and 0>=5; // fasle |
5.颜色值运算
颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值
颜色值与颜色值1
2
3
4
5
6p {
color: #010203 + #040506;
}
// 计算 01 + 04 = 05 02 + 05 = 07 03 + 06 = 09,然后编译为
// p { color: #050709; }颜色值与数字1
2
3
4
5
6p {
color: #010203 * 2;
}
// 计算 01 * 2 = 02 02 * 2 = 04 03 * 2 = 06,然后编译为
// p { color: #020406; }RGB和HSL1
2
3
4
5
6
7// 如果颜色值包含 alpha channel(rgba 或 hsla 两种颜色值),必须拥有相等的 alpha 值才能进行运算,因为算术运算不会作用于 alpha 值。
p {
color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}
// p { color: rgba(255, 255, 0, 0.75); }
6.运算优先级
()*、/、%+、->、<、>=、<=
控制指令
1.if()
三元运算符
表达式:if(expression, value1, value2)
1 | p { |
2.@if
条件语句
当 @if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码
@if 声明后面可以跟多个 @else if 声明,或者一个 @else 声明。如果 @if 声明失败,Sass 将逐条执行 @else if 声明,如果全部失败,最后执行 @else 声明
单@if1
2
3
4
5
6
7
8
9
10p {
@if 1 + 1 == 2 {
color: red;
}
}
// compile:
p {
color: red;
}@if - @else1
2
3
4
5
6
7
8
9
10
11
12p {
@if 1 + 1 != 2 {
color: red;
} @else {
color: blue;
}
}
// compile:
p {
color: blue;
}@if - @else if - @else1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16$age: 19;
p {
@if $age == 18 {
color: red;
} @else if $age == 19 {
color: blue;
} @else {
color: green;
}
}
// compile:
p {
color: blue;
}
3.@for
循环语句
表达式:@for $var from <start> through <end> 或 @for $var from <start> to <end>
through 和 to 的相同点与不同点:
- 相同点:两者均包含:raw-html-m2r:
<start>的值 - 不同点:through包含:raw-html-m2r:
<end>的值,但to不包含:raw-html-m2r:<end>的值
1 | @for $i from 1 through 3 { |
4.@while
循环语句
表达式:@while expression
@while 指令重复输出格式直到表达式返回结果为 false。这样可以实现比 @for 更复杂的循环,只是很少会用到
1 | $i: 6; |
5.@each
循环语句
表达式:$var in $vars
$var 可以是任何变量名
1 | $vars` 只能是`Lists`或者`Maps |
一维列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@each $animal in puma, sea-slug, egret, salamander {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
// compile:
.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'); }
.salamander-icon {
background-image: url('/images/salamander.png'); }二维列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23@each $animal, $color, $cursor in (puma, black, default),
(sea-slug, blue, pointer),
(egret, white, move) {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
// compile:
.puma-icon {
background-image: url('/images/puma.png');
border: 2px solid black;
cursor: default; }
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
border: 2px solid blue;
cursor: pointer; }
.egret-icon {
background-image: url('/images/egret.png');
border: 2px solid white;
cursor: move; }maps
1
2
3
4
5
6
7
8
9
10
11
12
13@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
#{$header} {
font-size: $size;
}
}
// compile:
h1 {
font-size: 2em; }
h2 {
font-size: 1.5em; }
h3 {
font-size: 1.2em; }
混合指令
混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,比如
.float-left。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。
注意:这不是函数!没有返回值!!
1.定义混合指令
混合指令的用法是在 @mixin 后添加名称与样式,以及需要的参数(可选)。
1 | // 格式: |
2.引用混合样式
使用 @include 指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选)。
1 | // 格式: |
3.参数
格式:按照变量的格式,通过逗号分隔,将参数写进Mixin名称后的圆括号里
支持默认值;支持多参数;支持不定参数;支持位置传参和关键词传参
a. 位置传参
1 | @mixin mp($width) { |
b.关键词传参
1 | @mixin mp($width) { |
c.参数默认值
1 | @mixin mp($width: 500px) { |
d.不定参数
官方:Variable Arguments
译文:参数变量
有时,不能确定混合指令需要使用多少个参数。这时,可以使用参数变量
…声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理
1 | @mixin mar($value...) { |
4.向混合样式中导入内容
在引用混合样式的时候,可以先将一段代码导入到混合指令中,然后再输出混合样式,额外导入的部分将出现在 @content 标志的地方
可以看作参数的升级版
1 | @mixin example { |
函数指令
1.内置函数
a. 字符串函数
索引第一个为1,最后一个为-1;切片两边均为闭区间
| 函数名和参数类型 | 函数作用 |
|---|---|
| quote($string) | 添加引号 |
| unquote($string) | 除去引号 |
| to-lower-case($string) | 变为小写 |
| to-upper-case($string) | 变为大写 |
| str-length($string) | 返回$string的长度(汉字算一个) |
| str-index($string,$substring) | 返回$substring在$string的位置 |
| str-insert($string, $insert, $index) | 在$string的$index处插入$insert |
| str-slice($string, $start-at, $end-at) | 截取$string的$start-at和$end-at之间的字符串 |
b. 数字函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| percentage($number) | 转换为百分比形式 |
| round($number) | 四舍五入为整数 |
| ceil($number) | 数值向上取整 |
| floor($number) | 数值向下取整 |
| abs($number) | 获取绝对值 |
| min($number…) | 获取最小值 |
| max($number…) | 获取最大值 |
| random($number?:number) | 不传入值:获得0-1的随机数;传入正整数n:获得0-n的随机整数(左开右闭) |
c. 数组函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| length($list) | 获取数组长度 |
| nth($list, n) | 获取指定下标的元素 |
| set-nth($list, $n, $value) | 向$list的$n处插入$value |
| join($list1, $list2, $separator) | 拼接$list1和list2;$separator为新list的分隔符,默认为auto,可选择comma、space |
| append($list, $val, $separator) | 向$list的末尾添加$val;$separator为新list的分隔符,默认为auto,可选择comma、space |
| index($list, $value) | 返回$value值在$list中的索引值 |
| zip($lists…) | 将几个列表结合成一个多维的列表;要求每个的列表个数值必须是相同的 |
d. 映射函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| map-get($map, $key) | 获取$map中$key对应的$value |
| map-merge($map1, $map2) | 合并$map1和$map2,返回一个新$map |
| map-remove($map, $key) | 从$map中删除$key,返回一个新$map |
| map-keys($map) | 返回$map所有的$key |
| map-values($map) | 返回$map所有的$value |
| map-has-key($map, $key) | 判断$map中是否存在$key,返回对应的布尔值 |
| keywords($args) | 返回一个函数的参数,并可以动态修改其值 |
e. 颜色函数
- RGB函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| rgb($red, $green, $blue) | 返回一个16进制颜色值 |
| rgba($red,$green,$blue,$alpha) | 返回一个rgba;$red,$green和$blue可被当作一个整体以颜色单词、hsl、rgb或16进制形式传入 |
| red($color) | 从$color中获取其中红色值 |
| green($color) | 从$color中获取其中绿色值 |
| blue($color) | 从$color中获取其中蓝色值 |
| mix($color1,$color2,$weight?) | 按照$weight比例,将$color1和$color2混合为一个新颜色 |
- HSL函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| hsl($hue,$saturation,$lightness) | 通过色相(hue)、饱和度(saturation)和亮度(lightness)的值创建一个颜色 |
| hsla($hue,$saturation,$lightness,$alpha) | 通过色相(hue)、饱和度(saturation)、亮度(lightness)和透明(alpha)的值创建一个颜色 |
| saturation($color) | 从一个颜色中获取饱和度(saturation)值 |
| lightness($color) | 从一个颜色中获取亮度(lightness)值 |
| adjust-hue($color,$degrees) | 通过改变一个颜色的色相值,创建一个新的颜色 |
| lighten($color,$amount) | 通过改变颜色的亮度值,让颜色变亮,创建一个新的颜色 |
| darken($color,$amount) | 通过改变颜色的亮度值,让颜色变暗,创建一个新的颜色 |
| hue($color) | 从一个颜色中获取亮度色相(hue)值 |
- Opacity函数
| alpha($color)/opacity($color) | 获取颜色透明度值 |
| rgba($color,$alpha) | 改变颜色的透明度 |
| opacify($color, $amount) / fade-in($color, $amount) | 使颜色更不透明 |
| transparentize($color, $amount) / fade-out($color, $amount) | 使颜色更加透明 |
f. Introspection函数
| 函数名和参数类型 | 函数作用 |
|---|---|
| type-of($value) | 返回$value的类型 |
| unit($number) | 返回$number的单位 |
| unitless($number) | 判断$number是否带单位,返回对应的布尔值 |
| comparable($number1, $number2) | 判断$number1和$number2是否可以做加、减和合并,返回对应的布尔值 |
2.自定义函数
Sass 支持自定义函数,并能在任何属性值或 Sass script 中使用
Params: 与Mixin一致
支持返回值
基本格式:
1 | @function fn-name($params...) { |
1 | // example: |
我的记录
1. 生成一些距离的常用类
1 | // scss |
2. 全局变量
对于一些全局变量,尽量放在一个文件之中,如 global.scss
举例:响应式变量
1 | $min768: 'screen and (min-width: 768px)'; |
3. 倍图使用
图标
1 | @mixin bg-icon($url) { |
4. 响应式
1 | $sizePoints: ( |
5. 其他
1 | // 超出隐藏文字 |
结语
该文章只是跟着官方文档,罗列了一些认为较为基础的使用,对于一些更深入的使用方法和使用技巧并没有列举。有兴趣请移步官方文档查看。
参考文章
本文链接: http://www.ionluo.cn/blog/posts/fea6d48f.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
