SASS教学+SCSS:CSS 再进化,掌握语法攻略!

sass-banner.png

这几天摸索了SASS+SCSS 的写法,发现有许多的GitHub 专案,使用它进行开发。

自己进行几个专案后,编写速度确实有提升,于是整理出这篇SASS+SCSS 教学,从SASS+SCSS 介绍→ 安装+执行→ 语法SASS教学,进行文章编写。

不敢说可以从入门到进阶,但对SASS 主观念的掌握,应该是没问题的,本篇文章内容

  1. SASS+SCSS介绍
  2. 安装+执行
  3. 嵌套
  4. 引用父选择器&
  5. 变量
  6. 引入
  7. 混合
  8. 继承
  9. 操作符
  10. 结论

1. SASS+SCSS 介绍

SASS是一个成熟且稳定的CSS预处理器,除了把普通的CSS语法强化,它还使用了SassScript增加了许多功能,如:变量、嵌套、混合、导入等..功能,在一般专案的编写或是中大型的专案上,都可以编写的更加快速。

SASS 会编译(compiled)程式码,转成一般CSS 形式,让浏览器可以解读输出,把页面呈现出来。

主要包含两种写法:分别是旧版的SASS(缩排语法,副档名.sass,使用缩排来区分程式码块,与Haml类似)和新版的SCSS(块语法,副档名.scss,使用和CSS相同方式,用大括号分开)。

/** 一般 css 写法 **/
.nav{
    background: #ccc;
}
.nav li {
    display: inline-block;
}
.nav li a{
    display: block;
    padding: 15px;
    text-decoration: none;
    color: #000;
}
.nav li img{
    width: 100%;
}

SASS写法:采用「缩进语法(TAB)」的方式,去除了一般CSS的括号、分号等..加快编写流程,有一部分的人喜欢这样的编写方式而采用,如下:

/** sass寫法 **/
.nav
    background: #ccc
    li
        display: inline-block
        a
            display: block
            padding: 15px
            text-decoration: none
            color: #000
        img
            width: 100%

SCSS写法:采用「块语法(Block)」,一般从CSS转为SCSS开发比较无痛,保留了括号、分号等..元素,相对于上面的SASS是比较新的编写方式,学习成本比较低,是目前主流的方式,如下:

/** scss寫法 **/
.nav{
    background: #ccc;
    li {
        display: inline;
        a {
            display: block;
            padding: 15px;
            text-decoration: none;
            color: #000;
        }
        img {
            width: 100%;
        }
    }
}

看完上面的程式码,会发现SASS 可以协助解决编写CSS 常遇到的几个问题,如:「 重复编写」、「 后续维护」、「 漏写问题」等问题..,然后加快开发流程,如下:

  1. 父选择器,重复编写:?如要扩充页面样式,就会不断的加上.nav li .. 等父级class 名称,比较费工!
  2. 属性样式,重复编写:常会看到许多CSS 属性,是许多区块都需要用到,在SASS 没出来前,每个区块都需特别写一遍,现在直接引用即可。
  3. 后续维护:若哪天需要把.nav 这个class 名称更换,就需全部替换,比较麻烦。
  4. 漏写问题:SASS / SCSS 有条理的节省了许多代码编写,降低漏写的Bug。

2. 安装+执行

安装+执行SASS 的方式有满多种,有使用第三方应用程式的,也有直接安装在本机上的,这边会建议直接安装在本机上,比较一劳永逸,这边列出几种安装方式,如下:

SASS 安装

  1. 使用Node.js 安装 $ npm install -g sass
  2. 使用Ruby 安装 $ gem install compass
  3. 使用Brew 安装(Mac专用)$ brew install sass

指令执行完成,基本上就安装好了,若想测试是否安装成功,可以输入 $sass -v 看是否有显示SASS 版本号,若有的话代表安装完成

SASS 执行
首先在专案资料夹下,生成index.html 和两个资料夹css、sass ,然后在sass 下面新增一个style.scss,这支档是我们开发,主要编写样式的档案。

sass 范例档案

我们现在要试着把sass 资料夹里的style.scss ,编译成浏览器看的懂的.css 副档名型式。

所以下指令把style.scss 档案转译生成style.css,并放置在css 资料夹里,如下:
$ sass sass/style.scss:css/style.css
如果顺利的话,应该会看到「 css 」档案夹里,新增了两个档案,分别是「 style.css 」和「 style.css.map 」,这边比较要留意的是style.css(浏览器主要解读这只档)。

sass 转译成css

  1. 需留意「 当前路径」,这会影响到style.scss 档案编译生成style.css 的路径,若不对会报错
  2. 在index.html 里面,记得引入style.css 档案( style.scss 不需引入),才会有样式出现

若持续有样式需新增,每次一编写完style.scss 就得执行一次 $ sass sass/style. scss :css/style. css指令,才能在浏览器上看到变化,相信一定会很想撞墙

所以这时可以改下另一个指令(加上 --watch 参数,若原有的style.css / style.css.map 已存在,会自动覆盖,不存在的话会自动生成新的),如下:
$ sass --watch sass/style.scss:css/style.css

执行后,会发现sass 已经开始在监听style.scss ,若这只档案有修改,style.css 变会即时的进行编译,给浏览器做使用,

在开发过程中,一个专案可能不只有一个样式档,假如有多个档案需同时进行监听,这边提供几个方式给大家:

  1. 重复执行:看有几个档案需监听,就输入几次。
    $ sass --watch path/to/filename. scss :path/filename. css

  2. 一次执行:看有几个档案需监听,一次下指令。
    $ sass --watch path/filename1. scss :path/filename1. css path/filename2. scss :path/filename2. css path/filename3. scss :path/filename3. css

  3. 指定目录下全部监听:监听sass 目录下的sass/scss 档案到指定的css 目录下(下面指令为两个资料夹在同一层)
    $ sass --watch sass:css

  4. 当前目录下全数监听,并直接生成css 档案。
    $ sass --watch .

到了这一步,若顺利的话,相信你也学会,如何在编写sass/scss 档案时,指定的css 档案可以同步的进行编译,并让浏览器能够顺利的出现画面。

个人觉的sass 学习比较麻烦的就是安装+执行这个章节,后面就是语法部分,语法就相对简单明了了,原来就有css 开发经验的捧有们,相信也可以很快就入手的

接下来,我们开始前进到语法部分

3. 嵌套

SASS 提供CSS 语法扩展,如:嵌套功能( Nested Rules ),主要是解决CSS 编写过程中,父元素重复编写问题,可以缩短开发流程、方便后续维护、?样式模组化等.. 优点

这是容易入门SASS教学的第一步,直接上代码,我们使用SASS 编写样式,并对比编译后的CSS ,如下:

/** 编译前( sass 语法 ) **/
#main {
    width: 200px;
    height: 100px;
    background: #ddb92a;

    .greenbox{
        width: 100px;
        height: 50px;
        background: green;
        p, a {
            font-size: 20px;
        }
    }
}
/** 编译后( 转为CSS 语法输出) **/
#main {
    width: 200px;
    height: 100px;
    background: #ddb92a;
}
#main .greenbox{
    width: 100px;
    height: 50px;
    background: green;
}
#main .greenbox p, #main .greenbox a{
    font-size: 20px;
}

除此之外,常用的属性也可以进行CSS「 嵌套属性」,比如:font-familyfont-sizefont-weight,会发现 font 多次出现。

还有常见的 background 系列,比如:background-colorbackground-positionbackground-sizebackground-image,都可以用嵌套功能,来节省开发时间,这边上代码,如下:

/** 编译前( sass语法) **/
.main {
    font: {
        family: Helvetica, sans-serif;
        size: 15em;
        weight: bold;
    }
}
/** 编译后( 转为CSS 语法输出) **/
.main {
    font-family: Helvetica, sans-serif;
    font-size: 15em;
    font-weight: bold;
}

到目前,对嵌套功能应该有初步认识了,若之前有看过别人写的SASS / SCSS 档,应该会有种似曾相似的感觉吧

理解了它,接下来我们继续看SASS 还有什么特别的地方,可以让我们学习的..

4. 引用父选择器&

如果想在嵌套状态下,取得外层的父选择器,那可以使用「 & 」,它会直接抓父选择器给你用。

常会把它用在,如CSS 元件状态: :hover:focus:hover:link:visited 等..,或是 :before:after ,这边上个代码,如下:

/** 编译前( sass语法) **/
#main {
    display: block;
    a {
        color: #d0b95b;
        &:hover, &:active, &:focus {
            color: #a08106;
            outline: none;
            text-decoration: none !important;
        }
    }
}
/** 编译后( 转为CSS 语法输出) **/
#main {
    display: block;
}
#main a {
    color: #d0b95b;
}
#main a:hover, #main a:active, #main a:focus {
    color: #a08106;
    outline: none;
    text-decoration: none !important;
}

还有另一种用法,也常常看到,如下:

/** 编译前( sass语法) **/
#main{
    &.color- 2 {
        background: red;
        &:before {
            border: 1px solid #ccc;
        }
    }
    &.color- 3 {
        background: yellow;
        &:before {
            border: 1px solid blue;
        }
    }
}
/** 编译后( 转为CSS 语法输出) **/
#main.color-2 {
    background: red; 
}
#main.color-2:before {
    border: 1px solid #ccc;
}
#main.color-3 {
    background: yellow; 
}
#main.color-3:before {
    border: 1px solid blue; 
}

能抓到父选择器,是不是开发起来也方便多了呢?

一开始看到别人编写的SASS 时,觉得「 & 」的写法满酷的,后来才懂.. 原来是这样运作呀

5. 变量

在我们实际编写CSS 的过程中,常会遇到多次相同的颜色、字型、字体大小等.. 重复出现。

重复出现是好事,因为只要复制+贴上就好了..但假如遇到哪天设计师/客户,需要修改就..(因为全都需要更改)

所以SASS 可以协助我们解决这问题,就如同JS 变量逻辑一样,只需改最源头的变量即可,其他所有引用该变量的地方,值都会自动更改。

SASS 中使用 $ 进行变量声明,支持7 种主要数据类型:

  • 数字(如:1, 1. 5, 20px
  • 字符串,带引号和不带引号(如:"foo", 'foo', foo
  • 颜色(如:red, #28b0b4, rgba ( 0 , 0 , 0 , 0.5 )
  • 布尔值(如: true, false
  • 空值(如: null
  • 值列表(list),用空格或逗号分开(如:2em 1em 0 1emHelvetica, Arial
  • maps:从一个值映射到另一个(如:( key1: value1, key2: value2 )

这边来对比一下,使用SASS 开发的编译前( SASS 语法) & 编译后( 转为CSS 语法输出)的程式码,如下:

/** 编译前( sass 语法) **/
$bnr-font: Helvetica, sans-serif;
$bnr-color: #494947;
.banner1 p {
    font-family: $bnr-font;
    color: $bnr-color;
    padding: 10px 15px;
    letter-spacing: 0.2 em;
}
.banner2 p {
    font-family: $bnr-font;
    color: $bnr-color;
    margin: 15px;
}
/** 编译后( 转为CSS 语法输出) **/
.banner1 p {
    font-family: Helvetica, sans-serif;
    color: #494947;
    padding: 10px 15px;
    letter-spacing: 0.2 em;
}
.banner2 p {
    font-family: Helvetica, sans-serif;
    color: #494947;
    margin: 15px;
}

如此一来,当哪天收到需要更改某通用按钮颜色、通用字体字型.. ,就可以直接更改变量即可,是不是很方便

6. 引入

SASS 扩展了CSS 的 @import 功能,允许在文件内导入其他的SASS 或SCSS 子文件。

在文件进行编译后,被导入的SASS 或SCSS 子文件,会全部合并到同一个CSS 文件,然后呈现出来。

常见的 .sass.scss 导入

这边展示一下基本用法,我们把 _reset. scss 导入到 main. scss 中,直接上代码:

/** 编译前( sass 语法) **/
/** _reset.scss **/
html, body, ul, ol, a {
    margin:   0 ;
    padding: 0 ;
}
/** main.scss **/
@import 'reset' ;
body {
    background: #a08106;
    font-size: 16px;
}
/** 编译后( 转为CSS 语法输出) **/
html, body, ul, ol, a {
    margin:   0 ;
    padding: 0 ;
}
body {
    background: #a08106;
    font-size: 16px;
}

小提醒:若有多个文件需汇入,可同时使用多个 @import 引用文件,如下图

bootstrap.scss 多个文件引入

监听父文件即可
编写代码过程中,可以把不同样式区块的SASS 或SCSS 代码,拆开成不同独立的文件,然后使用 @import 把各片段文件,统整汇入到同一支 .sass.scss 文件中,并监听这一支文件即可

在文件进行监听时,所有 @import 进来的 .sass.scss 子文件,也同时被监听,所以当子文件有修改,父文件编译出的 .css 也会自动更新。

使用下划线,SASS 编译自动忽略

若有片段文件不需SASS 编译出新的CSS 文件,可在文件开头添加一个下划线,在编译过程中,系统就会忽略它,而只对开头无下划线的文件,进行新的CSS 文件生成。

上述的范例说明

看一下另一个范例,下面是bootstrap 的目录文件:


左图:目录结构 。右图: bootstrap.scss 文件

1.把多个scss 文件,使用 @import添加到 bootstrap.scss 中。
2.之后只需监听--watch bootstrap.scss 这一支文件即可,假如内部@import 的文件有变更,都会在bootstrap.css 自动更新。
3.bootstrap.scss 文件内的 @import 档案,不需要加下划线。
开头有下划线的文件,在执行sass 指令时,不会生成新的css 文件,系统会自动忽略。
4.@import scss 片段文件,不用加上副档名也可以,系统会自动寻找同名的副档名 .scss.sass 文件,并依序导入。

一般CSS @import 功能
@import 默认情况,会预设导入同名的 .sass.scss 文件,但在以下情况下,仅当成一般的CSS @import 语句,不会导入任何的SASS 文件,如下:

  • 如果文件的副档名是 .css@import "foo.css" ;
  • 文件名以 http :// 开始:@import "http://foo.com/bar" ;
  • 文件名是 url ()@import url ( foo ) ;
  • @import 中包含媒体查询(media queries)

7. 混合

若是有重复的代码,会不断使用到,就可用混合指令(Mixin Directives),直接把样式封装成一个类名称,就可以重复调用,如下:

/** 编译前( sass 语法) **/
/** 定义mixin 指令**/
@mixin font-main {
    font: {
      family: Arial;
      size: 16px;
      weight: 100 ;
    }
    color: #000;
}
/** 引用mixin **/
.box p {
    @include font-main;
}
/** 编译后( 转为CSS 语法输出) **/
.box p {
  font-family: Arial;
  font-size: 16px;
  font-weight: 100 ;
  color: #000;
}
  • 使用 @mixin 定义一个「 混合」
  • 使用 @include 引用一个「 混合」
  • 可同时引用多个「 混合」

使用参数功能

使用「 混合」功能,有设置参数功能( 可设定默认值),让整体功能变更弹性,有点像函数的传入参数,如下:

/** 编译前( sass语法) **/
/** 定义mixin 指令**/
@mixin border- set ( $color, $width, $style: solid ) { 
    border: {
        color: $color;
        width: $width;
        style: $style;
    }
}
@mixin background- set ( $color, $image, $repeat ) { 
    background: {
        color: $color;
        image: url ( $image ) ;
        repeat: $repeat;
    }
}
/** 引用mixin **/
.box div {
    @include border- set ( red, 2px ) ;
    @include background- set ( green, "../img_tree.png" , 'no-repeat' ) ;
    letter-spacing: 0.5 em;
}
/** 编译后( 转为CSS 语法输出) **/
.box div {
  border-color: red;
  border-width: 2px;
  border-style: solid;
  background-color: green;
  background-image: url ( "../img_tree.png" ) ;
  background-repeat: "no-repeat" ;
  letter-spacing: 0.5 em;
}

8. 继承

「 继承」@extend 是一个满实用的功能,若想让多个class 使用相同样式,就可使用 @extend 直接继承过来,减少重复编写的时间,如下:

/** 编译前( sass语法) **/
%msg-style {
    display: block;
    flex-wrap: wrap;
    background: #d9d9d8;
    color: #000;
}
.msg {
    @extend %msg-style;
}
.msg-success {
    @extend %msg-style;
    background: #34fc6d;
}
.msg-error {
    @extend %msg-style;
    background: #fc253e;
}
/** 编译后( 转为CSS 语法输出) **/
.msg, .msg-success, .msg-error {
  display: block;
  flex-wrap: wrap;
  background: #d9d9d8;
  color: #000;
}
.msg-success {
  background: #34fc6d;
}
.msg-error {
  background: #fc253e;
}
  • 使用站位选择器 % ,定义一个样式,被定义的类,它将不会被编译出来。
  • 若没有标注 % 的类,也可以使用 @extend 引入,但定义的类会被编译出来。
  • 有使用 @extend 的类,会被系统编译整合,使用共用样式。

多重扩展,可引入多个选择器

同一个选择器,可以使用 @extend扩展多个选择器,这代表它继承了扩展选择器的样式,如下:

/** 编译前( sass语法) **/
.error {
    background-color: #fa945c;
}
.notice {
    font-size: 16px;
    font-family: sans-serif;
    font-color: #000;
}
.seriousError {
    @extend .error;
    @extend .notice;
    background-color: #ff1b1b;
}
/** 编译后( 转为CSS 语法输出) **/
.error, .seriousError {
  background-color: #fa945c;
}
.notice, .seriousError {
  font-size: 16px;
  font-family: sans-serif;
  font-color: #000;
}
.seriousError {
  background-color: #ff1b1b;
}

上面几个状况,应该是比较常见的 @extend功能,应该满足够使用了,若想了解更多,可以直接参考SASS官方

9. 操作符

SassScript 支持对数字的运算,如:(加法 +、减法-、乘法 *、除法/、取模 % 等..),来看一下代码,如下:

/** 编译前( sass 语法) **/
div a {
    $width: 500px;
    width: $width/ 2 ;             //使用变量,和/
    font: 16px/10px;             //原生CSS,不作为除法
    height: ( 250px/ 2 ) ;           //使用了(),和/
    margin-left: 10px + 8px/2px; //使用了+, ?和/
}
/** 编译后( 转为CSS 语法输出) **/
div a {
  width: 250px;
  font: 16px/10px;
  height: 125px;
  margin-left: 14px; 
}

简单来说,就是增加了运算功能,有需要也可进行使用。

这边也有另一个范例,如下:

/** 编译前( sass语法) **/
.container { width: 100 %; }
article [ role= "main" ] { 
  float: left;
  width: 700px / 960px * 100 %; 
}
aside [ role= "complementary" ] { 
  float: right;
  width: 400px / 960px * 100 %; 
}
/** 编译后( 转为CSS 语法输出) **/
.container {
  width: 100 %;
}
article [ role= "main" ] { 
  float: left;
  width: 72.9166666667 %;
}
aside [ role= "complementary" ] { 
  float: right;
  width: 41.6666666667 %;
}

10. 结论

如果能看到这边,首先给自己掌声!相信对SASS教学,也有程度的认识了!

接着,可以找个小案子,来自己练习,你会发现,CSS结合了JS特性,开发起来会变得更加快速(省了很多代码)

SASS 在入门安装+下指令时,会有些要适应,但这边搞定后,会发现后面语法观念,其实很容易上手,优化了传统CSS 开发上的许多不变。

希望这篇SASS教学文,有帮助到需要的捧有们,我们下篇文章见

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,312评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,578评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,337评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,134评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,161评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,303评论 1 280
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,761评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,421评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,609评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,450评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,504评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,194评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,760评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,836评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,066评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,612评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,178评论 2 341