前言

今时不同来日,能叫咱们切图仔的只能是咱们本人!

JavasScrip框架满天飞的年代,前端三板斧之一的CSS也前前后后涌出SassLessStylus等多款CSS预处理框架。

明天咱们要讲的就是其中的的老大哥Sass的升级版ScssScss给咱们提供了变量 、循环 、继承 、混入、函数等一系列弱小的性能以不便咱们开发。

以前感觉Scss简略,起初发现,简略是真的简略,我菜也是真的菜

如果文章对你有帮忙的话,记得一键三连哟。有问题和纳闷的话也能够在评论区留言。我会第一工夫回复大家,如果感觉我的文章哪里有知识点谬误的话,也恳请可能告知,把错的货色了解成对的,无论在什么行业,都是致命的。

日常博客记录在语雀,欢送关注 语雀文档。

Scss和Sass

Sass从第三代开始,放弃了缩进式格调,并且齐全向下兼容一般的CSS代码,这一代的Sass也被称为Scss

文档

单文件编译能够在上面的网站进行操作,多文件编译见下下节,中文文档缺失的货色挺多的,有条件的能够翻看英文文档。

  • 中文文档:https://www.sass.hk
  • 英文文档:https://sass-lang.com/documen...
  • CSSScss:https://www.sass.hk/css2sass
  • ScssCSS:https://www.sassmeister.com

Sass版本

Sass有三个版本Dart SasslibsassRuby Sass

  1. Dart Sass,用Dart语言写的sass实现,于2016年11月1日公布alpha版本,版本1.23.0之后齐全反对模块化机制。
  2. libSass也就是俗称的node-sass,用c/c++实现的sass版本,应用十分宽泛。 node-sass是绑定了 libsassnodejs库,能够极快的将.scss 文件编译为.css文件,这个装置过程……,懂的都懂,官网也不举荐再应用了。
  3. Ruby Sass,是最后的Sass实现,然而2019年3月26日被进行了,当前也不会再反对,使用者须要迁徙到别的实现上。

环境配置

中文文档的装置教程是Ruby Sass,集体举荐应用npm装置Dart Sass,这也是官网举荐的形式。

全局装置

npm默认装置的是Dart Sass了。

npm install -g sass

我的项目构造

code    --css        --index.scss    --dist

监听运行

应用命令行操作,监听文件夹下的scss文件并输入为css文件,如果是webpack我的项目,则须要应用sass-loader

sass --style=expanded  -w css:dist --no-source-map

Live Sass Compiler

如果你应用的VSCodeLive Sass Compiler插件,能够参考我的配置,这个插件用的 Sass版本是LibSass3.5.4,对有些指令存在兼容性和不反对的状况。

"liveSassCompile.settings":{        "generateMap":false,        "formats":[            {                "format": "expanded",                "savePath": "~/css/",            }        ]}

输入格局

嘿嘿,上面注释术语都同对立改为小写哈。
scss提供了四种输入格局,在命令行中应用 --style 选项进行设置,在Live Sass Compiler中配置format参数。

注:dart sass只反对expandedcompressed

sass --watch style.scss:style.css --style compressed

:nested

nestedscss默认的输入格局,选择器与属性等独自占用一行,缩进量与 scss文件中统一,每行的缩进量反映了其在嵌套规定内的层数

#main {  color: #fff;  background-color: #000; }  #main p {    width: 10em; }.p {  font-size: 10em;  font-weight: bold;  text-decoration: underline; }

:expanded

expanded输入像是咱们平时手写的款式,选择器、属性等各占用一行,属性依据选择器缩进,而选择器不做任何缩进。

#main {  color: #fff;  background-color: #000;}#main p {  width: 10em;}.p {  font-size: 10em;  font-weight: bold;  text-decoration: underline;}

:compact

compact会将每条 css 规定演绎为一行。嵌套过的选择器在输入时没有空行,不嵌套的选择器会输入空白行作为分隔符。

#main { color: #fff; background-color: #000; }#main p { width: 10em; }.p { font-size: 10em; font-weight: bold; text-decoration: underline; }

:compressed

compressed会删除所有无意义的空格、空白行、以及正文,力求将文件体积压缩到最小,同时也会做出其余调整,比方会主动替换占用空间最小的色彩表达方式。

#main{color:#fff;background-color:#000}#main p{width:10em}.p{font-size:10em;font-weight:bold;text-decoration:underline}

语法嵌套规定

选择器嵌套

css中反复写选择器是十分宜人的。尤其是html构造嵌套十分深的时候,scss的选择器嵌套能够防止反复输出父选择器,能够无效的进步开发效率,缩小款式笼罩可能造成的异样问题。这也是咱们最罕用的性能。很多人用scss就只用了这个性能,而后感觉本人会了。

这个是失常的css构造

.container {    width: 1200px;    margin: 0 auto;}.container .header .img {    width: 100px;    height: 60px;}

编译成scss的样子,子元素向父元素外部嵌套了。

.container {    width: 1200px;    margin: 0 auto;    .header {        .img {            width: 100px;            height: 60px;        }    }}

属性嵌套

有些css属性遵循雷同的命名空间 (雷同的结尾),比方font-familyfont-sizefont-weight都以font作为属性的命名空间。为了便于管理这样的属性,也为了防止反复输出。(这个编辑器提醒有点不太现实……,不是很好用)。

.container {  font: {    family: fantasy;    size: 30em;    weight: bold;  }}

编译成css

.container {  font-family: fantasy;  font-size: 30em;  font-weight: bold;}

命名空间也能够蕴含本人的属性值

.container {  color: red {    adjust: fantasy;  }}

编译成css

.container {  color: red;  color-adjust: fantasy;}

父选择器&

在嵌套 css规定时,有时会须要应用嵌套外层的父选择器,例如,当给某个元素设定 hover 款式时,能够用& 代表嵌套规定外层的父选择器,scss在编译时会把&替换成父选择器名。

案例外面的&示意的就是父级a选择器

.container {    a {        color: #333;        &:hover {             text-decoration: underline;             color: #f00;        }    }}

转化成scss

.container a {    color:#333;}.container a:hover {    text-decoration:underline;    color:#F00;}

换个思路,也能够应用&进行选择器名称拼接。

.main {    color: black;    &-sidebar { border: 1px solid; }}

转化成css

.main {    color: black;}.main-sidebar {    border: 1px solid;}

Scss的两种正文

多行正文/* ... */

多行正文会编译到.css文件中,compressed(压缩)模式下除外, 将 !作为多行正文的第一个字符示意在压缩输入模式下也保留这条正文,通常用于增加版权信息。

/*!* 我是* 多行* 正文*/body { color: black; }

编译成css

/*!* 我是* 多行* 正文 */body{color:#000}

单行正文//

单行正文不会编译到.css文件

// 我是单行正文body { color: black; }

编译成css

body {  color: black;}

变量

应用

原生css中的变量,应用--变量名:变量值定义,var(--变量名)进行应用。

:root {    --color: #F00;}p {    color: var(--color);}

scss中的变量,以美元符号$结尾,赋值办法与 css属性的写法一样。

$color:#F00;p {    color: $color;}

转行成css

p {    color: #F00;}

5条变量规定

下文的mixinfunction命名也遵循1234条规定:

  1. 变量以美元符号$结尾,前面跟变量名;
  2. 变量名是不以数字结尾的可蕴含字母、数字、下划线、横线(连接符);
  3. 通过连接符-与下划线_定义的同名变量为同一变量;
  4. 变量肯定要先定义,后应用;
  5. 写法同css,即变量名和值之间用冒号:分隔;

2种变量作用域

  1. 变量作用域分为全局变量域局部变量域

    • 全局变量:申明在最外层的变量,可在任何中央应用;
    • 局部变量:嵌套规定内定义的变量只能在嵌套规定内应用。
  2. 将局部变量转换为全局变量能够增加!global 申明。
$color: red;.container {    $height: 500px;    $font-size: 16px !global;    font-size: $font-size;    color: $color;    height: $height;}.footer {    /**$font-size应用!global 申明成全局变量了*/    font-size: $font-size;     /**    * Error: Undefined variable.     * $height是.container下的局部变量,无奈在.footer上面编译    */    height:$height;}

编译成css

.container {    font-size: 16px;    color: red;    height: 500px;}.footer {     /**$font-size应用!global 申明成全局变量了*/    font-size: 16px;}

7种次要的数据类型

scss反对7种次要的数据类型:

  1. 数字,1rem、2vh、13、 10px
  2. 字符串,分有引号字符串与无引号字符串,"foo"、 'bar'、baz
  3. 色彩,blue, #04a3f9, rgba(255,0,0,0.5)
  4. 布尔型,truefalse
  5. 空值,null是其类型的惟一值。示意短少值,通常由函数返回以示意短少后果;
  6. 数组 (list),用空格或逗号作分隔符,1.5em 1em 0 2em,Helvetica,Arial,sans-serif
  7. maps, 相当于 JavaScript object(key1: value1, key2: value2)

官网中把Function也当作一种类型,点击原文理解。

$layer-index: 10;$border-width: 3px;$font-weight: bold;$font-base-family: "Open Sans", Helvetica, Sans-Serif;$block-base-padding: 6px 10px 6px 10px;$top-bg-color: rgba(255, 147, 29, 0.6);$blank-mode: true;$var: null;$fonts: (  serif: "Helvetica Neue",  monospace: "Consolas",);.container {  font-family: $font-base-family;  font-size: $font-size;  padding: $block-base-padding;  @if $blank-mode {    background-color: #000;  } @else {    background-color: #fff;  }  content: type-of($var);  content: length($var);  color: $top-bg-color;}// 如果列表中蕴含空值,则生成的CSS中将疏忽该空值。.wrap {  font: 18px $font-weight map-get($fonts, "sans");}

编译成css

.container {  font-family: "Open Sans", Helvetica, Sans-Serif;  font-size: 16px;  padding: 6px 10px 6px 10px;  background-color: #000;  content: null;  content: 1;  color: rgba(255, 147, 29, 0.6);}.wrap {  font: 18px bold; // 如果列表中蕴含空值,则生成的CSS中将疏忽该空值。}

scss属性也反对其余值,比方Unicode字符集,或!important 申明。然而scss 不会非凡看待这些属性值,一律视为无引号字符串。

$color:red;.container {    color:$color !important;}

编译成css

.container {  color: red !important;}

!default

能够在变量的结尾增加!default来给变量设置默认值,有点相似Javascript的逻辑运算符let content=content || "Second content"。留神,变量是 null时将视为未被!default赋值。

$content: "First content";// 如果$content之前没定义就应用如下的默认值$content: "Second content" !default;#main {    content: $content;}

编译成css

#main {  content: "First content";}

圆括号

圆括号()能够用来影响运算的程序,和数学中的成果是统一的。

运算符

相等运算==和不相等运算!=。所有数据类型均反对 ==!=,另外,每种数据类型也有其各自反对的运算形式。

$theme:"blue";.container {    @if $theme=="blue" {        background-color: red;    }    @else {        background-color: blue;    }}.container {    @if $theme !="blue" {        background-color: red;    }    @else {        background-color: blue;    }}

编译为css

.container {  background-color: red;}.container {  background-color: blue;}

关系运算符

四个关系运算符< > >= <=

$theme:3;.container {    @if $theme >= 5 {        background-color: red;    }    @else {        background-color: blue;    }}

编译为css

.container {    background-color: blue;}

布尔运行符

三个布尔运算符and or not

$width: 100;$height: 200;$last: false;div {  @if $width>50 and $height<300 {    font-size: 16px;  } @else {    font-size: 14px;  }  @if not $last {    border-color: red;  } @else {    border-color: blue;  }  @if $width>500 or $height<300{    line-height: 20px;  } @else {    line-height: 50px;  }}

编译为css

div {    font-size: 16px;    border-color: red;    line-height: 20px;}div {    font-size: 16px;    border-color: red;}

数字操作符

+ - * / %

/* 纯数字与百分号或单位运算时会主动转化成相应的百分比与单位值 */.container {    /* ================== + 运算===================== */    width: 50 + 20;    width: 50 + 20%;    width: 50% + 20%;    width: 10pt + 20px;    width: 10pt + 20;    /* ================== - 运算===================== */    height: 50 - 20;    height: 10 - 20%;    height: 50pt - 20px;    /* ================== * 运算===================== */    height: 50 * 30;    height: 10 * 30%;    height: 50 * 2px;    height: 50pt * 4;    /* ==================/ 运算 (除完后最多只能保留一种单位)===================== */    $width: 100px;    width: 10/5;    width: 10px / 5px;    width: 10px / 20;    width: ($width/2); // 应用变量与括号    height: (500px/2); // 应用了括号    /* ==================% 求余运算===================== */    width: 10 % 3;    width: 50px % 7;    width: 50% % 7;}

编译成css

/* 纯数字与百分号或单位运算时会主动转化成相应的百分比与单位值 */.container {    /* ================== + 运算===================== */    width: 70;    width: 70%;    width: 70%;    width: 25pt;    width: 30pt;    /* ================== - 运算===================== */    height: 30;    height: -10%;    height: 35pt;    /* ================== * 运算===================== */    height: 1500;    height: 300%;    height: 100px;    height: 200pt;    /* ==================/ 运算 (除完后最多只能保留一种单位)===================== */    width: 10/5;    width: 10px/5px;    width: 10px/20;    width: 50px;    height: 250px;    /* ==================% 运算===================== */    width: 1;    width: 1px;    width: 1%;}

/css中有分隔数字的用处,在scss中,以下三种状况会进行除法运算:

  1. 如果值或值的一部分,是变量或者函数的返回值;
  2. 如果值被圆括号包裹;
  3. 如果值是算数表达式的一部分。
$width: 1000px;div {    font: 16px/30px Arial, Helvetica, sans-serif; // 不运算    width: ($width/2); // 应用变量与括号    width: (#{$width}/2); // 应用 #{} 插值语句将变量包裹,防止运算。    z-index: round(10)/2; // 应用了函数    height: (500px/2); // 应用了括号    margin-left: 5px + 8px/2px; // 应用了+表达式}

编译成css

div {    font: 16px/30px Arial, Helvetica, sans-serif;    width: 500px;    width: 1000px/2;    z-index: 5;    height: 250px;    margin-left: 9px;}

如果须要应用变量,同时又要确保 / 不做除法运算而是残缺地编译到 css文件中,只须要用 #{} 插值语句将变量包裹。

字符串运算

  1. +可用于连贯字符串;
  2. 如果有引号字符串(位于 + 左侧)连贯无引号字符串,运算后果是有引号的;
  3. 无引号字符串(位于 + 左侧)连贯有引号字符串,运算后果则没有引号。
.container {    content: "Foo " + Bar;    font-family: sans- + "serif";}

编译为css

.container {    content: "Foo Bar";    font-family: sans-serif;}

插值语句

文章下面有讲到插值语句,这里来解释一下。\
通过 #{} 插值语句能够在选择器、属性名、正文中应用变量,应用#{}插值语句将变量包裹起来即可,和js中的模板字符串很像。

$font-size: 12px;$line-height: 30px;$class-name: danger;$attr: color;$author: "福大命大";p {    font: #{$font-size}/#{$line-height} Arial Helvetica, sans-serif;}/* * 这是文件的阐明局部* @author: #{$author}*/a.#{$class-name} {    border-#{$attr}: #f00;}

编译成css

p {    font: 12px/30px Arial Helvetica, sans-serif;}/* * 这是文件的阐明局部* @author: 福大命大*/a.danger {    border-color: #f00;}

流程管制

sass中流程管制蕴含四类,也是咱们在js中常见的@if、@for、@each、@while

@if

@if语法和js相似,根本格局是@if...@else if...@else

应用

$theme:3;.container {    @if $theme >= 5 {        background-color: red;    }    @else {        background-color: blue;    }}

编译为css

.container {    background-color: blue;}

案例

这里已一个利用mixinif封装一个三角形生成,mixin常识前面又讲到。

@mixin triangle($direction:top, $size:30px, $border-color:black) {  width: 0px;  height: 0px;  display: inline-block;  border-width: $size;  border-#{$direction}-width: 0;  @if ($direction==top) {     border-color: transparent transparent $border-color transparent;     border-style: dashed dashed solid dashed;  }  @else if($direction==right) {     border-color: transparent transparent transparent $border-color;     border-style: dashed dashed dashed solid;  }  @else if($direction==bottom) {     border-color: $border-color transparent transparent transparent;     border-style: solid dashed dashed dashed;  }  @else if($direction==left) {     border-color: transparent $border-color transparent transparent;     border-style: dashed solid dashed dashed;  }}.p0 {     @include triangle($size:50px);}.p1 {     @include triangle(right, 50px, red);}.p2 {    @include triangle(bottom, 50px, blue);}.p3 {     @include triangle(left, 50px, green);}

编译为

.p0 {    width: 0px;    height: 0px;    display: inline-block;    border-width: 50px;    border-top-width: 0;    border-color: transparent transparent black transparent;    border-style: dashed dashed solid dashed;}.p1 {    width: 0px;    height: 0px;    display: inline-block;    border-width: 50px;    border-right-width: 0;    border-color: transparent transparent transparent red;    border-style: dashed dashed dashed solid;}.p2 {    width: 0px;    height: 0px;    display: inline-block;    border-width: 50px;    border-bottom-width: 0;    border-color: blue transparent transparent transparent;    border-style: solid dashed dashed dashed;}.p3 {    width: 0px;    height: 0px;    display: inline-block;    border-width: 50px;    border-left-width: 0;    border-color: transparent green transparent transparent;    border-style: dashed solid dashed dashed;}

@for

for在条件范畴内反复操作,这个指令蕴含两种格局:

  1. @for $var from <start> through <end>
  2. @for $var from <start> to <end>

两者区别在于 throughto 的含意:

  1. 应用 through时,条件范畴蕴含 <start><end>的值;
  2. 应用 to时条件范畴只蕴含<start>的值不蕴含<end>的值;
  3. $var 能够是任何变量,比方$i<start><end> 必须是整数值。
@for $i from 1 to 3 {  #loading span:nth-child(#{$i}) {      width: 20 * ($i - 1) + px;  }}

编译为

#loading span:nth-child(1) {    width: 0px;}#loading span:nth-child(2) {    width: 20px;}

如果把to换成through

#loading span:nth-child(1) {    width: 0px;}#loading span:nth-child(2) {    width: 20px;}#loading span:nth-child(3) {    width: 40px;}

@each

@each指令的格局是@each $var in $list , $var能够是任何变量名,比方$length 或者$name,而$list是一连串的值,也就是值列表。

$color-list:red green blue turquoise darkmagenta;@each $color in $color-list {    $index: index($color-list, $color);    .p#{$index - 1} {        background-color: $color;    }}

编译为

.p0 {    background-color: red;}.p1 {    background-color: green;}.p2 {    background-color: blue;}.p3 {    background-color: turquoise;}.p4 {    background-color: darkmagenta;}

@while

@while 指令循环输入直到表达式返回后果为 false。这样能够实现比@for 更简单的循环。

比方,能够借此生成栅格化布局。

$column:12;@while $column>0 {   .col-sm-#{$column} {      width: $column / 12 * 100%;   }    $column:$column - 1;}

编译为

.col-sm-12 {    width: 100%;}.col-sm-11 {    width: 91.6666666667%;}.col-sm-10 {    width: 83.3333333333%;}.col-sm-9 {    width: 75%;}.col-sm-8 {    width: 66.6666666667%;}.col-sm-7 {    width: 58.3333333333%;}.col-sm-6 {    width: 50%;}.col-sm-5 {    width: 41.6666666667%;}.col-sm-4 {    width: 33.3333333333%;}.col-sm-3 {    width: 25%;}.col-sm-2 {    width: 16.6666666667%;}.col-sm-1 {    width: 8.3333333333%;}

@import

@import算是一个比拟繁难的模块零碎。scss拓展了@import 的性能,容许其导入 scsssass文件。被导入的文件将合并编译到同一个 css文件中,被导入的文件中所蕴含的变量或者混合指令 (mixin) 都能够在导入的文件中应用。

应用

common.scss

$color:red;

index.scss

@import "common.scss";.container {    border-color: $color;}

编译成

.container {  border-color: red;}

以下状况下,@import 仅作为一般的css语句,不会导入scss文件:

  1. 文件拓展名是 .css
  2. 文件名以 http:// 结尾;
  3. 文件名是 url()
  4. @import蕴含媒体查问。
@import "common.css";@import url(common);@import "http://xxx.com/xxx";@import 'landscape' screen and (orientation:landscape);

scss容许同时导入多个文件,例如同时导入 rounded-corners text-shadow 两个文件,不必再独自写个import引入。

@import "rounded-corners", "text-shadow";

导入文件也能够应用 #{} 插值语句(上面有讲,这里把它了解成js中模板字符串就行)动静导入,但不是通过变量动静导入 scss文件,只能作用于 cssurl() 导入形式

$family: unquote("Droid+Sans");@import url("http://fonts.googleapis.com/css?family=#{$family}");

编译为

@import url("http://fonts.googleapis.com/css?family=Droid+Sans");

@Partials

如果须要导入 scss或者 sass文件,但又不心愿将其编译为 css,只须要在文件名前增加下划线,这样会通知 scss不要编译这些文件。
留神:

  1. 导入语句中却不须要增加下划线;
  2. 不能够同时存在增加下划线与未增加下划线的同名文件,增加下划线的文件将会被疏忽。

_common.scss

$color:red;

index.scss

@import "common.scss";.container {    border-color: $color;}

编译为

.container {  border-color: red;}

_common.scss文件不会编译成 _common.css 文件。

Partials次要是用来定义公共款式的,专门用于被其余的 scss文件 import进行应用的。

嵌套@import

大多数状况下,个别在文件的最外层(不在嵌套规定内)应用@import,其实,也能够将@import 嵌套进内层选择器或者 @media 中,与平时的用法成果雷同,只是这样导入的款式只能呈现在嵌套的层中,存在作用域。

common.scss

.example {    color: red;}

index.scss

#main {    @import "example";}

被编译成

#main .example {    color: red;}

留神:@import不能嵌套应用在控制指令或混入中(带有@符号的叫指令)。

@media 媒体查问加强

scss中,@media 指令与 css中用法一样,只是减少了一点额定的性能,容许在css规定中嵌套。如果@media 嵌套在 css规定内,编译时,@media 将被编译到文件的最外层,蕴含嵌套的父选择器。这个让 @media 不便不少,不须要反复写选择器,也不会打乱 css的书写流程。

应用

.sidebar {  width: 300px;  @media screen and (orientation: landscape) {    width: 500px;    .item {      height: auto;    }  }}

编译为

.sidebar {    width: 300px;}@media screen and (orientation: landscape) {  .sidebar {    width: 500px;  }  .sidebar .item {    height: auto;  }}

嵌套

@media容许相互嵌套应用,编译时,scss主动增加 and

@media screen {  .sidebar {    @media (orientation: landscape) {      width: 500px;    }  }}

编译为

@media screen and (orientation: landscape) {  .sidebar {    width: 500px;  }}

应用插值

能够应用变量,函数,以及运算符代替条件的名称或者值。

$media: screen;$feature: -webkit-min-device-pixel-ratio;$value: 1.5;@media #{$media} and ($feature: $value) {  .sidebar {    width: 500px;  }}

编译为

@media screen and (-webkit-min-device-pixel-ratio: 1.5) {  .sidebar {    width: 500px;  }}

@mixin

混合指令(Mixin)用于定义可重复使用的款式。混合指令能够蕴含所有的css规定,绝大部分 scss规定,甚至能够通过参数性能引入变量,输入多样化的款式。

留神:函数命名和变量命名规定统一。

应用

@mixin mixin-name() {    /* css 申明 */}// 应用@include mixin-name;

规范模式

// 定义一个区块根本的款式@mixin block {    width: 96%;    margin-left: 2%;    border-radius: 8px;    border: 1px #f6f6f6 solid;}// 应用混入 .container {    .block {        @include block;    }}

编译为

.container .block {    width: 96%;    margin-left: 2%;    border-radius: 8px;    border: 1px #f6f6f6 solid;}

嵌入选择器

@mixin外面再嵌套一层

@mixin warning-text {    font-size: 12px;    .warn-text {        color: rgb(255, 253, 123);        line-height: 180%;    }}.container {       @include warning-text;}

编译为

.container {    font-size: 12px;}.container .warn-text {    color: #fffd7b;    line-height: 180%;}

单参数

// 定义flex布局元素纵轴的排列形式@mixin flex-align($aitem) {    align-items: $aitem;}// 只有一个参数,间接传递参数.container {    @include flex-align(center);}

编译为

.container {    align-items: center;}

多参数

// 定义块元素内边距@mixin block-padding($top, $right, $bottom, $left) {    padding-top: $top;    padding-right: $right;    padding-bottom: $bottom;    padding-left: $left;}// 依照参数程序赋值.container1 {   @include block-padding(10px, 20px, 30px, 40px);}// 可指定参数赋值.container2 {   @include block-padding($left: 20px, $top: 10px, $bottom: 10px, $right: 30px);}// 可指定参数赋值,然而必须指定4个值,不能缺失.container3 {   @include block-padding($left: 10px, $top: 10px, $bottom: 0, $right: 0);}

编译为

.container1 {    padding-top: 10px;    padding-right: 20px;    padding-bottom: 30px;    padding-left: 40px;}.container2 {    padding-top: 10px;    padding-right: 30px;    padding-bottom: 10px;    padding-left: 20px;}.container3 {    padding-top: 10px;    padding-right: 0;    padding-bottom: 0;    padding-left: 10px;}

指定默认值

// 定义块元素内边距,参数指定默认值@mixin block-padding($top:0, $right:0, $bottom:0, $left:0) {    padding-top: $top;    padding-right: $right;    padding-bottom: $bottom;    padding-left: $left;}// 可指定参数赋值.container {    /** 不带参数 */    @include block-padding;    /** 按程序指定参数值 */    @include block-padding(10px,20px);    /** 给指定参数指定值 */    @include block-padding($left: 10px, $top: 20px)}

编译为

.container {    /** 不带参数 */    padding-top: 0;    padding-right: 0;    padding-bottom: 0;    padding-left: 0;    /** 按程序指定参数值 */    padding-top: 10px;    padding-right: 20px;    padding-bottom: 0;    padding-left: 0;    /** 给指定参数指定值 */    padding-top: 20px;    padding-right: 0;    padding-bottom: 0;    padding-left: 10px;}

可变参数

应用...解决参数不固定的状况,相似于js中的函数的残余参数

@mixin linear-gradient($direction, $gradients...) {    background-color: nth($gradients, 1);    background-image: linear-gradient($direction, $gradients);}.table-data {    @include linear-gradient(to right, #F00, orange, yellow);}

编译为

.table-data {    background-color: #F00;    background-image: linear-gradient(to right, #F00, orange, yellow);}

总结

  1. mixin是能够重复使用的一组css申明,有助于缩小反复代码,只需申明一次,就可在文件中援用;
  2. 混合指令能够蕴含所有的 css规定,绝大部分scss规定,能够传递参数,输入多样化的款式;
  3. 应用参数时倡议加上默认值;
  4. @import导入部分模块化款式(相似性能、同一组件);
  5. @minix定义的是可重复使用的款式

@function

@function用于封装简单的操作,能够很容易地以一种可读的形式形象出通用公式和行为,函数提供返回值,罕用来做计算方面的工作。

应用

留神:函数命名和变量命名规定统一。

@function square($base) {    @return $base * $base * 1px;}.sidebar {    float: left;    margin-left: square(4);}

编译为

.sidebar {    float: left;    margin-left: 16px;}

可选参数

默认值能够是任何表达式,它们甚至能够援用后面的参数!

//change-color和hue是内置办法//hue 返回$color的色彩为0到360度之间的一个数字。//change-color 用于设置色彩的属性@function invert($color, $amount: 100%) {    //@error hue($color); 调试 210deg    $inverse: change-color($color, $hue: hue($color) + 180);    @return mix($inverse, $color, $amount);}$primary-color: #036;.header {    background-color: invert($primary-color, 80%);}

编译为

.header {    background-color: #523314;}

指定参数

$primary-color: #036;.banner {    //scale-color Fluidly scales one or more properties of .$color    background-color: $primary-color;    color: scale-color($primary-color, $lightness: +40%);}

编译为

.banner {    background-color: #036;    color: #0a85ff;}

可变参数

参数列表还可用于采纳任意关键字参数,meta.keywords()函数采纳参数列表

@function sum($numbers...) {    $sum: 0;    @each $number in $numbers {        $sum: $sum + $number;    }    @return $sum;}$widths: 50px, 30px, 100px;.micro {    width: sum($widths...);}

编译为

.micro {    width: 180px;}

@return

@return只容许在@function内应用,和js一样,遇到return就会返回。

@function red() {    $is: true;    @if $is {        @return 'is';    }    @return red;}.con{    color: red();}

编译为

.con {    color: "is";}

总结:
@function@mixin参数的应用形式没啥区别;
@function用来计算,@mixin用来封装款式,@import用来抽离他们为一个模块。

@extend继承

应用

咱们以elementUIel-button组件为例,能够应用@extend继承曾经存在的款式,原理是应用逗号选择器。

// # id选择器一样的.button {    display: inline-block;    margin-bottom: 0;    font-weight: normal;    text-align: center;    white-space: nowrap;    vertical-align: middle;    cursor: pointer;    background-image: none;    border: 1px solid transparent;    padding: 6px 12px;    font-size: 14px;    line-height: 1.42857143;    border-radius: 4px;    user-select: none;}.btn-default {    @extend .button;    color: #333;    background-color: #fff;    border-color: #ccc;}.btn-danger {    @extend .button;    color: #fff;    background-color: #d9534f;    border-color: #d43f3a;}

编译成

.button, .btn-danger, .btn-default {    display: inline-block;    margin-bottom: 0;    font-weight: normal;    text-align: center;    white-space: nowrap;    vertical-align: middle;    cursor: pointer;    background-image: none;    border: 1px solid transparent;    padding: 6px 12px;    font-size: 14px;    line-height: 1.42857143;    border-radius: 4px;    user-select: none;}.btn-default {    color: #333;    background-color: #fff;    border-color: #ccc;}.btn-danger {    color: #fff;    background-color: #d9534f;    border-color: #d43f3a;}

能够应用多个@extend

.alert {    padding: 15px;    margin-bottom: 20px;    border: 1px solid transparent;    border-radius: 4px;    font-size: 12px;}.important {    font-weight: bold;    font-size: 14px;}.alert-danger {    @extend .alert;    @extend .important;    color: #a94442;    background-color: #f2dede;    border-color: #ebccd1;}

编译为

.alert, .alert-danger {    padding: 15px;    margin-bottom: 20px;    border: 1px solid transparent;    border-radius: 4px;    font-size: 12px;}.important, .alert-danger {    font-weight: bold;    font-size: 14px;}.alert-danger {    color: #a94442;    background-color: #f2dede;    border-color: #ebccd1;}

多层继承

@extend能够多层继承,列如:.alert-danger继承自.important.important又继承自.alert

.alert {    padding: 15px;    margin-bottom: 20px;    border: 1px solid transparent;    border-radius: 4px;    font-size: 12px;}.important {    @extend .alert;    font-weight: bold;    font-size: 14px;}.alert-danger {    @extend .important;    color: #a94442;    background-color: #f2dede;    border-color: #ebccd1;}

编译为

.alert, .important, .alert-danger {    padding: 15px;    margin-bottom: 20px;    border: 1px solid transparent;    border-radius: 4px;    font-size: 12px;}.important, .alert-danger {    font-weight: bold;    font-size: 14px;}.alert-danger {    color: #a94442;    background-color: #f2dede;    border-color: #ebccd1;}

占位符选择器

占位符选择器%,与罕用的idclass选择器写法类似,只是 #. 替换成了%,占位符选择器必须通过 @extend 指令调用。\
还是下面的例子,这里应用占位符选择器操作

.button %base {    display: inline-block;    margin-bottom: 0;    font-weight: normal;    text-align: center;    white-space: nowrap;    vertical-align: middle;    cursor: pointer;    background-image: none;    border: 1px solid transparent;    padding: 6px 12px;    font-size: 14px;    line-height: 1.42857143;    border-radius: 4px;    user-select: none;}        .btn-default {    @extend %base;    color: #333;    background-color: #fff;    border-color: #ccc;}.btn-danger {    @extend %base;    color: #fff;    background-color: #d9534f;    border-color: #d43f3a;}

成果和下面的类选择器一样,然而,他有个有长处,占位符选择器%所属的款式未应用时,不会被编译到css文件中,算是一个小优化吧。

.button .btn-danger, .button .btn-default {    display: inline-block;    margin-bottom: 0;    font-weight: normal;    text-align: center;    white-space: nowrap;    vertical-align: middle;    cursor: pointer;    background-image: none;    border: 1px solid transparent;    padding: 6px 12px;    font-size: 14px;    line-height: 1.42857143;    border-radius: 4px;    user-select: none;}.btn-default {    color: #333;    background-color: #fff;    border-color: #ccc;}.btn-danger {    color: #fff;    background-color: #d9534f;    border-color: #d43f3a;}

@use

存在兼容性问题,仅在Dart Sass 1.23.0以上无效,官网文档有兼容性介绍。

scss真正意义上的模块化,能够从其它 scss样式表中加载mixinfunction变量,并将来自多个样式表的 css组合在一起。scss还提供了很多内置模块,咱们能够通过@use应用。

@import毛病

  1. 多处导入,存在款式反复加载。
  2. 因为没有命名空间,为了防止撞名,不敢应用简写的 classname,因而起名总是须要留神。
  3. 没有公有函数的概念,款式齐全裸露在应用import的中央,这对ui库不够敌对。

应用

src/_corners.scss

$radius: 3px;@mixin rounded {    border-radius: $radius;}

index.scss

@use "src/corners";.button {    @include corners.rounded;    padding: 5px + corners.$radius;}

命名空间

src/_corners.scss

$radius: 3px;@mixin rounded {    border-radius: $radius;}

index.scss

@use "src/corners" as c;.button {    @include c.rounded;    padding: 5px + c.$radius;}

编译为

.button {    border-radius: 3px;    padding: 8px;}

as*

应用as*,那么这一模块就处于全局命名空间。

src/_corners.scss

$radius: 3px;@mixin rounded {    border-radius: $radius;}

index.scss

@use "src/corners" as *;.button {    @include rounded;    padding: 5px + $radius;}

编译为

.button {    border-radius: 3px;    padding: 8px;}

公有模块

应用scss能够轻松地定义公有成员,公有成员命名以-或结尾。

src/_corners.scss

$-radius: 3px;@mixin rounded {    border-radius: $-radius;}

index.scss

@use "src/corners";.button {    @include corners.rounded;    // Error: Private members can't be accessed from outside their modules    padding: 5px + corners.$-radius;}

@forward

@forward语句能够引入另一个模块的所有变量、mixins和函数,将它们间接作为以后模块的API裸露进来,不会真的在以后模块减少代码。不同于 @use@forward不能给变量增加命名空间。

用法

留神,此时生成的bootstrap.css文件中,是不蕴含functionsvariablesmixins代码的,也不能间接在bootstrap.scss文件中应用这些模块。而是须要在另一个文件中 @import 'bootstrap'或者 @use bootstrap模块,再去应用这些办法。bootstrap.scss文件相似于一个传输中转站,把上下游的成员变量无缝连接起来。

/* bootstrap.scss */@forward"functions";@forward"variables";@forward"mixins";

留神,间接写在上游模块的失常的款式依然会被 @forward 进来。见下例:

a.scss

@mixin rounded {    border-radius: 100px;}footer {    height: 1px;}

b.scss

$radius: 3px;

c.scss

@forward "a";@forward "b";

index.scss

@import "c.scss";.button {    @include rounded;    padding: $radius;}

编译为

footer {    height: 1px;}.button {    border-radius: 100px;    padding: 3px;}

show/ hide

通过管制 showhide,能够决定模块中的哪些成员对引入后的模板可见。对暗藏的变量,在上游文件中不能够应用,相当于模块公有成员。

c.scss

@forward "a" show rounded;@forward "b" hide $radius;

index.css

@import "c.scss";.button {    @include rounded;    padding: $radius;}// Error: Undefined variable. padding: $radius;

应用as *号为子模块增加前缀

大多数状况下,一个款式库会存在一个入口文件index.scss,而后在index.scss中引入其余的子文件。这种构造相似于一个多合一模块。那么,如果要在某一文件中 @forward多个子模块,就能够应用as <prefix>-*语句,为子模块下的成员主动带上前缀以辨别。

c.scss

@forward "a" as mixin-*;@forward "b" as var-*;

index.css

@import "c.scss";.button {    @include mixin-rounded;    padding: $var-radius;}

很多内置的办法就是这样应用的,嘿嘿!

@at-root

@at-root用来跳出嵌套,在多级嵌套时比拟罕用,蕴含withoutwith

用法

//没有跳出.parent-1 {    color:#f00;    .child {        width:100px;    }}//单个选择器跳出.parent-2 {    color:#f00;    @at-root .child {        width:200px;    }}//多个选择器跳出.parent-3 {    background:#f00;    @at-root {        .child1 {            width:300px;        }        .child2 {            width:400px;        }    }}

编译为

.parent-1 {    color: #f00;}.parent-1 .child {    width: 100px;}.parent-2 {    color: #f00;}.child {    width: 200px;}.parent-3 {    background: #f00;}.child1 {    width: 300px;}.child2 {    width: 400px;}

@without和with

默认@at-root只会跳出选择器嵌套,而不能跳出@media@support,如果要跳出这两种,则需应用@at-root (without: media)@at-root (without: support)@at-root的关键词有四个:

  1. all 示意所有;
  2. rule 示意惯例css选择器;
  3. media 示意media
  4. support示意support@support次要是用于检测浏览器是否反对css的某个属性)。

咱们默认的@at-root@at-root (without:rule)

/*跳出父级元素嵌套*/@media print {    .parent1{        color:#f00;        @at-root .child1 {            width:200px;        }    }}/*跳出media嵌套,父级无效*/@media print {    .parent2{        color:#f00;        @at-root (without: media) {            .child2 {                width:200px;            }        }    }}/*跳出media和父级*/@media print {    .parent3{        color:#f00;        @at-root (without: all) {            .child3 {                width:200px;            }        }    }}

编译成

/*跳出父级元素嵌套*/@media print {    .parent1 {        color: #f00;    }    .child1 {        width: 200px;    }}/*跳出media嵌套,父级无效*/@media print {    .parent2 {        color: #f00;    }}.parent2 .child2 {    width: 200px;}/*跳出media和父级*/@media print {    .parent3 {        color: #f00;    }}.child3 {    width: 200px;}

@at-root与 & 配合应用

.child{    @at-root .parent &{        color:#f00;    }}

编译成

.parent .child {    color: #f00;}

利用于@keyframe

.demo {    animation: motion 3s infinite;    @at-root {        @keyframes motion {        }    }}

编译成

.demo {    animation: motion 3s infinite;}@keyframes motion {}

Scss内置扩大

scss内置扩大分为color list map math meta selector string等,扩大也就是scss内置的一些function,每个模块下内容比拟多,这里用一些罕用的进行举例。

内置函数能够应用@use模块化引入,也能够间接应用他提供的全局函数名调用,以下两种形式是一样的。

@use 'sass:list';p {    color: nth($list: red blue green, $n: 2); // blue    color: list.nth($list: red blue green, $n: 2); // blue}

color

scss蕴含很多操作色彩的函数。例如lighten()darken()可用于调亮或调暗色彩,opacify()使色彩透明度缩小,transparent()使色彩透明度减少,mix()用来混合两种色彩。

.p1 {    // 让色彩变亮    color:scale-color(#5c7a29, $lightness: +30%);}.p2 {    // 让色彩变暗    color:scale-color(#5c7a29, $lightness: -15%);}.p3 {    // 升高色彩透明度    color:scale-color(#5c7a29, $alpha: -40%);}

编译为

.p1 {    color: #95c249;}.p2 {    color: #4e6823;}.p3 {    color: rgba(92, 122, 41, 0.6);}

String

scss有许多解决字符串的函数,比方向字符串增加引号的quote()、获取字符串长度的string-length()和将内容插入字符串给定地位的string-insert()

p {    &:after {        content: quote(这是外面的内容);    }    background-color: unquote($string: "#F00");    z-index:str-length("scss学习");}

编译为

p {    background-color: #F00;    z-index: 6;}p:after {    content: "这是外面的内容";}

Math

数值函数解决数值计算,例如:percentage()将无单元的数值转换为百分比,round()将数字四舍五入为最靠近的整数,min()max()获取几个数字中的最小值或最大值,random()返回一个随机数。

p {    z-index: abs(-15); // 15    z-index: ceil(5.8); //6    z-index: max(5, 1, 6, 8, 3); //8    opacity: random(); // 随机 0-1}

编译为

p {    z-index: 15;    z-index: 6;    z-index: max(5, 1, 6, 8, 3);    opacity: 0.8636254167;}

List

List函数操作Listlength()返回列表长度,nth()返回列表中的特定项,join()将两个列表连贯在一起,append()在列表开端增加一个值。

p {    z-index: length(12px); //1    z-index: length(12px 5px 8px); //3    z-index: index(a b c d, c); //3    padding: append(10px 20px, 30px); // 10px 20px 30px    color: nth($list: red blue green, $n: 2); // blue}

编译为

p {    z-index: 1;    z-index: 3;    z-index: 3;    padding: 10px 20px 30px;    color: blue;}

Map

Map函数操作Mapmap-get()依据键值获取map中的对应值,map-merge()来将两个map合并成一个新的mapmap-values()映射中的所有值。

$font-sizes: ("small": 12px, "normal": 18px, "large": 24px);$padding:(top:10px, right:20px, bottom:10px, left:30px);p {    font-size: map-get($font-sizes, "normal"); //18px    @if map-has-key($padding, "right") {        padding-right: map-get($padding, "right");    }    &:after {        content: map-keys($font-sizes) + " "+ map-values($padding) + "";    }}

编译为

p {    font-size: 18px;    padding-right: 20px;}p:after {    content: '"small", "normal", "large" 10px, 20px, 10px, 30px';}

selector

选择符相干函数可对抉择css进行一些相应的操作,例如:selector-append()能够把一个选择符附加到另一个选择符,selector-unify()将两组选择器合成一个复合选择器。

@use 'sass:selector';@debug selector.is-superselector("a", "a"); // true// 能够间接应用@forward下的前缀@debug selector-append("a", ".disabled"); // a.disabled@debug selector-extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled.header {    content: selector-append(".a", ".b", ".c") + '';    content: selector-unify("a", ".disabled") + '';}

编译为

.header {    content: ".a.b.c";    content: "a.disabled";}

meta

meta提供一个mixin和一些原子级别的function,比方应用meta.calc-args获取办法的参数,meta.calc-name获取办法名。

meta.load-css

meta.load-css($url,$with:())mixin能够把$urlcss款式全副蕴含进来。留神,$url引入的函数,变量和mixinmeta.load-css()后的scss中并不能用,它只会返回编译后的css代码。它的第二个参数能够批改应用了!default的变量。

src/corners

$border-contrast: false !default;code {    background-color: #6b717f;    color: #d2e1dd;    @if $border-contrast {        border-color: #dadbdf;    }}

index.scss

@use "sass:meta";body.dark {    @include meta.load-css("src/corners", $with: ("border-contrast": true));}

编译为

body.dark code {    background-color: #6b717f;    color: #d2e1dd;    border-color: #dadbdf;}

function

@use "sass:meta";@debug meta.calc-args(calc(100px + 10%)); // unquote("100px + 10%")@debug meta.calc-args(clamp(50px, var(--width), 1000px)); // 50px, unquote("var(--width)"), 1000px@debug meta.calc-name(calc(100px + 10%)); // "calc"@debug meta.calc-name(clamp(50px, var(--width), 1000px)); // "clamp"

调试相干

@debug

@debug打印表达式的值,不便调试。

$font-sizes: 10px + 20px;    $style: (        color: #bdc3c7    );.container {    @debug $style;    @debug $font-sizes;}

@error

@error显示致命谬误

$colors: (    blue: #c0392b,    black: #2980b9);@function style-variation($style) {    @error "Invalid color: '#{$style}'.";    @if map-has-key($colors, $style) {        @return map-get($colors, $style);    }}.container {    color: style-variation(white);}

@warn

@warn显示警告性倡议,会显示堆栈信息。

$colors: (    blue: #c0392b,    black: #2980b9  );@function style-variation($style) {    @warn "Invalid color: '#{$style}'.";    @if map-has-key($colors, $style) {        @return map-get($colors, $style);    }}.container {    color: style-variation(white);}

自检函数

自检相干函数,属于内置扩大meta下的办法,feature-exists()查看以后scss版本是否存在某个个性,variable-exists()查看以后作用域中是否存在某个变量,mixin-exists()查看某个mixin是否存在。自检函数通常用在代码的调试上,返回的是个布尔值。

$color:#F00;@mixin padding($left:0, $top:0, $right:0, $bottom:0) {    padding: $top $right $bottom $left;}.container {    @if variable-exists(color) {        color: $color;    }    @else {        content: "$color不存在";    }    @if mixin-exists(padding) {        @include padding($left: 10px, $right: 10px);    }}

编译为

.container {    color: #F00;    padding: 0 10px 0 10px;}

结语

看了这么久了,辛苦了,不过我也写了很久啦,大佬无妨点个赞再走吧。
也能够看看我的其余文章,嘿嘿嘿

2022年除夕,我终于搞懂了原型和原型
13道隐式类型转换面试题,让你一次爽到底
⌈2022⌋ JavaScript超具体循环总结
云闪付小程序前端不齐全踩坑指北
巧用Node.js process暗藏我的项目重要参数