写点什么

Vue 进阶(幺柒捌):延伸阅读 Sass、Scss、Less 与 Stylus 编程特性

  • 2021 年 11 月 14 日
  • 本文字数:8914 字

    阅读完需:约 29 分钟

Vue进阶(幺柒捌):延伸阅读Sass、Scss、Less与Stylus编程特性

一、混合(Mixins)

MixinsCSS预处理器语言中最强大的特性,简单点来说,Mixins可以将一部分样式抽出,作为单独定义的模块,被很多选择器重复使用。平时你在写样式时肯定有碰到过,某段CSS样式经常要用到多个元素中,这样你就需要重复的写多次。在CSS预处理器语言中,你可以为这些公用的CSS样式定义一个Mixin,然后在你CSS需要使用这些样式的地方直接调用你定义好的Mixin。这是一个非常有用的特性,Mixins被当作一个公认的选择器,还可以在Mixins中定义变量或者默认参数

1.1 Sass 混合

Sass样式中声明Mixins时需要使用“@mixin”,后面为Mixins的名,也可以定义参数,同时可以给这个参数设置一个默认值,但参数名是使用“$”符号开始,而且和参数值之间需要使用冒号(:)分开。


在选择器调用定义好的Mixins需要使用“@include”,其后为你要调用的Mixins名。不过在Sass中还支持老的调用方法,就是使用加号“+”调用Mixins,在“+”后跟Mixins名。


举个简单的例子,比如说在你的Sass样式中定义了一个名叫“error”的Mixin,这个“error”设置了一个参数“$borderWidth”,在无特别定义外,这个参数的默认值设置为“2px”:


/*声明一个Mixin叫作“error”*/@mixin error($borderWidth:2px){  border:$borderWidth solid #f00;  color: #f00;}/*调用error Mixins*/.generic-error {  @include error();/*直接调用error mixins*/}.login-error {  @include error(5px);/*调用error mixins,并将参数$borderWidth的值重定义为5px*/}  
复制代码

1.2 LESS 混合

LESS中,混合是指将定义好的“ClassA”中引入另一个已经定义的“Class”,就像在当前的“Class”中增加一个属性一样。


不过LESS样式中声明MixinsSass声明方法不一样,更像CSS定义样式,在LESS中,可以将Mixins看成是一个类选择器,当然Mixins也可以设置参数,并给参数设置默认值。不过设置参数的变量名是使用“@”开头,同样参数和默认参数值之间需要使用冒号(:)分隔开。


正如Sass混合示例,同样在LESS样式中定义一个名叫“error”的Mixin,这个“error”设置了一个参数“@borderWidth”,在无特别定义外,这个参数的默认值是“2px”:


/*声明一个Mixin叫作“error”*/.error(@borderWidth:2px){  border:@borderWidth solid #f00;  color: #f00;}/*调用error Mixins*/.generic-error {  .error();/*直接调用error mixins*/}.login-error {  .error(5px);/*调用error mixins,并将参数@borderWidth的值重定义为5px*/}  
复制代码

1.3 Stylus 混合

Stylus中的混合和前两款CSS预处理器语言的混合略有不同,可以不使用任何符号,就是直接声明Mixins名,然后在定义参数和默认值之间用等号(=)来连接。


/*声明一个Mixin叫作“error”*/error(borderWidth=2px){  border:borderWidth solid #f00;  color: #f00;}/*调用error Mixins*/.generic-error {  error();/*直接调用error mixins*/}.login-error {  error(5px);/*调用error mixins,并将参数$borderWidth的值重定义为5px*/}  
复制代码


三个示例都将会转译成相同的CSS代码:


.generic-error {  border: 2px solid #f00;  color:#f00;}.login-error {  border:5px solid #f00;  color: #f00;}  
复制代码

二、嵌套(Nesting)

CSS预处理器语言中的嵌套指的是:在一个选择器中嵌套另一个选择器来实现继承,从而减少代码量,并且增加了代码的可读性。比如说,我们在CSS中多个元素有一个相同的父元素,我们需要一遍一遍的在每个元素前写这个父元素,那么写样式会变得很乏味,除非给特定的元素添加类名“class”或者ID


section {  margin:10px;}section nav {  height:25px;}section nav a {  color: #0982c1;}section nav a:hover {  text-decoration: underline;}  
复制代码


相反,使用CSS预处理器语言的嵌套特性,我们可以在父元素的大括号({})里写这些元素。同时可以使用“&”符号来引用父选择器。对于SassLESSStylus这三款CSS预处理器语言的嵌套选择器来说,他们都具有相同的语法:


section {  margin:10px;  nav {    height:25px;    a {      color:#0982c1;      &:hover {        text-decoration:underline;      }    }  }}  
复制代码


上面的预处理器转译出来的CSS代码和我们之前开始展示的CSS代码是相同的,非常的方便吧!

三、继承(Inheritance)

对于熟悉CSS的同学来说,对于属性的继承并不陌生。平时在写CSS样式常碰到多个元素应用相同的样式时,我们在 CSS 中通常都是这样写:


p,ul,ol{/*样式写在这里*/}  
复制代码


这样做非常好,但往往我们需要给单独元素添加另外的样式,这个时候我们就需要把其中选择器单独出来写样式,如此一来我们维护样式就相当的麻烦。为了应对这个问题,CSS预处理器语言可以从一个选择继承另一个选择器下的所有样式。

3.1 Sass 和 Stylus 的继承

SassStylus的继承是把一个选择器的所有样式继承到另一个选择器上。在继承另一个选择器的样式时需要使用“@extend”开始,后面紧跟被继承的选择器:


.block {  margin: 10px 5px;  padding: 2px;}p {  @extend .block;/*继承.block选择器下所有样式*/  border: 1px solid #eee;}ul,ol {  @extend .block; /*继承.block选择器下所有样式*/  color: #333;  text-transform: uppercase;}  
复制代码


上面的代码转译成 CSS:


.block,p,ul,ol {  margin: 10px 5px;  padding:2px;}p {  border: 1px solid #eee}ul,ol {  color:#333;  text-transform:uppercase;}  
复制代码

3.2 LESS 继承

LESS支持的继承和SassStylus不一样,他不是在选择器上继承,而是将Mixins中的样式嵌套到每个选择器里面。这种方法的缺点就是在每个选择器中会有重复的样式产生。


.block {  margin: 10px 5px;  padding: 2px;}p {  .block;/*继承.block选择器下所有样式*/  border: 1px solid #eee;}ul,ol {  .block; /*继承.block选择器下所有样式*/  color: #333;  text-transform: uppercase;}  
复制代码


转译出来的CSS代码:


.block {  margin: 10px 5px;  padding:2px;}p {  margin: 10px 5px;  padding:2px;  border: 1px solid #eee}ul,ol {  margin: 10px 5px;  padding:2px;  color:#333;  text-transform:uppercase;}  
复制代码


正如所看到的,上面的代码“.block”的样式将会被插入到相应的你要继承的选择器中,但需要注意的是优先级的问题。

四、运算符(Operations)

CSS预处理器语言还具有运算的特性,其简单的讲,就是对数值型的Value(如:数字、颜色、变量等)进行加减乘除四则运算。这样的特性在CSS样式中是想都不敢想的,但在CSS预处理器语言中对样式做一些运算一点问题都没有了,例如:


@base_margin: 10px;@double_margin: @base_margin * 2;@full_page: 960px;@half_page: @full_page / 2;@quarter_page: (@full_page / 2) / 2;  
复制代码


上面代码是LESS的运算示例,声明一下,在取得“@quarter_page”变量时,我们可以直接除以 4,但是在这里,我们只是想演示一下圆括号组成的“运算顺序”。在复合型运算中,小括号也是很有必要的,例如:


border: (@width / 2) solid #000;  
复制代码


Sass在数字运算上要比LESS更专业,他可以直接换算单位了。Sass可以处理无法识别的度量单位,并将其输出。这个特性很明显是一个对未来的尝试——证明W3C作出的一些改变。


Stylus的运算是三款预处理器语言中最强大的一款,他拥有其他程序语言一样的运算功能,简单点的加减乘除,复杂的有关系运算、逻辑运算等。受限于篇幅,感兴趣的同学可以到官网上仔细阅读。

五、颜色函数

颜色函数是CSS预处理器语言中内置的颜色函数功能,这些功能可以对颜色进行处理,例如颜色的变亮、变暗、饱和度控制、色相控制,渐变颜色等处理十分的方便。

5.1 Sass 颜色函数

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% 混合色*/  
复制代码


这只是Sass中颜色函数的一个简单列表,更多详细的介绍可以阅读Sass文档


颜色函数可以运用到任何一个元素上,只要其有颜色的属性,下面是一个简单的例子:


$color: #0982C1;h1 {  background: $color;  border: 3px solid darken($color, 50%);/*边框颜色在$color的基础上变暗50%*/}  
复制代码

5.2 LESS 颜色函数

lighten(@color, 10%); /* 返回的颜色在@color基础上变亮10% */darken(@color, 10%);  /* 返回的颜色在@color基础上变暗10%*/saturate(@color, 10%);   /* 返回的颜色在@color基础上饱和度增加10% */desaturate(@color, 10%); /* 返回的颜色在@color基础上饱和度降低10%*/spin(@color, 10);  /* 返回的颜色在@color基础上色调增加10 */spin(@color, -10); /* 返回的颜色在@color基础上色调减少10 */mix(@color1, @color2); /* 返回的颜色是@color1和@color2两者的混合色 */  
复制代码


LESS的完整颜色函数功能,请阅读LESS文档


下面是LESS中如何使用一个颜色函数的简单例子:


@color: #0982C1;h1 {  background: @color;  border: 3px solid darken(@color, 50%);}
复制代码

5.3 Stylus 颜色函数

lighten(color, 10%); /* 返回的颜色在'color'基础上变亮10% */darken(color, 10%);  /* 返回的颜色在'color'基础上变暗10% */saturate(color, 10%);   /* 返回的颜色在'color'基础上饱和度增加10% */desaturate(color, 10%); /* 返回的颜色在'color'基础上饱和度降低10% */    
复制代码


有关于Stylus的颜色函数介绍,请阅读Stylus文档


下面是Stylus颜色函数的一个简单实例:


color = #0982C1h1  background color  border 3px solid darken(color, 50%)  
复制代码


从上面展示的部分颜色函数可以告诉我们,SassLESSStylus都具有强大的颜色函数功能,功能特性上都大同小异,只是在使用方法上略有不同。而且他们都具有相同的一个目的,就是方便操作样式中的颜色值。

六、导入(Import)

CSS中,并不喜欢用@import来导入样式,因为这样的做法会增加http的请求。但是在CSS预处理器中的导入(@import)规则和CSS的有所不同,它只是在语义上导入不同的文件,但最终结果是生成一个CSS文件。


如果你是通过“@import ‘file.css’”导入“file.css”样式文件,那效果跟普通CSS导入样式文件一样。


注意:导入文件中定义了变量、混合等信息也将会被引入到主样式文件中,因此需要避免他们的相互冲突。


SassLESSStylus三款CSS预处理器语言,导入样式的方法都是一样:


被导入文件的样式:


/* file.{type} */body {  background: #EEE;}  
复制代码


需要导入样式的文件:


@import "reset.css";@import "file.{type}";p {  background: #0982C1;}  
复制代码


转译出来的 CSS 代码:


@import "reset.css";body {  background: #EEE;}p {  background: #0982C1;}  
复制代码

七、注释(Comment)

CSS预处理器语言中的注释是比较基础的一部分,这三款预处理器语言除了具有标准的CSS注释之外,还具有单行注释,只不过单行注释不会被转译出来。

7.1 Sass、LESS 和 Stylus 多行注释

多行注释和CSS的标准注释,他们可以输出到CSS样式中,但在Stylus转译时,只有在“compress”选项未启用的时候才会被输出来。


/* *我是注释*/body  padding 5px  
复制代码

7.2 Sass、LESS 和 Stylus 单行注释

单行注释跟JavaScript语言中的注释一样,使用双斜杠(//),但单行注释不会输出到CSS中。


//我是注释@mainColor:#369;//定义主体颜色  
复制代码


Stylus中除了以上两种注释之外,他还有一种注释,叫作多行缓冲注释。这种注释跟多行注释类似,不同之处在于始的时候,这里是”/*!”。这个相当于告诉Stylus压缩的时候这段无视直接输出。


/*!*给定数值合体*/add(a, b)  a + b  
复制代码


上面从九个常用的特性对SassLESSStylus三款CSS预处理器语言的使用做了对比,在某些特性上可以说是一模一样,而有一些特性上功能其实一样,只是在部分书写规则上有所不同。当然有些特性是完全不同。在这里主要是从使用方法上做为一个比较,主要目的是让大家经过对比之后,使自己选择哪一款CSS预处理器语言有所方向和帮助。

八、CSS 预处理器的高级应用

我们知道,SassLESSStylus都具有变量、混合、嵌套、函数和作用域等特性,但这些特性都是一些普通的特性。其实除了这些特性之外,他们还拥有一些很有趣的特性有助于我们的开发,例如条件语句、循环语句等。接下来,我们同样从使用上来对比一下这三款CSS预处理器语言在这方面应用又有何不同异同。

8.1 条件语句

说到编程,对于编程基本控制流,大家并不会感到陌生,除了循环就是条件了。条件提供了语言的可控制,否则就是纯粹的静态语言。提供的条件有导入、混合、函数以及更多。在编程语言中常见的条件语句:


if/else if/else
复制代码


if表达式满足(true)的时候执行后面语句块,否则,继续后面的else ifelse


在这三款CSS3预处理器语言中都具有这种思想,只不过LESS中表达的方式略有不同,接下来我们依次看看他们具体如何使用。

8.1.1 Sass 条件语句

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; }
复制代码


Sass中条件语句还可以和@else if@else配套使用:


$type: monster;p {  @if $type == ocean {    color: blue;  } @else if $type == matador {    color: red;  } @else if $type == monster {    color: green;  } @else {    color: black;  }}  
复制代码


转译出来的CSS


p {color:green;}  
复制代码

8.1.2 Stylus 条件语句

Stylus条件语句的使用和其他编程语言的条件语句使用基本类似,不同的是他可以在样式省略大括号({}):


box(x, y, margin = false)  padding y x  if margin    margin y xbody  box(5px, 10px, true)  
复制代码


Stylus同样可以和else ifelse配套使用:


box(x, y, margin-only = false)  if margin-only    margin y x  else    padding y x  
复制代码


Stylus除了这种简单的条件语句应用之外,他还支持后缀条件语句。这就意味着ifunless(熟悉 Ruby 程序语言的用户应该都知道 unless 条件,其基本上与 if 相反,本质上是“(!(expr))”)当作操作符;当右边表达式为真的时候执行左边的操作对象。


例如,我们定义了negative()来执行一些基本的检查。下面我们使用块式条件:


negative(n)  unless n is a 'unit'    error('无效数值')  if n < 0    yes  else    no  
复制代码


接下来,我们利用后缀条件让我们的方法简洁:


negative(n)  error('无效数值') unless n is a 'unit'  return yes if n < 0  no  
复制代码


当然,我们可以更进一步。如这个“n < 0 ? yes : no”可以用布尔代替:“n < 0”。后缀条件适合于大多数的单行语句。如“@import,@charset”混合书写等。当然,下面所示的属性也是可以的:


pad(types = margin padding, n = 5px)  padding unit(n, px) if padding in types  margin unit(n, px) if margin in types
body pad()
body pad(margin)
body apply-mixins = true pad(padding, 10) if apply-mixins
复制代码


上面代码转译出来的CSS


body {  padding: 5px;  margin: 5px;}body {  margin: 5px;}body {  padding: 10px;}  
复制代码

8.1.3 LESS 条件语句

LESS的条件语句使用有些另类,他不是我们常见的关键词ifelse if之类,其实现方式是利用关键词“when”。


.mixin (@a) when (@a >= 10) {   background-color: black;  }  .mixin (@a) when (@a < 10) {   background-color: white;  }  .class1 { .mixin(12) }  .class2 { .mixin(6) }  
复制代码


转译出来的CSS


.class1 {   background-color: black;  } .class2 {   background-color: white;  }  
复制代码


利用When以及<、>、=、<=、>=是十分简单和方便的。LESS并没有停留在这里,而且提供了很多类型检查函数来辅助条件表达式,例如:iscolorisnumberisstringiskeywordisurl等等。


.mixin (@a) when (iscolor(@a)) {   background-color: black;  }  .mixin (@a) when (isnumber(@a)) {   background-color: white;  }  .class1 { .mixin(red) }  .class2 { .mixin(6) }  
复制代码


转译出来的 CSS


.class1 {   background-color: black;  }  .class2 {   background-color: white;  }  
复制代码


另外,LESS的条件表达式同样支持ANDOR以及NOT来组合条件表达式,这样可以组织成更为强大的条件表达式。需要特别指出的一点是,ORLESS中并不是or关键词,而是用,来表示or的逻辑关系。


.smaller (@a, @b) when (@a > @b) {   background-color: black; } .math (@a) when (@a > 10) and (@a < 20) {   background-color: red; } .math (@a) when (@a < 10),(@a > 20) {   background-color: blue; } .math (@a) when not (@a = 10)  {   background-color: yellow; } .math (@a) when (@a = 10)  {   background-color: green; }  .testSmall {.smaller(30, 10) } .testMath1 {.math(15)} .testMath2 {.math(7)} .testMath3 {.math(10)}
复制代码


转译出来的 CSS


.testSmall {   background-color: black; } .testMath1 {   background-color: red;   background-color: yellow; } .testMath2 {   background-color: blue;   background-color: yellow; } .testMath3 {   background-color: green; }  
复制代码

8.2 循环语句

SassStylus还支持for循环语句,而LESS并没支持for循环语句,但值得庆幸的是,在LESS中可以使用When来模拟出for循环的特性。

8.2.1 Sass 循环语句

Sass中使用for循环语句需要使用@for,并且配合“from”和“through”一起使用,其基本语法:


@for $var from <start> through <end> {语句块}  
复制代码


我们来看一个简单的例子:


@for $i from 1 through 3 {  .item-#{$i} { width: 2em * $i; }}  
复制代码


转译出来的 CSS 代码:


.item-1 {  width: 2em; }.item-2 {  width: 4em; }.item-3 {  width: 6em; }  
复制代码


Sass中循环语句除了@for语句之外,还有@each语句和@while语句


@each循环语法:


@each $var in <list>{语句块}  
复制代码


来看个简单的实例:


@each $animal in puma, sea-slug, egret, salamander {  .#{$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'); }.salamander-icon {  background-image: url('/images/salamander.png')  }
复制代码


@while循环使用和其他编程语言类似:


$i: 6;@while $i > 0 {  .item-#{$i} { width: 2em * $i; }  $i: $i - 2;}  
复制代码


转译出来的 CSS


.item-6 {  width: 12em; }.item-4 {  width: 8em; }.item-2 {  width: 4em; }  
复制代码

8.2.2 Stylus 循环语句

Stylus样式中通过for/in对表达式进行循环,形式如下:


for <val-name> [, <key-name>] in <expression>  
复制代码


例如:


body  for num in 1 2 3    foo num  
复制代码


转译出来 CSS


body {  foo: 1;  foo: 2;  foo: 3;}  
复制代码


下面这个例子演示了如何使用<key-name>


body  fonts = Impact Arial sans-serif  for font, i in fonts    foo i font  
复制代码


转译出来的CSS


body {  foo: 0 Impact;  foo: 1 Arial;  foo: 2 sans-serif;}  
复制代码

8.2.3 LESS 循环语句

LESS语言中并没有循环语句,可是像其条件语句一样,通过when来模拟出他的循环功能。


.loopingClass (@index) when (@index > 0) {  .myclass {    z-index: @index;  }  // 递归  .loopingClass(@index - 1);}// 停止循环.loopingClass (0) {} // 输出.loopingClass (3);  
复制代码


转译出的 CSS


.myclass {z-index: 3;}.myclass {z-index: 2;}.myclass {z-index: 1;}  
复制代码


相比之下,SassStylus对条件语句和循环语句的处理要比LESS语言强大。因为他们具有真正的语言处理能力。


综上所述,我们对SassLESSStylus做一个简单的对比总结:


  • 三者都是开源项目;

  • Sass诞生是最早也是最成熟的CSS预处理器,有Ruby社区和Compass支持;Stylus早期服务器Node JS项目,在该社区得到一定支持者;LESS出现于 2009 年,支持者远超于 Ruby 和 Node JS 社区;

  • SassLESS语法较为严谨、严密,而Stylus语法相对散漫,所以LESS学习起来更快一些,因为他更像CSS的标准;

  • SassLESS相互影响较大,其中SassLESS影响,已经进化到了全面兼容CSSSCSS

  • SassLESS都有第三方工具提供转译,特别是SassCompass是绝配;

  • SassLESSStylus都具有变量、作用域、混合、嵌套、继承、运算符、颜色函数、导入和注释等基本特性,而且以“变量”、“混合”、“嵌套”、“继承”和“颜色函数”称为五大基本特性,各自特性实现功能基本相似,只是使用规则上有所不同;

  • SassStylus具有类似于语言处理的能力,比如说条件语句循环语句等,而 LESS 需要通过When等关键词模拟这些功能,在这一方面略逊一层;


上面是CSS预处理器语言中的SassLESSStylus在某些方面的对比,相对于CSS来说,上面都是CSS预处理器语言的优点?那么他有没有缺点呢?


万物都有阴阳两极,有圆就有缺,CSS预处理器语言也逃避不了这个宿命。个人感觉 CSS 预处理器语言那是程序员的玩具,想通过编程的方式跨界解决 CSS 的问题。可以说 CSS 应该面临的问题一个也少不了,只是增加了一个编译过程而已,简单来说 CSS 预处理器语言较 CSS 玩法变得更高级了,但同时降低了自己对最终代码的控制力。更致命的是提高了门槛,首先是上手门槛,其次是维护门槛,再来是团队整体水平和规范的门槛。这也造成了初学学习成本的昂贵。

九、拓展阅读

发布于: 3 小时前阅读数: 3
用户头像

No Silver Bullet 2021.07.09 加入

岂曰无衣 与子同袍

评论

发布
暂无评论
Vue进阶(幺柒捌):延伸阅读Sass、Scss、Less与Stylus编程特性