SASS%……%

Sass入门(1)

2016-12-23  本文已影响386人  SA_Arthur

前言

什么是CSS预处理器

定义:

CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行编码工作。

通俗的说,“CSS预处理器用一种专门的编程语言,进行Web页面样式设计,然后再编译成正常的CSS文件,以供项目使用。CSS预处理器为CSS增加了一些编程的特性,无需考虑浏览器的兼容问题”,例如你可以在CSS中使用变量简单的逻辑程序函数等等在编程语言中的一些基本特性,可以让你的CSS更加简洁适应性更强可读性更佳更易于代码的维护等诸多好处。

其他CSS预处理器语言:

CSS预处理器技术已经非常的成熟,而且也涌现出了很多种不同的CSS预处理器语言(前三者较为流行),比如说:

  • Sass(Scss)
  • Less
  • Stylus
  • Turbine
  • Swithch CSS
  • CSS Cacheer
  • DT CSS

如何描述Sass

Sass是一门高于CSS的元语言(可以看一下元编程),它能用来清晰的结构化地描述文件样式,有着比普通CSS更加强大的功能。Sass能够提供更简洁更优雅的语法,同时提供多种功能来创建可维护管理的样式表。

下文中Sass表示sass和scss的统称,演示方法采取scss新语法,sass则表示Sass旧语法。


sass和scss有什么区别?

sass和scss其实是同一种东西,我们平时都称之为Sass,两者之间的不同在于:

sass/scss和纯CSS写法有区别吗?

sass语法格式

这里说的sass语法是Sass的最初语法格式,它是通过tab键控制缩进的一种语法规则,而且这种缩进要求非常严格,并且不能带有任何大括号和分号。所以常常把这种格式称之为Sass老版本,其文件名以“.sass”为扩展名。

例如:

body { 
    font: 100% Helvetica, sans-serif; 
    color: #333;
}

用sass的语法格式来写就是:

$font-stack: Helvetica, sans-serif
$primary-color: #333
body
    font: 100%
    $font-stack color: $primary-color

在整个sass代码中,是没有类似CSS中的大括号和分号。

scss语法格式

scss是Sass的新语法格式,从外形上来判断,它和CSS长得几乎是一模一样,代码都包裹在一堆大括号里,并且末尾结束处都有一个分号,其文件格式名常常以“.scss”为扩展名。

同样的CSS代码:

body {
    font: 100% Helvetica, sans-serif; 
    color: #333;
}

使用scss语法格式将会是下面这样:

$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
    font: 100% $font-stack;
    color: $primary-color;
}

这样的语法格式便于经常使用CSS的程序员。

但是不管是sass的语法格式还是scss的语法格式,它们的功能都是一样的,不同的只是书写格式文件扩展名

下面是对比图:


“.sass”只能使用Sass老语法规则,也就是sass语法的缩进规则,“.scss”使用的是Sass的新语法规则,也就是scss语法规则(类似CSS语法格式)。

Sass命令编译

命令编译指的是使用电脑中的命令终端,通过输入Sass指令来编译Sass,这种编译方式是最直接也是最简单的一种方式,因为只需要在你的命令终端输入:

单文件编译:

sass <要编译的Sass文件路径>/style.scss:<要输出的CSS文件路径>/style.css

这是对一个单文件进行编译,如果想对整个项目所有Sass文件编译成CSS文件,可以这样操作:

多文件编译:

sass sass/:css/

上面的命令表示将项目中“sass”文件夹中所有“.scss”(“.sass”)文件编译成“.css”文件,并且将这些CSS文件都放在项目中“CSS”文件夹中。

缺点以及解决方法:

在实际编译过程中,你会发现上面的命令,只能一次性编译。每次个性保存“.scss”文件之后,都得重新执行一次这样的命令,这样操作太麻烦,所以在编译Sass的时候,可以开启“watch”功能,这样只要你的代码进行过任何保存修改,都能自动监测到代码的变化,并且直接编译出来。

sass --watch <要編譯的Sass文件路徑>/style.scss:<要輸出的CSS文件路徑>/style.css

当然,使用Sass命令编译时,可以带很多的参数:

watch 举例:
假设本地有一个项目,要将项目中的“bootstrap.scss”编译出“bootstrap.css”文件,并且将编译出来的文件放在“css”文件夹中,那么可以在命令终端执行:

sass --watch sass/bootstrap.scss:css/bootstrap.css

一旦我的bootstrap.scss文件有任何修改,只要重新保存了修改文件,命令终端就能监测,并且重新编译出文件:


Sass不同样式风格的输出方法

sass --watch test.scss:test.css --style nested/expanded/compact/compressed
style后面就是输出方法

Sass基础语法

变量

Sass的变量包括三个部分:

普通变量和默认变量

普通变量

定义之后可以在全局范围内使用。

$fontSize: 12px;
body {
    font-size:$fontSize;
}

编译后的CSS代码:

body {
    font-size:12px;
}
默认变量

Sass的默认变量仅需要在值后面加上!default即可。

$baseLineHeight:1.5 !default;
body { 
    line-height: $baseLineHeight;
}

编译后的css代码:

body {
    line-height:1.5;
}

SASS的默认变量一般是用来设置默认值,然后根据需求来覆盖的。覆盖的方式也很简单,只需要在默认变量之前重新声明下变量即可。

$baseLineHeight: 2;
$baseLineHeight: 1.5 !default;
body{ 
    line-height: $baseLineHeight; 
}

编译后的CSS代码:

body { 
    line-height:2;
}

变量的调用

在Sass中声明了变量之后,就可以在需要的地方调用变量。调用变量的方法也很简单。

例如定义了变量:

$brand-primary : darken(#428bca, 6.5%) !default;   // #337ab7 
$btn-primary-color: #fff !default;
$btn-primary-bg : $brand-primary !default;
$btn-primary-border : darken($btn-primary-bg, 5%) !default;

在按钮button中调用,可以按下面的方式调用:

.btn-primary {
    background-color: $btn-primary-bg; 
    color: $btn-primary-color; 
    border: 1px solid $btn-primary-border;
}

编译出来的CSS:

.btn-primary { 
    background-color: #337ab7; 
    color: #fff; 
    border: 1px solid #2e6da4;
}

全局变量和局部变量

Sass中变量的概念与其他CSS预处理器不一致,例如:

嵌套

Sass有三种嵌套方式:

选择器嵌套

/* Sass */
nav {
  a {
    color: red;
    header & {
      color:green;
    }
  }  
}

/* css */
nav a {
    color:red;
}
header nav a {
    color:green;
}

属性嵌套

/* Sass */
.box {
    border: {
    top: 1px solid red;
    bottom: 1px solid green;
  }
}

/* css */
.box {
    border-top: 1px solid red;
    border-bottom: 1px solid green;
}

伪类嵌套

/* Sass */
.clearfix{
    &:before,
    &:after { 
        content:""; 
        display: table;
    }
    &:after { 
        clear:both; 
        overflow: hidden; 
    }
}

/* css */
clearfix:before, .clearfix:after {
    content: "";
    display: table;
}
.clearfix:after {
    clear: both;
    overflow: hidden;
}

混合宏

@mixin是用来声明混合宏的关键词,@include调用声明好的混合宏。

/* 不带参数的混合宏 */
@mixin border-radius{  
    -webkit-border-radius: 5px; 
    border-radius: 5px;
}  
/* 带参数的混合宏 */
@mixin border-radius($radius:5px){ 
    -webkit-border-radius: $radius; 
    border-radius: $radius;
}

还有复杂的混合宏:

@mixin box-shadow($shadow...) {   // 带有多个参数,这个时候可以用"..."来替代
    @if length($shadow) >= 1 { 
        @include prefixer(box-shadow, $shadow); 
     } @else{ 
        $shadow:0 0 4px rgba(0,0,0,.3); 
        @include prefixer(box-shadow, $shadow); 
    }
}

混合宏的参数

  1. 传一个不带值的参数

    在混合宏中,可以传一个不带任何值的参数,例如:

    @mixin border-radius($radius) { 
        -webkit-border-radius: $radius;
        border-radius: $radius;
    }
    

    在混合宏“border-radius”中定义了一个不带任何值的参数“$radius”,在调用的时候可以给这个混合宏传一个参数值:

    .box { 
        @include border-radius(3px);
    }
    

    这里表示给混合宏传递了一个“border-radius”的值为“3px”
    编译出来的CSS:

    .box { 
          -webkit-border-radius: 3px; 
          border-radius: 3px;
    }
    
  2. 传一个带值的参数

    在Sass的混合宏中,还可以给混合宏的参数传一个默认值,例如:

    @mixin border-radius($radius:3px) { 
          -webkit-border-radius: $radius; 
          border-radius: $radius;
    }
    

    在混合宏“border-radius”传了一个参数“$radius”,而且给这个参数赋予了一个默认值“3px”
    在调用类似这样的混合宏时,会多有一个机会,假设你的页面中的圆角很多地方都是“3px”的圆角,那么这个时候只需要调用默认的混合宏“border-radius”:

    .btn { 
          @include border-radius;
    }
    

    编译出来的CSS:

    .btn { 
          -webkit-border-radius: 3px;
          border-radius: 3px;
    }
    

    但有的时候,页面中有些元素的圆角值不一样,那么可以随机给混合宏传值,例如:

    .box { 
          @include border-radius(50%);
    }
    

    编译出来的CSS:

    .box { 
          -webkit-border-radius: 50%; 
          border-radius: 50%;
    }
    
  3. 传多个参数
    Sass混合宏除了能传一个参数之外,还可以传多个参数,例如:

    @mixin center($width,$height) {
          width: $width; 
          height: $height; 
          position: absolute; 
          top: 50%; 
          left: 50%; 
          margin-top: -($height) / 2; 
          margin-left: -($width) / 2;
    }
    

    在混合宏“center”就传了多个参数。
    并且在实际调用和调用其他混合宏是一样的:

    .box-center { 
          @include center(500px,300px);
    }
    

    编译出来的CSS:

    .box-center { 
          width: 500px; 
          height: 300px; 
          position: absolute; 
          top: 50%; 
          left: 50%; 
          margin-top: -150px; 
          margin-left: -250px;
    }
    

    有一个特别的参数“…”,当混合宏传的参数过多的时候,可以使用该参数来替代,例如:

    @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));
    }
    

    编译出来的CSS:

    .box { 
          -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.5), 0 0 2px rgba(0, 0, 0, 0.2); 
          box-shadow: 0 0 1px rgba(0, 0, 0, 0.5), 0 0 2px rgba(0, 0, 0, 0.2);
    }
    

    混合宏会生成冗余的代码块,Sass在调用相同的混合宏时,并不能智能地将相同的样式代码块合并在一起。

Sass扩展和继承

Sass中是通过关键词“@extend”来继承已存在的类样式块,在Sass中的继承,可以继承类样式块中所有样式代码,而且编译出来的CSS将会把选择器合并在一起,形成组合选择器。

例如:

.btn { 
      border: 1px solid #ccc; 
      padding: 6px 10px; 
      font-size: 14px;
}
.btn-primary { 
      background-color: #f36; 
      color: #fff; 
      @extend .btn;
}

.btn-second { 
      background-color: orange; 
      color: #fff; 
      @extend .btn;
}

生成:.btn.btn-primary.btn-second三个相同样式合并在一起。

.btn, .btn-primary, .btn-second { 
      border: 1px solid #ccc; 
      padding: 6px 10px; 
      font-size: 14px;
}
.btn-primary { 
      background-color: #f36; 
      color: #fff;
}
.btn-second { 
      background-clor: orange; 
      color: #fff;
}

占位符%placeholder

Sass中的占位符%placeholder功能是一个很强大,很实用的一个功能,它可以取代以前CSS中的基类造成的代码冗余的情况。因为%placeholder声明的代码,如果不被@extend调用的话,不会产生任何代码。
例如:

%mt5 { 
      margin-top: 5px;
} 
%pt5{ 
      padding-top: 5px;
}

这段代码没有被@extend调用,它没有产生任何代码块,只是静静地躺在某个Sass文件中,只有通过@extend调用才会产生代码:

%mt5 { 
      margin-top: 5px;
}
%pt5{ 
      padding-top: 5px;
}
.btn { 
      @extend %mt5; 
      @extend %pt5;
}
.block { 
      @extend %mt5; 
      span { 
          @extend %pt5; 
      }
}

编译出来的CSS:

.btn, .block { 
      margin-top: 5px;
}
.btn, .block span { 
      padding-top: 5px;
}

从编译出来的CSS代码可以看出,通过@extend调用的占位符,编译出来的代码会将相同代码合并在一起。

混合宏、继承、占位符的区别

Sass插值#{}

使用CSS预处理器语言的一个主要原因是想使用Sass获得一个更好的结构体系。例如说想要写更干净的高效面向对象的CSS。Sass中的插值(Interpolation)就是重要的一部分。

例如:

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

它可以让变量和属性工作得很完美,上面的代码编译成CSS:

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

这是Sass插值中简单的例子,当你想设置属性值的时候可以使用字符串插入进来。另一个有用的办法是构建一个选择器,例如:

@mixin generate-sizes($class, $small, $medium, $big) { 
      .#{$class}-small { font-size: $small; } 
      .#{$class}-medium { font-size: $medium; } 
      .#{$class}-big { font-size: $big; }
}
@include generate-sizes("header-text", 12px, 20px, 40px);

编译出来的CSS:

.header-text-small { 
    font-size: 12px; 
}
.header-text-medium { 
    font-size: 20px; 
}
.header-text-big { 
    font-size: 40px; 
}
一旦發現這一點,就會想到用`mixins`來生成代碼或是另一個`mixins`,但是會有限制,可能會刪除用於Sass變量的插值。
例如:

一旦发现这一点,就会想到用mixins(混合指令)来生成代码或是另一个mixins,但是会有限制,可能会删除用于Sass变量的插值。

例如:

$margin-big: 40px;
$margin-medium: 20px;
$margin-small: 12px;
@mixin set-value($size) { 
      margin-top: $margin-#{$size};
}
.login-box { 
      @include set-value(big);
}

上面的Sass代码编译出来会得到:

error style.scss (Line 5: Undefined variable: “$margin-".)

所以,#{}语法并不是随处可用的,也不能在mixin中调用:

@mixin updated-status { 
      margin-top: 20px; 
      background: #F00;
}
$flag: "status";
.navigation { 
      @include updated-#{$flag};
}

上面代码在编译成CSS时同样会报错:

error style.scss (Line 7: Invalid CSS after "...nclude updated-": expected "}", was "#{$flag};")

但是可以在@extend中使用插值,例如:

%updated-status { 
      margin-top: 20px; 
      background: #F00;
}
.selected-status {
      font-weight: bold;
}
$flag: "status";.navigation { 
      @extend %updated-#{$flag}; 
      @extend .selected-#{$flag};
}

上面的Sass代码是可以运行的,可以动态地插入.class%placeholder,但是不接受mixin这样的参数,例如上面的代码编译出来的CSS:

.navigation { 
      margin-top: 20px; 
      background: #F00;
}
.selected-status, .navigation { 
      font-weight: bold;
}

Sass注释

Sass字符串

SassScript 支持 CSS 的两种字符串类型:

在编译CSS文件时不会改变其类型,但如果是使用#{}插值语句 (interpolation) 时,有引号的字符串将会被编译成无引号的字符串,这样方便了在混合指令mixin中引用选择起名。

@mixin firefox-message($selector) { 
      body.firefox #{$selector}:before { 
         content: "Hi, Firefox users!"; 
      }
}
@include firefox-message(".header");

编译为:

body.firefox .header:before { 
      content: "Hi, Firefox users!"; 
}

需要注意的是:当deprecated = property syntax 时(暂时不理解是为什么),所有字符串都将被编译为无引号字符串,无论是否使用了引号。

Sass值列表

所谓值列表(lists)是指Sass如何处理CSS中:

margin: 10px 15px 0 0;

或者:

font-face: Helvetica, Arial, sans-serif;

像上面这样通过空格或者逗号分隔的一系列的值。
事实上,独立的值也被视为值列表——只包含一个值的值列表。

Sass列表函数()赋予了值列表更多的功能:

Sass运算

加法

加法运算是Sass运算中的一种,在变量或属性中都可以做加法运算。
例如:

.box { 
    width: 20px + 8in;
}

编译出来的CSS:

.box { 
    width: 788px;
}

但对于携带不同类型的单位时,在Sass中计算会报错,如下所示:

.box {
  width: 20px + 1em;
}

编译的时候,编译器会报错:“Incompatible units: 'em' and ‘px'”。

减法

Sass的减法运算和加法运算类似。
例如:

$full-width: 960px;
$sidebar-width: 200px;
.content { 
    width: $full-width **-** $sidebar-width;
}

编译出来的CSS:

.content { 
    width: 760px;
}

在减法中,单位不同也会报错。

乘法

Sass中的乘法运算和前面介绍的加法与减法运算略有不同,虽然乘法可以支持多种单位(例如em、px、%...),但当一个单位同时声明两个值时会有问题。
例如:

.box { 
    width:10px * 2px; 
}

编译的时候报“20px*px isn't a valid CSS value.”错误信息。

如果进行乘法运算时,两个值单位相同时,只需要为一个数值提供单位即可,上面的例子可以修改成:

.box { 
    width: 10px * 2;
}

编译出来的CSS:

.box { 
    width: 20px;
}

Sass的乘法运算和加法、减法运算一样,在运算中有不同类型的单位时,也会报错。

例如:

.box { 
    width: 20px * 2em;
}

编译时报“40em*px isn't a valid CSS value.”错误信息。

除法

Sass的乘法运算规则也适用于除法运算。不过除法运算还有一个特殊之处,众所周知“/”符号在CSS中已经作为一种符号使用。因此在Sass中做除法运算时,直接使用“/”符号作为除号时,将不会生效,编译时既得不到所想要的效果,也不会报错。

“/”符号被当作除法运算符时有以下几种情况:

如下所示:

p { 
      font: 10px/8px;  // 纯CSS,不是除法运算 
      $width: 1000px; 
      width: $width/2;  // 使用了变量,是除法运算 
      width: round(1.5)/2;  // 使用了函数,是除法运算 
      height: (500px/2);  // 使用了圆括号,是除法运算 
      margin-left: 5px + 8px/2px;  // 使用了加号(+),是除法运算
}

编译出来的CSS:

p {
      font: 10px/8px; 
      width: 500px; 
      height: 250px; 
      margin-left: 9px; 
}

在除法运算时,如果两个值带有相同的单位值时,除法运算之后会得到一个不带单位的数值。

变量计算

在Sass中除了可以使用数值进行运算之外,还可以使用变量进行计算。
例如:

$content-width: 720px;
$sidebar-width: 220px;
$gutter: 20px;
.container { 
      width: $content-width + $sidebar-width + $gutter; 
      margin: 0 auto;
}

编译出来的CSS:

.container {
    width: 960px;
    margin: 0 auto;
}

数字运算

在Sass运算中数字运算是较为常见的,数字运算包括前面的:加法、减法、乘法和除法等运算,而且还可以通过括号来修改它们的运算先后顺序。

.box {
      width: ((220px + 720px) - 11 * 20 ) / 12 ;  
}

编译出来的CSS:

.box {
      width: 60px;
}

颜色运算

所有算术运算都支持颜色值,并且是分段运算的。也就是说,红、绿和蓝各颜色分段单独进行运算。
例如:

p { 
      color: #010203 + #040506;
}

计算公式为01 + 04 = 05、02 + 05 = 07 和 03 + 06 = 09,并且被合成为:

p { 
      color: #050709;
}

算数运算也能将数字颜色值一起运算,同样也是分段运算的。
例如:

p { 
      color: #010203 * 2;
}

计算公式为01 * 2 = 02、02 * 2 = 04 和 03 * 2 = 06,并且被合成为:

p { 
      color: #020406;
}

RGBA模式也可以运算,但R、G、B的最高值超过255将会显示255,最低值小于0将会显示0。
例如:

p {
      color: rgba(178, 34, 34, 0.54) + rgba(178, 34, 34, 0.54);
}

会等于:

p {
      color: rgba(255, 68, 68, 0.54);   // R超过255所以显示255,G和B的值都相加,A=0.54不变
}

但是需要注意的是:

p {
      color: rgba(178, 34, 34, 0.34) + rgba(131, 23, 24, 0.54);
}

会报错:Error: Alpha channels must be equal: rgba(178, 34, 34, 0.34) + rgba(131, 23, 24, 0.54)

**因为A值如果相同,是不参与运算之中,值保持不变。但如果A值不同则会报错。 减法同理。 **

而在RGB模式中,运算后将会转换成十六进制(Hex)颜色值。

字符运算

在Sass中可以通过加法符号“+”来对字符串进行连接。
例如:

$content: "Hello" + "" + "Sass!";
.box:before { 
    content: " #{$content} ";
}

编译出来的CSS:

.box:before { 
    content: " Hello Sass! ";
}

除了在变量中做字符连接运算之外,还可以直接通过“+”,把字符连接在一起:

div { 
    cursor: e + -resize;
}

编译出来的CSS:

div { 
    cursor: e-resize;
}

注意,如果有引号的字符串被添加了一个没有引号的字符串(也就是说,带引号的字符串在“+”加号的左侧),结果将会是一个有引号的字符串。同样的,如果一个没有引号的字符串被添加了一个有引号的字符串(没有引号的字符串在“+”加号的左侧),结果将会是一个没有引号的字符串
例如:

p:before { 
    content: "Foo " + Bar; font-family: sans- + "serif";
}

编译出来的CSS:

p:before {  
    content: "Foo Bar"; 
    font-family: sans-serif;
}

Sass控制命令

@if

@if指令是一个SassScript,它可以根据条件来处理样式块,如果条件为true的话返回一个样式块,反之false则返回另一个样式块。在Sass中除了@if之外,还可以配合@else if@else一起使用。

假设要控制一个元素隐藏或显示,我们就可以定义一个混合宏,通过@if...@else...来判断传进参数的值来控制display的值。

例如:

@mixin blockOrHidden($boolean:true) {
    @if $boolean {
        @debug "$boolean is #{$boolean}"; 
        display: block; 
    } @else { 
    @debug "$boolean is #{$boolean}"; 
        display: none; 
    }
}
.block { 
    @include blockOrHidden;
}
.hidden{ 
    @include blockOrHidden(false);
}

编译出来的CSS:

.block { 
    display: block;
}
.hidden { 
    display: none;
}

@for

在制作网格系统的时候,大家应该对.col1~.col12这样的印象比较深。在CSS中需要一个个去书写,而在Sass中,可以使用@for循环来完成。而在Sass的@for有两种方式:

编译出来的CSS:

.item-1 { width: 2em;}
.item-2 { width: 4em;}
.item-3 { width: 6em;}

再来个 to 关键字的例子:

@for $i from 1to

.item-#{$i} { width: 2em * $i; }

编译出来的CSS:

.item-1 { width: 2em;}
.item-2 { width: 4em;}

上一篇下一篇

猜你喜欢

热点阅读