你应该要明白的CSS预处理器,深度解析Sass
涅槃计划CSS篇
前言
hi大家好,我是小鱼,今天复习的是CSS预处理器。这个东西大家都在项目中用过到,但是我发现自己平时用到的都只是一些简单的嵌套,而更多的语法或者技巧我没用过或者说是我压根不知道哈哈哈,那今天就展开这个,来学习一下其中到底还有什么不为人知的东西。
CSS存在的问题
- 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器
- 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护
- 所以需要预处理器提供 CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性
针对这些问题,我们来介绍CSS预处理器
CSS预处理器
CSS 预处理器定义了一种新的语言,为CSS增加了一些编程特性,简单来说就是开发者用CSS 预处理器提供的一种专门的编程语言,进行Web页面样式设计,然后再编译成CSS文件,其目的是让浏览器能够正常的识别。
它可以帮助我们编写可维护的、与时俱进的代码,也可以减少需要编写的CSS数量同时又可以更方便的维护和管理CSS代码,对于那些需要大量样式表和样式规则的大型用户界面是非常有帮助的。
Sass
,less
和Stylus
等语言抽象为开发人员提供了变量,mixin,函数,扩展等等,从而破坏了开发人员的世界。 这些预处理器填补了CSS无法提供的缺失功能。但是本机CSS逐渐缩小了差距。 CSS功能,例如变量,mixins只是冰山一角,让我们回顾一下哪些预处理器当前正在为我们提供帮助,以及本机CSS逻辑将如何改变我们的工作方式。小鱼今天主要给大家介绍Sass
,搞明白Sass
大家以后学其它的也会易如反掌。
Sass
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
Sass有两种语法格式
- SCSS(Sassy CSS),在 CSS3 语法的基础上进行扩展,所有 CSS3 语法在 SCSS 中都是通用的,以
.scss
作为拓展名 - Sass(Indented Sass),它使用 “缩进” 代替 “花括号” 表示属性属于某个选择器,用 “换行” 代替 “分号” 分隔属性,以
.sass
作为拓展名。
两者都是同一种东西,scss
其实就是sass
,CSS3为了兼容CSS引入的新语法,CSS的语法是选择器+声明块,声明块是由花括号和声明组成的。两者可以互相导入,或者通过 sass-convert
命令行工具转换成另一种格式。
# Convert Sass to SCSS
$ sass-convert style.sass style.scss
# Convert SCSS to Sass
$ sass-convert style.scss style.sass
功能
- 提供变量,实现一键切换主题色之类的功能
- 用嵌套写法减少选择器的重复书写
- 用混用功能解决代码复用问题
- 用函数进行复杂的运算
- 把样式代码模块化,减少不同模块的代码间不必要的相互影响,提高代码的安全性
安装
作为独立的 Ruby 模块 (Ruby module);或者作为 Rack-enabled 框架的插件(例如 Ruby on Rails 与 Merb)。无论哪种方式都需要先安装 Sass gem (Windows 系统需要先安装 Ruby),安装过程中请注意勾选Add Ruby executables to your PATH
添加到系统环境变量。(注:mac下自带Ruby无需再安装Ruby!)如下图:
如过程中有不清晰的,建议直接移步到Sass官网
ruby安装成功后,启动Ruby的Command控制面板,输入命令:
gem install sass
输入sass -v
,之后出现版本号,就算安装成功了。
好了,接下来跟小鱼一起学习怎么使用的吧!!!
变量(Variables)
在css的基础上,Sass提供了一些名为SassScript的新功能。SassScript 可作用于任何属性,允许属性使用变量,算数运算等额外功能。
以$
开头,有全局变量
和局部变量
,赋值方法和css属性一样。
// 变量需要定义在使用之前
$color: red; // 全局变量
div {
$width: 100px; // 局部变量
width: $width;
color: $color;
}
// 编译成CSS
div {
width: 100px;
color: red;
}
简单计算
$width: 10px;
main {
width: $width / 2;
height: $width * 2;
}
// 编译成CSS
main {
width: 5px;
height: 20px;
}
插值
#{}
插值可以在Sass样式表中的任何地方使用
$name: "box";
.div-#{$name} {
font-size: 12px
}
// 编译成CSS
.div-box {
font-size: 12px
}
嵌套(Nesting)
代码嵌套,用于选择后代。相对于css原生的后代选择器,嵌套样式的代码,会更加直观、简洁。
我们写CSS如果遇到比较复杂的界面,样式比较多也比较复杂,那这种情况我们就会把选择器写的很长,如果样式名也很长的话,那么可以想象一下你的样式文件会是什么样子。Sass
的嵌套就可以解决这个问题。
栗子↓ css 写法
#main .container {
color: white;
}
#main .container .warp {
width: 500px;
}
#main .container .warp .box {
background-color: #333;
}
Sass写法
#main .container {
color: white;
.warp {
width: 500px;
.box {
background-color: #333;
}
}
}
把共同选择器提取了出来,嵌套规则:Sass中允许将一套CSS样式嵌入进另一套CSS样式中内层的样式将外层的选择器作为父选择器。
父选择器 &
CSS写法
.p1 {
color: blue;
}
.p1:hover {
color: yellow;
}
.p2 {
background-color: pink;
}
.p2_item {
font-size: 16px;
}
Sass写法
.p1 {
color: blue;
&:hover {
color: yellow;
}
}
.p2 {
background-color: pink;
&_item {
font-size: 16px;
}
}
混合(Mixin / Include)
作为CSS预处理器中语言中最强大的特性,很多代码都有解决复用的方案,Mixins可以将一部分样式抽出,作为单独定义的模块,被很多选择器重复使用。
混合器使用@mixin
标识符定义。看上去很像其他的CSS @
标识符,比如说@media
或者@font-face
。这个标识符给一大段样式赋予一个名字,然后就可以轻易地通过引用这个名字重用这段样式。
声明的@mixin
通过@include
来调用。
上代码↓
// 先定义一个mixin
@mixin flex-layout {
display: flex;
justify-content: center;
align-items: center;
}
// 引用
.warp {
font-size: 14px;
@include flex-layout;
}
编译后的代码
.warp {
font-size: 14px;
display: flex;
justify-content: center;
align-items: center;
}
传递参数
@mixin
可以传递参数,参数名以$符号开始,也可以给参数设置默认值,如果有多个参数以逗号分开。
@mixin content($color: red,$pd: 20px) {
background-color: $color;
padding: $pd;
text-align: center;
}
.a {
@include content;
}
.b {
@include content($color: blue,$pd: 10px);
}
编译后的代码
.a {
background-color: red;
padding: 20px;
text-align: center;
}
.b {
background-color: blue;
padding: 10px;
text-align: center;
}
导入(Import)
这里解释下Sass导入的优势,CSS执行@import,浏览器会优先执行其他文件,破坏了并行下载样式,Sass会在生成CSS文件时就把相关文件导入进来,打包成一个CSS文件,省略了其他下载请求。
继承(Extend)
提到继承我们就会想到类,当一个元素拥有的类(比如说.a
)表明它属于另一个类(比如说.b
),那如果我们要细化这两个类呢?
给这两个类分别写相同的样式,但是如果有大量的重复怎么办?使用sass
时,我们提倡的就是不要做重复的工作。
可以使用一个选择器组(比如说.a .b
)给这两个选择器写相同的样式。如果.a的所有样式都在同一个地方,这种做法很好,但是如果是分散在样式表的不同地方呢?再这样做就困难多了。
这时@extend
就闪亮登场了。
使用选择器的继承,使用关键词@extend
,后面紧跟需要继承的选择器。
Sass
/* This CSS will print because %message-shared is extended. */
%message-shared {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
// This CSS won't print because %equal-heights is never extended.
%equal-heights {
display: flex;
flex-wrap: wrap;
}
.message {
@extend %message-shared;
}
.success {
@extend %message-shared;
border-color: green;
}
.error {
@extend %message-shared;
border-color: red;
}
.warning {
@extend %message-shared;
border-color: yellow;
}
CSS
/* This CSS will print because %message-shared is extended. */
.message, .success, .error, .warning {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
border-color: green;
}
.error {
border-color: red;
}
.warning {
border-color: yellow;
}
逻辑控制
Sass
中通过@if
、@else
实现条件判断来提供语言的流控制。
SASS
中还实现了一个三目判断,语法为:if($condition, $if_true, $if_false)
。
三个参数分别表示:条件,条件为真的值,条件为假的值。
$type: monster;
h1 {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
循环
Sass支持for循环语句,通过@for
、@each
、@while
来实现循环,配合map
和list
这两种数据类型可以实现多数编程语言提供的功能。
for
for循环语句需要使用@for,并且配合“from”和“through”一起使用,基本语法:
@for $var from <start> through <end> {语句块}
@for $i from 1 through 3 {
.box-#{$i} { width: 2px * $i; }
}
css
.box-1 { width: 2px; }
.box-2 { width: 4px; }
.box-3 { width: 6px; }
each
@each $var in <list>{语句块}
@each $icon in minus, plus, check, close {
.#{$icon}-box {
background-image: url('/images/#{$icon}.png');
}
}
css
.icon-box { background-image: url('/images/minus.png'); }
.icon-box { background-image: url('/images/plus.png'); }
.icon-box { background-image: url('/images/check.png'); }
.icon-box { background-image: url('/images/close.png'); }
while
$i: 6;
@while $i > 0 {
.item-#{$i} { padding: 5px * $i; }
$i: $i - 2;
}
css
.item-6 { padding: 30px; }
.item-4 { padding: 20px; }
.item-2 { padding: 10px; }
颜色函数
lighten($color, 10%); /* 返回的颜色在$color基础上变亮10% */
darken($color, 10%); /* 返回的颜色在$color基础上变暗10% */
saturate($color, 10%); /* 返回的颜色在$color基础上饱和度增加10% */
desaturate($color, 10%); /* 返回的颜色在$color基础上饱和度减少10% */
grayscale($color); /* 返回$color的灰度色*/
complement($color); /* 返回$color的补色 */
invert($color); /* 返回$color的反相色 */
mix($color1, $color2, 50%); /* $color1 和 $color2 的 50% 混合色*/
预处理器的实现原理
- 取到DSL源代码的分析树
- 将含有动态生成相关节点的分析树转换为静态分析树
- 将静态分析树转换为CSS的静态分析树
- 将CSS的静态分析树转换为CSS代码
end 总结
哇,感觉学到了好多,重新对CSS预处理器有了一个新的认识,为兼容各种浏览器而诞生的一种新的样式语言,经过编译最终转化为各个浏览器可识别的css文件。就像jQuery帮助改善网络一样,在CSS方面确实有预处理器。 像Sass这样的语言为CSS规范作者尚未考虑的新思想和方法铺平了道路。
转载自:https://juejin.cn/post/7160620996993482759