SCSS 日常用法

本文是以自己的理解起的结构,要看详细的帮助文档,参阅这里:https://sass-lang.com/documentation/
本文在线例子:https://kylebing.cn/test/scss/

你需要了解的

lesssass 是两种 css 预编译语言,就是说通过 less 或者 scss 写的代码最终都会被编译成 css 再使用。其目的是为了更快、更结构的编写 css 文件,都能使用 变量、运算符、判断、方法等等。

scsssass 的区别(这里先不讲 less ):

  • 先有的 sass 后有的 scss
  • scss 需要大括号{}和分号;
  • sass 什么都不用直接裸奔,通过缩进来区分代码等级,像 yaml 语言

初学者最好用 scss 而非 sasssass 在你追求代码简洁的时候用,来看个对比

scss_sass.png

使用 scss 之前你需要准备的

最好用 JetBrains 系列软件(webStorm phpStorm IDEA等)开发,里面添加对于 scssFile Watcher 即可,在每次scss 文件改变的时候,程序都会自动编译 scsscss

或者在 vue 单文件项目中直接在 <style lang='scss'></style> 中使用 scss
scss 本身就支持拆分成多文件,再通过 mixin 整合起来。

关于如何添加 scss 支持,看这里: https://blog.csdn.net/KimBing/article/details/100532939

看个小例子

写一个 .btn 类并支持 :hover :active 样式

css

.btn {
/* btn 初始样式 */
}
.btn:hover{
/* :hover 样式 */
}
.btn:active{
/* :active 样式 */
}

scss

.btn{
// btn 初始样式
    &:hover{
        // hover 样式
    }
    &:active{
        // active 样式
    }
}

scss, sass, less& 都代指父类
上面这个例子中的 & 代指 .btn
可以看出 scss 的结构要比 css 清晰,并且写的也要更少。
下面的 scss 在使用中就会生成上面的 css
而这还只是皮毛,保证你用过 scss 之后就不会再用 css 写样式了。

一、变量

变量是以 $ 开头的,可以是颜色,长度,数值,等等。

像 js 的变量一样,scss 的变量也是有作用域的,也就是说内部声明的变量是无法在外面使用的,如果想让内部的变量在外部可访问,需要在变量值后面添加 !global 声明。

(还可以通过添加 !default 给变量设置默认值,这个在写一个样式库的时候比较实用,避免别人在没有给变量赋值之前使用)

$变量名: 变量值
// Colors
$red:       #CD594B !global;
$yellow:    #F8CE5E;
$green:     #4B9E65;
$yellow:    #5A8DEE;

// Unites
$btn-padding: 4px;
$btn-lineheight: 26px;

实际使用中:

scss

.btn-success {
    background-color: $green;
    line-height: $btn-lineheight;
    color: #fff;
}

生成 css

.btn-success {
    background-color: #4B9E65;
    line-height: 26px;
    color: #fff;
}

嵌入字符串

将变量直接嵌入字符串,需要用 #{ 变量 } (类似 ES6 中模板字符串中的 ${ 变量 }

其实 #{} 中是可以插入任意东西的,这里只用到了插入变量,还可以插入方法等等,高级用法。

scss

$bg-path: "./img"

.card{
    background: url("#{$bg-path}/card-bg.png" center center);
}

css

.card{
    background: url("./img/card-bg.png" center center);
}

二、导入文件 @import

通过 @import 可以把多个文件结合到一起
有了这个功能,就可以通过功能拆分 scss 文件,使其更结构化,比如,可以分成:变量类,按钮类,列表类,字体类,排版类等等。

拆分成多个文件的时候,以 _开头命名的文件,不会被像 phpStorm 中的 file watcher 自动预编译成css文件,less 没有这效果,在这一点上 scss 很不错。

比如,我一个项目的 css 结构是这样的:以 _ 开头的都是整个项目的 css 的结构部分,像底部按键、表单、按钮、通用方法等。最后都整合在 pay.scss

css/
├── _agent.scss
├── _form.scss
├── _mixin.scss
├── _navbar.scss
├── _normalize.scss
├── _regist.scss
├── _reset.scss
├── _tabbar.scss
├── _trade.scss
├── _trand-time.scss
├── _trand-tradition.scss
├── _usercenter.scss
├── _utility.scss
├── _variables.scss
├── _wallet.scss
├── pay.css
├── pay.css.map
└── pay.scss

_variables.scss

$bg-btn: #ddd;
$color-btn: #444;

btn.scss

@import "_variables";

.btn{
    display: inline-block;
    padding: 3px 6px;
    background-color: $bg-btn; 
    color: $color-btn;
}

生成 css

.btn{
    display: inline-block;
    padding: 3px 6px;
    background-color: #ddd; 
    color: #444;
}

三、相互嵌入,扩展

1. @mixin @include

这个是最常用的,通过 @mixin 定义一个类或方法,在其它地方通过 @include 引用这个方法或类。

如果是方法,还可以定义默认值,也就是说可以某些时候,可以传部分参数。

直接看例子
scss

// @mixin 如果没有调用,不会被渲染

@mixin rounded($conor: 5px){ // 定义 mixin 并设置默认值 5px
  -webkit-border-radius: $conor;
  -moz-border-radius: $conor;
  border-radius: $conor;
}

.btn-rounded{
  @include rounded(); // 这里引用上面的 mixin,默认值 5px
}

.btn-big-rounded{
  @include rounded(10px); // 这里引用上面的 mixin,并设置值 10px
}

生成 css

.btn-rounded{
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
}
.btn-big-rounded{
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
}
扩展

mixin 想输入多个参数的时候 参数可以这样写

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

2. @extend 继承

有些时候,需要写的某个类里,包含另一个类的所有声明。
如: 警告按钮,包含所有警告颜色类的内容。

scss

.danger{
  background-color: #FF3B30;
}
.round{
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
.btn{
  display: inline-block;
  padding: 3px 6px;
}

.btn-danger{
  @extend .danger, .round, .btn;
}

css

.danger, .btn-danger {
  background-color: #FF3B30;
}
.round, .btn-danger {
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
.btn, .btn-danger {
  display: inline-block;
  padding: 3px 6px;
}

@extend 注意事项:
不能继承 @extend .danger.text 这种连续组合的类,应该写为 @extend .danger, .text

四、@if @else, @each, @for 的使用

1. @if @else

呃,没什么说的,就是 if else 《官方文档:if else》

SCSS

@if $name == normal {   // 判断 $name 是否为 'normal'
  color: #333;          // 如果是,内部文字颜色为 #333
  border: 1px solid darken($color, 20%);
} @else {
  color: white;
  border: 1px solid darken($color, 5%);
}

2. @each

js 中的 Array.each(item=>{}) 一样,遍历变量所存在的所有数据。
比如下面的例子,会遍历 $btn-styles 中的三个字符串

$btn-styles: "normal", "primary", "danger";

@each $type in $btn-styles {
  .btn-#{$type}{
    background-color: white;
  }
}

CSS

.btn-normal  { background-color: white; }
.btn-primary { background-color: white; }
.btn-danger  { background-color: white; }

3. @for

for 用于基于数字的遍历,有两种使用方法

  • for $i from 1 to 10 从1到10,不包含10
  • for $i from 1 through 10 从1到10,包含10

举个最常用的例子,生成 pb-1 pb-2... pb-8

SCSS

@for $gap from 1 through 8 {
  .pb-#{$gap} {
    padding-bottom: 10px * $gap;
  }
}

CSS

.pb-1 { padding-bottom: 10px; }
.pb-2 { padding-bottom: 20px; }
.pb-3 { padding-bottom: 30px; }
.pb-4 { padding-bottom: 40px; }
.pb-5 { padding-bottom: 50px; }
.pb-6 { padding-bottom: 60px; }
.pb-7 { padding-bottom: 70px; }
.pb-8 { padding-bottom: 80px; }

五、常用方法

详见:https://sass-lang.com/documen...

不知道别人,反正我最常用的就是颜色方法了。列举常用的颜色方法

lighten         (颜色, 百分比)   // 调亮
darken          (颜色, 百分比)   // 调暗
saturate        (颜色, 百分比)   // 调高饱和度
desaturate      (颜色, 百分比)   // 降低饱和度
transparentize  (颜色, 0.0-1.0) // 透明度,注意这里接收的不是百分比,是 0.0-1.0 的小数值

color-function.png

SCSS

$green: #4B9E65;

.green-original    { background-color: $green;                      }
.green-lighten     { background-color: lighten($green,20%);         }
.green-darken      { background-color: darken($green,20%);          }
.green-saturate    { background-color: saturate($green,20%);        }
.green-desaturate  { background-color: desaturate($green,20%);      }
.green-transparent { background-color: transparentize($green, 0.2); }

CSS

.green-original    { background-color: #4B9E65;                 }
.green-lighten     { background-color: #88c79c;                 }
.green-darken      { background-color: #2a5939;                 }
.green-saturate    { background-color: #34b55c;                 }
.green-desaturate  { background-color: #62876e;                 }
.green-transparent { background-color: rgba(75, 158, 101, 0.8); }

六、其它

1. 方法 @function

方法以 @function 开头,以 @return 结尾,也就是说,方法的定义,必须要有返回值

详见:https://sass-lang.com/documentation/at-rules/function

2. 调试方法 @error @warn @debug

jsconsole.log console.error一样,用于输出提示信息

  • @debug : 普通输出
  • @warn : 警告输出
  • @error : 错误输出

3. 语法概览

通用

  • 变量声明, $var: value
  • 控制声明,@if @each
  • @error@warn@debug

CSS

  • 样式,h1 { ... }
  • 样式@ @media @font-face
  • @at-root

顶级

  • 导入 @import
  • 混合 @mixin
  • 方法定义 @function

表达式

  • 数字 12 100px
  • 字符串 Helvetina Neue bold
  • 颜色 #ffffff blue
  • 布尔值 true false
  • null
  • 属性值组 border: 1px solid #ccc
  • Maps ("background": red, "foreground": pink)

运算符

  • == !=
  • + - * / %
  • < <= >=
  • and or not
  • + - / 连接字符
  • ( )

其它

  • 变量 $var
  • 方法调用 nth($list,1) var(--main-bg-color)
  • 特殊方法 calc(1px + 100%) url(http://myapp.com/assets/logo.png)
  • 父选择器 &
  • !important

4. 注释

/*  多行注释
        可以多行
        在非压缩模式下,这种注释会被输出到 css 中
*/

// 单行注释
// 这种注释不会输出到 css 中

5. 特殊方法

CSS 本身自带一些方法,大多数方法都能与 SCSS 方法和平共存,但有些会产生冲突,如url()

如果 url() 传入的参数是有效的带引号的 url,sass 不会处理它,但还可以往其中插入变量,如果不是有效的带引号的 url,带有方法或变量的,sass 就把它当成正常的方式识别。如:

$bg-path: "./pics"

.card-bg{
    background: url("#{$bg-path}/card-bg.png") center center;
}

// 或
.card-bg{
    background: url($bg-path+"/card-bg.png") center center;
}

都会输出为

.card-bg{
    background: url("./pics/card-bg.png") center center;
}

七、写个例子 .btn

学会上面的所有内容,我们来写一个例子。
比如,你需要写一个按钮库 .btn-success, .btn-danger, .btn-normal, .btn-warning,如果单个定义的话,会很麻烦,现在有了 SCSS,就可以很方便的实现了。

完成后,效果是这样的:

scss-btns.gif

SCSS

// 定义基础颜色
// 一般在项目中会写在 _variables.scss 文件中
$green          : #4CD964;
$syan           : #5AC8FA;
$blue           : #007AFF;
$purple         : #5856D6;
$magenta        : #FF2D70;
$red            : #FF3B30;
$orange         : #FF9500;
$yellow         : #FFCC00;
$gray           : #8E8E93;

// 定义需要实现的按钮名和颜色,键值对
$btn-types: (
        "normal": white,
        "primary": $blue,
        "success": $green,
        "danger": $red,
        "warning": $orange,
        "second": $gray,
);

/****************************
把一些常用的需要多平台适配的(-webkit-)做成 mixin 方便调用,写的时候代码也简洁
像这种还有 box-shadow transform transition animation 等等
一般在项目中都单独定义成一个文件 _utility.scss,直接引用使用,也方便。
这里只是提一下,可能会对你有所启发
*/

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

/****************************
这里定义最常用的通用方法,比如 .link .btn .block .hidden
一般保存为 _normalize.scss 文件
*/

.unselectable{
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

// .btn 里只放 button 最基础的行为和动作
// 下面循环中的 .btn-xxxx 只处理按钮的颜色变化,这样明了
.btn {
  padding: 6px 10px;
  text-align: center;
  font-size: 1rem;
  cursor: pointer;
  margin-right: 5px;
  @extend .unselectable; // 引用其它类的内容作为自己的内容,也就是扩展
  @include border-radius(5px); // 调用 mixin
  &:active{
    transform: translateY(2px);
  }
}

@each $name, $color in $btn-types {
  .btn-#{$name} {
    @if $name == normal {   // 判断 button 名 是否为 'normal'
      color: #333;          // 如果是,内部文字颜色为 #333
      border: 1px solid darken($color, 20%);
    } @else {
      color: white;
      border: 1px solid darken($color, 5%);
    }
    background-color: $color;
    &:hover{
      background-color: lighten($color, 5%);
    }
    &:active{
      border-color: transparent;
      background-color: darken($color, 15%); // 点击的时候按钮背景颜色深 15%
    }
  }
}

上面的 scss 输出为下面的内容,有没有很强大

/* buttons */
.unselectable, .btn {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none; }

.btn {
  padding: 6px 10px;
  text-align: center;
  font-size: 1rem;
  cursor: pointer;
  margin-right: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px; }
  .btn:active {
    transform: translateY(2px); }

.btn-normal {
  color: #333;
  border: 1px solid #cccccc;
  background-color: white; }
  .btn-normal:hover {
    background-color: white; }
  .btn-normal:active {
    border-color: transparent;
    background-color: #d9d9d9; }

.btn-primary {
  color: white;
  border: 1px solid #006ee6;
  background-color: #007AFF; }
  .btn-primary:hover {
    background-color: #1a87ff; }
  .btn-primary:active {
    border-color: transparent;
    background-color: #0055b3; }

.btn-success {
  color: white;
  border: 1px solid #37d552;
  background-color: #4CD964; }
  .btn-success:hover {
    background-color: #61dd76; }
  .btn-success:active {
    border-color: transparent;
    background-color: #26b33e; }

.btn-danger {
  color: white;
  border: 1px solid #ff2317;
  background-color: #FF3B30; }
  .btn-danger:hover {
    background-color: #ff534a; }
  .btn-danger:active {
    border-color: transparent;
    background-color: #e30c00; }

.btn-warning {
  color: white;
  border: 1px solid #e68600;
  background-color: #FF9500; }
  .btn-warning:hover {
    background-color: #ffa01a; }
  .btn-warning:active {
    border-color: transparent;
    background-color: #b36800; }

.btn-second {
  color: white;
  border: 1px solid #818187;
  background-color: #8E8E93; }
  .btn-second:hover {
    background-color: #9b9b9f; }
  .btn-second:active {
    border-color: transparent;
    background-color: #68686d; }
其实这里可以使用渐变优化按钮颜色的,你可以考虑如何实现哟,加油。
给个提示: 基础颜色不需要变,只需要用颜色方法对基础颜色进行微调即可产出渐变需要的颜色

八、学习 scss 最好的例子

就是去看 bootstrap v4 的样式源码,bootstrap v4 就是用 scss 写的
下载 bootstrap 的 scss 源码,看里面怎么写的,进步很快的。

如果想学 less 可以看这篇 less基础用法(SegmentFault | CSDN), bootstrap v3 就是用 less 写的。

KyleBing
659 声望18 粉丝

前端,喜欢 Javascript scss,喜欢做一些实用的小工具