Sass是世界上最成熟,稳定,功能最强大的专业级 CSS扩展语言
介绍
随着 CSS
越来越大,越来越复杂并且难以维护。Sass使您可以使用 CSS中尚不存在的功能,例如 变量,嵌套,混合,继承和其他 使CSS编写变得有趣的好东西
虽然 scss
有着诸多好处,但是 scss
使用与 常见的 css
书写方式还是有许多差异,功能丰富的同时,也带来了 API
的丰富,也增大了前端工程师的心智负担
今天就用 前端最熟悉的 js 来带领大家走进 sass,窥探 SassScript
的世界
安装
全局安装 sass
npm i sass -g
创建 scss 文件
在这里我使用 npm init -y
创建一个空白的项目, 创建 index.scss
文件
目录结构如下:
输出 css
在终端中输入如下命令:
sass --watch index.scss output.css
scss 会监听 index.scss 文件的变化,只要有变化, 就被编译后输出到 output.css 文件
❤️ 变量($)
在 js 中 使用变量,应该是 学习 js 的第一课,可见变量 的重要性, scss 中的变量同样也很重要
在 js 中这样使用变量
let x = 10;
x ++
在 index.scss文件中添加如下代码,并保存
$width: 5em;
#main {
width: $width;
}
可以看到 output.css
文件中被编译后的代码
#main {
width: 5em;
}
可以看到,在 js
中使用变量,使用关键词let / const /var
定义
在 scss
中使用变量,使用$
+string
的形式
❤️ 继承
继承是 js
的核心之一,js 中 使用 原型链就大大简化了代码
var x = 10;
console.log(x.toFixed(2))
x 只是一个原始值,怎么能使用 toFixed
方法呢,秘密就是 原型链
在 scss 中也有这么好用的功能
嵌套继承
#main {
&:hover{
background: #000;
}
&.side {
width: 20px;
}
.son{
width: 30px;
}
}
保存 并查看 output.css
/* output.css */
#main:hover {
background: #000;
}
#main.side {
width: 20px;
}
#main .son {
width: 30px;
}
可以明显的看到,&
符号指向了当前的父选择器,son
是 main
的后代选择器,side
是 main
的并列选择器
混入继承
在 vue2 中可以使用 mixin 混入重复的变量或者方法,在其他页面可以直接使用混入的变量/方法,可以简化操作,方便统一管理
在 sass 中也有类似的混入
使用@mixin
定义混入指令,使用@include
引用变量,在一些重复的定义的 css 片段里,使用 混入是一个不错的选择
定义混合指令
@mixin large-text {
font-size: 30px;
color: #ff0000;
}
使用混入指令
.page {
@include large-text;
padding: 4px;
margin-top: 10px;
}
最后的输出结果
/* output.css */
.page {
font-size: 30px;
color: #ff0000;
padding: 4px;
margin-top: 10px;
}
如果只是这么简单的引用混入的话了,那你也太小看 sass 的混入了,他可以传参,来达到自定义的效果
还记得刚刚说的变量吗? mixin 传入变量直接使用,类似于函数的形参,include 就是函数的调用
先看js 中函数中的用法
// 一对一传递
function a(x,y){
x,y
}
// 解构
function b({x,y}){
x,y
}
// 默认值 + 解构
function c({x,y}={x:1,y:2}){
x,y
}x,y
}
再来对照 sass 中的混入
一对一传入
@mixin large-text($color) {
font-size: 30px;
color: $color;
}
.page {
/* 传入变量 blue */
@include large-text(blue);
padding: 4px;
margin-top: 10px;
}
保存并查看 output.css
/* output.css */
.page {
font-size: 30px;
/* 颜色 变为 blue */
color: blue;
padding: 4px;
margin-top: 10px;
}
默认参数
@mixin flex($col:column,$justify:center,$items:center){
display: flex;
flex-direction: $col;
justify-content: $justify;
align-items: $items;
}
.page {
@include flex(row)
}
输出
.page {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
默认+解构传入( 关键词参数 )
@mixin flex($col:column,$justify:center,$items:center){
display: flex;
flex-direction: $col;
justify-content: $justify;
align-items: $items;
}
.page {
@include flex($items:sapce-between)
}
.page {
display: flex;
flex-direction: column;
justify-content: center;
align-items: sapce-between;
}
使用 关键词 参数 简化了传入操作 ❤
解构传入(剩余参数)
@mixin colors($text, $background, $border) {
color: $text;
background-color: $background;
border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
@include colors($values...);
}
编译为
.primary {
color: #ff0000;
background-color: #00ff00;
border-color: #0000ff;
}
这种多参数混入非常的常见,特别是在有比较强关联的样式的时候
是不是已经对 sass 的功能表示震惊呢!别急后面还有很多有用的 api
🚀循环
老规矩,先看 js 中有哪些常用的循环方法, for
用来循环一个长度,for of
用来循环数组
for(let i =0;i<10;i++){
i // 0 - 10
}
let arr = [1,2,3];
for (const v of arr) {
v // 1,2,3
}
let arr2 = [[1,2,3],[2,3,4]];
for (const [a,b,c] of arr2) {
console.log(a,b,c) // 1,2,3 // 4,5,6
}
sass 中的循环和 js 中的循环有异曲同工的用处,甚至比 js 更方便
#{ } 插值语句
通过#{}
插值语句可以在选择器或属性名中使用变量:
$name: foo;
$attr: border;
p.#{$name} {
#{$attr}-color: blue;
}
// 编译为
p.foo {
border-color: blue;
}
for
@for $i from 1 through 3 {
.item-#{$i} {
width: 2em * $i;
}
}
输出结果
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}
🎈 each
@each
指令的格式是 $var in <list>
,
$var
可以是任何变量名,比如 $length
或者 $name
,而 <list>
是一连串的值,也就是值列表。
@each
将变量 $var
作用于值列表中的每一个项目,然后输出结果,例如
- 这个循环可以看作是
[red,yellow]
的简化版
@each $color in red, yellow {
.#{$color} {
color:$color
}
}
解析为
.red {
color: red;
}
.yellow {
color: yellow;
}
- 循环加解构
可以看作是[ [black, default], [blue, pointer] ]
的简化版
@each $color, $cursor in (black, default), (blue, pointer) {
.#{$color}-icon {
border: 2px solid $color;
cursor: $cursor;
}
}
.black-icon {
border: 2px solid black;
cursor: default;
}
.blue-icon {
border: 2px solid blue;
cursor: pointer;
}
- 循环 maps,形如这种
(k:v)
称为 maps 结构
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
#{$header} {
font-size: $size;
}
}
输出结果
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
while
$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;
}
while 使用的比较少,我反正是没用过
🤖 自定义函数
和 js
中的函数是一样的,使用 @function 关键字定义
,使用``
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
#sidebar { width: grid-width(5); }
/* 关键词参数*/
#sidebar { width: grid-width($n: 5); }
输出结果
#sidebar {
width: 240px;
}
判断
js 中的 if 判断是这样的
let x = 1
if(x == 1){
}else if(x == 2){
}else {
}
sass中也可以使用 if 来进行判断
p {
@if 1 + 1 == 2 { border: 1px solid; }
@if 5 < 3 { border: 2px dotted; }
@if null { border: 3px double; }
}
输出css
p {
border: 1px solid;
}
如果配合上函数的话,就能组合出很多强大的功能( 没有括号包裹 )
@function color($mode){
@if $mode == light {
@return white
}
@else if $mode==dark {
@return black
}
@else {
@return green
}
}
p{
color:color(light)
}
p {
color: white;
}
数学计算(加减乘除)
/
在 CSS 中通常起到分隔数字的用途,SassScript 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了 /
除法运算的功能。也就是说,如果 /
在 SassScript 中把两个数字分隔,编译后的 CSS 文件中也是同样的作用。
以下三种情况 /
将被视为除法运算符号:
- 如果值,或值的一部分,是变量或者函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
p {
font: 10px/8px; // Plain CSS, no division
$width: 1000px;
width: $width/2; // Uses a variable, does division
width: round(1.5)/2; // Uses a function, does division
height: (500px/2); // Uses parentheses, does division
margin-left: 5px + 8px/2px; // Uses +, does division
}
编译为
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
可以看出 font
没有解析,因为 font: 10px/8px
是 css 的原生属性,代表的是 font-size / line-height
如果需要使用变量,同时又要确保 /
不做除法运算而是完整地编译到 CSS 文件中,只需要用 #{}
插值语句将变量包裹。
p {
$font-size: 12px;
$line-height: 30px;
font: #{$font-size}/#{$line-height};
}
编译为
p {
font: 12px/30px;
}
总结
scss 可以高效的书写 css 代码,它拥有了 js 的部分功能, 使用 变量,使用mixin,使用 函数 可以把重复的 样式抽离,大大增强了 css 的模块化的能力,前端工程师 应该 掌握一门 css 预处理语言
上文中的 scss
都是常用的写法,下一期出一期 scss
高阶用法