欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

Sass-也许你想和CSS玩耍起来(上篇)

程序员文章站 2022-04-05 20:26:09
...

我们努力,我们坚持,共勉!

众所周知,css其实不是一门编程语言,熟悉的人都知道css全称Cascading Style Sheets(层叠样式表)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。我们用它来实现表现层和结构层的分离,也就是html和样式的分离。你可以用它为网页制定样式,但是他无法像JavaScript一样声明变量,调用函数,使用条件语句,可以说JavaScript是灵活的,动态的,而css是死板的,一成不变的。

所以,有人想要为其加入编程的思想,让他拥有遍历,拥有方法,甚至拥有继承,能够告诉你语法上的错误,所以有了css预处理,它的思想是先用一门新的专门编程的语言来设计网页样式,再编译成css,其实最后引用的仍旧是编译出来的css。

说到css预处理,可能大部分人首先想到的是Less。现在做css预处理的语言比较优秀的Less是其一:它快速方便入门简单,sass是其二:相对来说说它更加灵活,语法更多(尤其是if,else,for),当然好多人不使用的原因是嫌弃它安装不方便(还好有淘宝镜像),其三是Stylus:他与sass比较类似都是更加灵活强大。这里因为我比较喜爱Sass并且相信它不会那么快死去,所以对sass做一个简单介绍。

想好什么时候我们可以使用css预处理

诚然,css预处理让我们对样式的处理更加编程化,但是我们仍需要考虑好在怎样的环境中使用它,因为我们知道,无论你的sass代码多么炫酷,逻辑多么缜密,到最后都是生成了一个css文件(老前辈对年轻的我的教诲)。

所以我们需要根据项目的大小以及开发时间团队成本来确定,如果项目比较小需要的css并不是太多并且开发时间紧迫团队里很多人还不会使用,那么可能使用原生的css可能会更好一些。

sass基础

安装~

咳咳,不得不说好多开发者本来是想使用sass的,但是因为sass是基于ruby的,高墙在上,ruby装半天装不上,于是放弃呼。这里推荐你看下W3Cplus的教程使用淘宝的镜像来进行安装,包括node的一些包的安装我都是使用的淘宝镜像来进行安装的,很快很强大。

编译~

咳咳,很多朋友安装完了,但是发现编译起来很麻烦。这里继续上链接sass编译教程,我在这里推荐大家使用考拉来进行编译,虽然考拉已经停止更新但是它确实是十分实用的,less,sass都可以编译,而且可以在编译时进行压缩。

sass和scss

先来看看区别吧

$color : red;

//sass语法
.box
    color:$color;

//scss语法
.box{
  color:$color;
}

其实sass语法是sass最开始的语法结构,是通过tab缩进来进行的一个规则,有点类似jade模板的那种缩进,而且这种语法规则十分严格,有啥不对劲,编译的时候就报错。

而scss呢,是sass的新语法格式,不要认为他是另外一种预处理语言,其实它是sass在发现之前的语法结构太过于严格,并且和css有点不像后重新定制的语法结构,它在外观上是与css基本一致的,并且它十分宽松,你可以直接将之前的css代码复制过来。

我在这里写在了一个代码块中只是示例,其实他们文件名是分别以.sass和.scss来结尾的。

变量声明和调用

这是sass的编程元素基础之一。在JS中我们使用var来声明变量,当然ES6中新加了let,const。而在sass声明和调用变量的规则如下

$height: 15px !default;  //声明默认变量
$height: 50px;  //声明普通变量
body{
    height: $height; 
}

变量有默认变量和普通变量之分,默认变量只需像!important 一样在值后面加上!default即可。其实一般情况下我们只需要声明普通变量,默认变量在开发组件时使用比较方便。变量声明我就不用说了,真的很简单。

嵌套和局部变量,全局变量

和JS类似,sass语法中也有局部变量和全局变量。如下在最外层声明的是全局变量,全局范围内可以调用,在em{}中声明的是em的局部变量,只在em{}内部内进行调用。

$color:#000;  //全局变量
.block {
  color: $color;
}
em {
  $color: #fff;  //局部变量
  a {    //选择器嵌套
    color: $color;
    font: {    //属性嵌套
    size: 12px;
    weight: bold;
   }
    &:hover { //伪类嵌套
     color: $color;
    }   
  }
}

数据类型

和JS类似,sass也拥有自己的数据类型分别是

  • 数字: 如,1、 2、 13、 10px;
  • 字符串:有引号字符串或无引号字符串,如,"foo"、 'bar'、 baz;
  • 颜色:如,blue、 #04a3f9、 rgba(255,0,0,0.5);
  • 布尔型:如,true、 false;
  • 空值:如,null;
  • 值列表:用空格或者逗号分开,如,1.5em 1em 0 2em 、 Helvetica, Arial, sans-serif。

混合宏

编程的思想嘛。混合宏是一个类似于函数的存在,当然,他并不是函数。简单来说就是加了参数功能的灵活度提升的可重用的代码块。

@mixin border-radius{
    -webkit-border-radius: 5px;
    border-radius: 5px;
}

button {
    @include border-radius;
}

这里是一个简单的混合宏的使用,先是用@mixin定义了一个名叫border-radius的混合宏,然后在代码中利用@include进行调用,其实这样的话并不能太大体现出混合宏的特色。看下面的

@mixin border-radius1($radius){
  -webkit-border-radius: $radius;
  border-radius: $radius;
}
@mixin border-radius2($radius:5px){
  -webkit-border-radius: $radius;
  border-radius: $radius;
}

.box1 { @include border-radius(5px); } .box2 { @include border-radius; } .box2 { @include border-radius(5px); }

从代码里可以看出,混合宏可以像函数一样传入参数,并且可以像ES6的函数扩展一样添加参数默认值,如果在调用的时候不传参数,那么就会使用默认的值,这样极大的增加了代码的灵活性,省却很多开发时间。

其实,mixin的灵活还不仅仅如此,它可以传入多个参数,这样我们想到了函数可以根据参数数量的不同来执行不同的代码。yes !sass也可以做到!

@mixin size($width,$height){    //两个参数或者多个参数可以这样这样定义
  width: $width;
  height: $height;
}

.box-center {
  @include size(100px,200px);
}
@mixin box-shadow($shadows...){    //参数过多可以使用...来代替
  @if length($shadows) >= 1 {
    -webkit-box-shadow: $shadows;
    box-shadow: $shadows;
  } @else {
    $shadows: 0 0 2px rgba(#000,.25);
    -webkit-box-shadow: $shadow;
    box-shadow: $shadow;
  }
}
.box {
  @include box-shadow(0 0 1px rgba(#000,.5),0 0 2px rgba(#000,.2));
}

上面两个代码块第一个比较简单,就是增加参数数目。下面的代码块我们利用sass的if else方法来实现了判断,如果参数数目大于等于1,也就是传了参数,那么我们执行上面的代码,如果没有传参我们执行下面的代码,设置默认的$shadows值生成代码块。

但是混合宏也有不足之处:那就是调用一个混合宏生成的css代码并不会进行合并,这也是因为他能够传参所设置的,所以对于复用性很强的代码块不推荐使用混合宏。

继承和占位符

sass允许你使用@extend继承别的代码块,并且通过@extend所继承的代码块会在生成css的时候进行合并~哈哈,完美解决了上面的问题

.btn1 {
  border: 1px solid #ccc;
  padding: 6px 10px;
  font-size: 14px;
}

%btn2 {
  border: 1px solid #ccc;
  padding: 6px 10px;
  font-size: 14px;
}

%btn3 {
  border: 1px solid #ccc;
  padding: 6px 10px;
  font-size: 14px;
}

.btn-primary1 {
  background-color: #f36;
  color: #fff;
  @extend .btn1;
}

.btn-primary2 {
  background-color: #f36;
  color: #fff;
  @extend %btn2;
}

上面的代码中.btn1是预先定义好的类,然后我们在.btn-primary1中继承他的所有代码块,而%btn2就是在标题里所提到的占位符,占位符的代码块如果不被继承在生成的css中是不会显示出来的,所以如果你是用sass编译css的话,公共类使用占位符来定义是一个很不错的选择。为了加深理解我们看下上面的代码所生成的css代码。

.btn1, .btn-primary1 {
  border: 1px solid #ccc;
  padding: 6px 10px;
  font-size: 14px; }

.btn-primary2 {
  border: 1px solid #ccc;
  padding: 6px 10px;
  font-size: 14px; }

.btn-primary1 {
  background-color: #f36;
  color: #fff; }

.btn-primary2 {
  background-color: #f36;
  color: #fff; }

继承btn1的btn-primary1他和btn1进行了合并,而我们使用占位符定义的%btn2,%btn3在生成代码里没有显示,因为btn-primary2继承了%btn2,所以他继承的公共部分被单独拿出来,如果有多个代码块继承%btn2,他们会进行合并。

占位符还是混合宏,主要还是看你的代码怎么使用,如果只是静态的代码公共块,那么占位符会比较适合,而如果是可变的代码例如写一个复杂的css3动画之类的,可能混合宏比较适合了。

插值#{}

如果接触过jade模板的朋友会比较熟悉,这里的插值和它用法是基本一致的。让我们来看一个复杂的代码块

$properties: (margin, padding);
@mixin set-value($side, $value) {
    @each $prop in $properties {
        #{$prop}-#{$side}: $value;
    }
}
.login-box {
    @include set-value(top, 14px);
}

首先我们声明了一个$properties的变量,里面是一个值列表里面两个字符串,@mixin方法里我们通过@each方法循环出值列表里面的字符串然后利用插值的方法将字符串插入进去,我们看下生成的css代码

.login-box {
  margin-top: 14px;
  padding-top: 14px; }

这里只是做一个示例,正常情况下我们不会用这么复杂的方法来生成这么短的css代码,那样才是真正的浪费开发时间,当然茶余饭后做个组件开发的话,还是很有用的。

运算

sass允许我们做一些基本的运算:加减乘除,但是我要说的是:注意单位!注意单位!注意单位!当然如果你异想天开em+px,px*px,px/rem。。。我表示。。。

需要知道的是sass里允许进行颜色运算,也就是说 #222222 * 2你将会得到 #444444,其实颜色的运算机制是分段运算也就是说如果22*2 22*2 22*2然后在进行合并的。

字符串运算:

字符串可以通过+来进行链接,放心减号是不管用的。。。需要注意的是因为sass的字符串有两种类型,带引号和不带引号,相同相加当然出来的是一致的。如果有引号的字符串被添加了一个没有引号的字符串 (也就是,带引号的字符串在 + 符号左侧), 结果会是一个有引号的字符串。 同样的,如果一个没有引号的字符串被添加了一个有引号的字符串 (没有引号的字符串在 + 符号左侧), 结果将是一个没有引号的字符串,其实就是谁在左边就跟着谁。

p:before {
  content: "Foo " + Bar;
  font-family: sans- + "serif";
}
//生成的css如下
p:before {
  content: "Foo Bar";
  font-family: sans-serif; }

上面的内容就是sass的上篇。都是一些基础的东西,下篇的话会整理一下说到函数和方法规则相关的东西。