[TOC]

SCSS 语法说明

SASS是世界上最成熟、最稳定、最强大的专业级CSS扩展语言!SASS提供的变量、嵌套、混合、继承等特性,让CSS的书写更加有趣与程式化。

而SCSS是Sass3版本当中引入的新语法特性,完全兼容CSS3的同时继承了Sass强大的动态功能。

下面scss语法可在线测试:https://www.sassmeister.com/

1. 变量$

变量用来存储需要在CSS中复用的信息,例如颜色和字体。SASS通过$符号去声明一个变量。

$nav-color: #F90;
$highlight-border: 1px solid $nav-color;
nav {
  $width: 100px;
  width: $width;
  color: $nav-color;
  border: $highlight-border;
}

//编译后
nav {
  width: 100px;
  color: #F90;
  border: 1px solid #F90;
}

$nav-color这个变量定义在了规则块外边,所以在这个样式表中都可以像 nav规则块那样引用它。

在这段代码中,$nav-color这个变量定义在了规则块外边,所以在这个样式表中都可以像 nav规则块那样引用它。$width这个变量定义在了nav{ }规则块内,所以它只能在nav规则块 内使用。这意味着是你可以在样式表的其他地方定义和使用$width变量,不会对这里造成影响。

sass的变量名可以与css中的属性名和选择器名称相同,包括中划线和下划线。这完全取决于个人的喜好。

1.1 默认变量!default

一般情况下,反复声明一个变量,只有最后一处声明有效且会覆盖前面的值,如:

$link-color: blue;
div {  color: $link-color; }
$link-color: red;
a { color: $link-color; }

/* 编译后 */
div { color: blue;}
a { color: red; }

假如你写了一个可被他人通过@import导入的sass库文件,你可能希望导入者可以定制修改sass库文件中的某些值。使用sass!default标签可以实现这个目的。

!default含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。

$fancybox-width: 400px !default;
.fancybox {
width: $fancybox-width;
}

在上例中,如果用户在导入你的sass局部文件之前声明了一个$fancybox-width变量,那么你的局部文件中对$fancybox-width赋值400px的操作就无效。如果用户没有做这样的声明,则$fancybox-width将默认为400px

2. 嵌套CSS 规则

SASS允许开发人员以嵌套的方式使用CSS,

#content {
  article {
    h1 { color: #333 }
    p { margin-bottom: 1.4em }
  }
  aside { background-color: #EEE }
}

/* 编译后 */
#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #EEE }
/* --------------------------------------------------- */
article {
  ~ article { border-top: 1px dashed #ccc }
  > section { background: #eee }
  dl > {
    dt { color: #333 }
    dd { color: #555 }
  }
  nav + & { margin-top: 0 }
}

/* 编译后 */
article ~ article { border-top: 1px dashed #ccc }
article > footer { background: #eee }
article dl > dt { color: #333 }
article dl > dd { color: #555 }
nav + article { margin-top: 0 }

大多数情况下这种简单的嵌套都没问题,但是有些场景下不行,比如你想要在嵌套的选择器 里边立刻应用一个类似于:hover的伪类。为了解决这种以及其他情况,sass提供了一个特殊结 构&

2.1 父选择器标识符&

scss只用&符号在嵌套中来表示父选择器:

article a {
  color: blue;
  &:hover { color: red }
}

/* 编译后 */
article a { color: blue }
article a:hover { color: red }

同时父选择器标识符还有另外一种用法,你可以在父选择器之前添加选择器:

#content aside {
  color: red;
  // 在<body>标签上添加一个ie的类名
  body.ie & { color: green }
}

/*编译后*/
#content aside {color: red};
body.ie #content aside { color: green }

2.2 嵌套属性

CSS许多属性都位于相同的命名空间(例如border-style``border-width``border-color以及border-*等都位于border命名空间下),Scss当中只需要编写命名空间一次,后续嵌套的子属性都将会位于该命名空间之下

nav {
  border: {
  style: solid;
  width: 1px;
  color: #ccc;
  }
}

/*编译后*/
nav {
  border-style: solid;
  border-width: 1px;
  border-color: #ccc;
}

/* --------------------------------------------------- */

.demo {
  font: 20px/24px fantasy {
    weight: bold;
  }
}
/*编译后*/
.demo {
  font: 20px/24px fantasy;
  font-weight: bold;
}

3. 导入scss文件@import

css有@import特性,它允许一个css文件中导入其他css文件,然而,只有执行到@import时,浏览器才会去下载其他css文件,这导致页面加载起来变慢。

scss也有@import规则,不同的是,scss会在生成css文件时就把相关文件导入进来,所有相关样式归纳到同一个css文件,所有被导入文件中定义的变量和混合器均可在导入文件中使用。

使用sass@import规则并不需要指明被导入文件的全名。你可以省略.sass.scss文件后缀。在不修改样式表的前提下,你完全可以随意修改你或别人写的被导入的sass样式文件语法,在sassscss语法之间随意切换。

3.1 引入局部文件

当通过@import把scss样式分散到多个文件时,有的scss文件并不需要生成独立的css文件,这样的文件称为局部文件。scss有一个特殊的约定来命名这些文件。

scss局部文件的文件名以下划线开头(_variable.scss),这样,scss就不会在编译时单独编译这个文件输出css,而只把这个文件用作导入。

// _reset.scss
html, body, ul, ol {
  margin:  0;
  padding: 0;
}

// base.scss
@import 'reset';
body {
  font: 100% Helvetica, sans-serif;
  background-color: #efefef;
}

/*编译后*/
html, body, ul, ol {
  margin: 0;
  padding: 0; }

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

3.2 嵌套导入

跟原生的css不同,sass允许@import命令写在css规则内。这种导入方式下,生成对应的css文件时,局部文件会被直接插入到css规则内导入它的地方。举例说明,有一个名为_blue-theme.scss的局部文件,内容如下:

// _blue-theme.scss
aside {
  background: blue;
  color: white;
}

// base.scss
.blue-theme {@import "blue-theme"}

//生成的结果跟你直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样。
.blue-theme {
  aside {
    background: blue;
    color: #fff;
  }
}

3.3 原生CSS的导入

由于sass兼容原生的css,所以它也支持原生的CSS@import

下列三种情况下会生成原生的CSS@import,尽管这会造成浏览器解析css时的额外下载:

  • 被导入文件的名字以.css结尾;
  • 被导入文件的名字是一个URL地址(比如http://www.sass.hk/css/css.css),由此可用谷歌字体API提供的相应服务;
  • 被导入文件的名字是CSS的url()值。

不能用scss的@import直接导入一个原始的css文件,因为scss会认为你想用css原生的@import。但是,由于scss语法完全兼容css,所以你可以直接把原始的css文件改名为.scss后缀,就可直接导入了。

4. 静默注释

css注释格式:/* ... */,这个注释会显示到源码中。

scss提供了一种静默注释,其注释内容不会出现在生成的css文件中,格式: //

body {
  color: #333; // 这种注释内容不会出现在生成的css文件中
  padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}

scss在默写情况下,/* ... */注释也会在生成的css文件中抹去:当注释出现在原生css不允许的地方,如在css属性或选择器中,sass将不知如何将其生成到对应css文件中的相应位置,于是这些注释被抹掉:

body {
  color /* 这块注释内容不会出现在生成的css中 */: #333;
  padding: 1; /* 这块注释内容也不会出现在生成的css中 */ 0;
}

5. 混合@mixin、@include

混合(Mixin)用来分组那些需要在页面中复用的CSS声明,开发人员可以通过向Mixin传递变量参数来让代码更加灵活,该特性在添加浏览器兼容性前缀的时候非常有用,SASS目前使用@mixin name指令来进行混合操作。

// 定义一个混合
@mixin rounded-corners { border-radius: 5px; }
notice {
  border: 2px solid #00aa00;
  // 使用混合
  @include rounded-corners;
}

/*编译后*/
notice {
  border: 2px solid #00aa00;
  border-radius: 5px;}

5.1 混合器中有css规则

@mixin no-bullets {
  list-style: none;
  li {
    margin-left: 0px;
  }
}
ul.plain {
  color: #444;
  @include no-bullets;
}
/*编译后*/
ul.plain {
  color: #444;
  list-style: none;
}
ul.plain li {
  margin-left: 0px;
}

5.2 混合器传参

@mixin link-colors($normal, $hover, $visited) {
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}
a {
  @include link-colors(blue, red, green);
}
// 通过语法$name: value的形式指定每个参数的值。
ul {
    @include link-colors(
      $normal: blue,
      $visited: green,
      $hover: red
  );
}

/*编译后*/
a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }
ul { color: blue; }
ul:hover { color: red; }
ul:visited { color: green; }

5.3 默认参数值

参数默认值使用$name: default-value的声明形式,默认值可以是任何有效的css属性值,甚至是其他参数的引用,如下代码:

@mixin link-colors(
    $normal,
    $hover: $normal,
    $visited: $normal
  )
{
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

如果像下边这样调用:@include link-colors(red) $hover$visited也会被自动赋值为red

5.4 何时使用混合器

判断一组属性是否应该组合成一个混合器,一条经验法则就是你能否为这个混合器想出一个好的名字。比如rounded-corners``fancy-font或者no-bullets,那么往往能够构造一个合适的混合器。如果你找不到,这时候构造一个混合器可能并不合适。

6. 继承@extend

scss减少重复的主要特性就是选择器继承。

选择器继承是指一个选择器可以继承另一个选择器定义的所有样式。通过@extend语法实现:

.error { border: 1px solid red; }
 //应用到hl.seriousError
h1.error { font-size: 1.2rem; }
.seriousError {
  @extend .error;
  border-width: 3px;
}

/*编译后*/
.error, .seriousError {  border: 1px solid red; }
h1.error, h1.seriousError { font-size: 1.2rem; }
.seriousError { border-width: 3px; }

6.1 仅给继承用的占位符选择器%

有时,需要定义一套样式并不是给某个元素用,而是只通过 @extend 指令使用,如果不使用则不会编译到最终css文件中。

// 这段代码不会被输出到最终生成的CSS文件,因为它没有被任何代码所继承。
%other-styles { display: flex; }
// 下面代码会正常输出到生成的CSS文件,因为它被其接下来的代码所继承。
%message-common { border: 1px solid #ccc; }
.message { @extend %message-common; }

/*编译后*/
.message { border: 1px solid #ccc; }

6.2 !optional解决继承不存在报错

如果 @extend 失败会收到错误提示,比如,这样写 a.important {@extend .notice},当没有 .notice 选择器时,将会报错

!optional标记前面的扩展不必须生成一个新的选择器。

a.important {
  @extend .notice !optional; // .notice不存在时不会报错
}

6.1 继承的工作细节

跟变量和混合器不同,继承不是仅仅用css样式替换@extend处的代码那么简单。

@extend背后最基本的想法是,如果.seriousError @extend .error, 那么样式表中的任何一处.error都用.error``.seriousError这一选择器组进行替换。这就意味着相关样式会如预期那样应用到.error.seriousError。当.error出现在复杂的选择器中,比如说h1.error``.error a或者#main .sidebar input.error[type="text"],那情况就变得复杂多了,但是不用担心,sass已经为你考虑到了这些。

关于@extend有两个要点你应该知道。

  • 跟混合器相比,继承生成的css代码相对更少。因为继承仅仅是重复选择器,而不会重复属性,所以使用继承往往比混合器生成的css体积更小。如果你非常关心你站点的速度,请牢记这一点。
  • 继承遵从css层叠的规则。当两个不同的css规则应用到同一个html元素上时,并且这两个不同的css规则对同一属性的修饰存在不同的值,css层叠规则会决定应用哪个样式。相当直观:通常权重更高的选择器胜出,如果权重相同,定义在后边的规则胜出。

混合器本身不会引起css层叠的问题,因为混合器把样式直接放到了css规则中,而继承存在样式层叠的问题。被继承的样式会保持原有定义位置和选择器权重不变。通常来说这并不会引起什么问题,但是知道这点总没有坏处。

7. 加减乘除、取整等运算 (+, -, *, /, %)

SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %),如果必要会在不同单位间转换值。

.container { width: 100%; }
article[role="main"] {
  float: left;
  width: 600px / 960px * 100%;
}
aside[role="complementary"] {
  float: right;
  width: 300px / 960px * 100%;
}

/*编译后*/
.container { width: 100%; }
article[role=main] {  float: left; width: 62.5%; }
aside[role=complementary] { float: right; width: 31.25%; }

参考资料

Sass中文网

scss转CSS

css转scss

Last Updated: 2/25/2022, 10:01:00 AM