Sass 提供了嵌套的书写方式,用以简化选择器的书写,同时也带来了“作用域”。
在 Sass 中,可以在父选择器中写子选择器,以嵌套的形式来表达关联的关系,这样做可以减少我们重复书写父选择器的工作量。
#content {
#article {
h1 {
color: red;
}
p {
color: grey;
}
}
}
编译后
#content #article h1 {
color: red;
}
#content #article p {
color: grey;
}
在编译时,Sass 会递归遍历所有嵌套关系,从最内层选择器开始,逐层在前面加上父选择器。
在 CSS 中,基本选择器分为以下几种:
其中,伪类和伪元素选择器需要与别的选择器复合使用,以确定是哪些元素的伪类或伪元素。而其它选择器也可以复合使用,如 div#id、div.class、div[lang='en'] 等。
Sass 为了在嵌套中更好地表达这些复合关系,提供了父选择器 &。
div {
content: '#{&}'; // 将 & 当做变量使用
&#app { color: green; }
&.app { color: blue; }
&:hover { color: red; }
&:first-child { color: grey; }
&::before { content: ''; }
}
编译后
div { content: "div"; }
div#app { color: green; }
div.app { color: blue; }
div:hover { color: red; }
div:first-child { color: grey; }
div::before { content: ''; }
可以看到,如果把 & 当做变量使用,它被编译为了父选择器。 要注意的是,在复合选择器中,& 只能放在开头使用。
在 CSS 中,可以用逗号分隔多个选择器,形成一个群组。元素只要满足群组中任何一个选择器,都会使用群组对应的样式进行渲染,如
a, span, label {
color: grey;
}
在 Sass 中,我们可以使用嵌套的形式来简写群组。
.container {
h1, h2, h3 { margin-bottom: .8em; }
}
nav, aside {
a { color: blue; }
}
编译后
.container h1, .container h2, .container h3 {
margin-bottom: .8em;
}
nav a, aside a {
color: blue;
}
组合选择器:
对于组合选择器,直接嵌套就可以了。
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 }
除了可以嵌套书写选择器,还可以嵌套书写属性,如
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
编译后
nav {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
Sass 引入了嵌套,出现了嵌套层级,自然也就有了“层级作用域”。
在 Sass 中,变量只能在它被声明的层级和子层级访问;如果一个变量在不同层级中被重复定义,在使用时会从下到上寻找最近的定义。这与 JS 中的函数作用域相似。
.inner {
$width: 10px;
width: $width;
p {
width: $width / 2;
}
}
编译后
.inner { width: 10px; }
.inner p { width: 5px; }
如果变量仅在子级被定义,而在父级被访问,编译时会报错。
Undefined variable: "$width".
@import 是 CSS2 原生支持的指令,由于 CSS 只有在执行到这条指令时,才会去加载对应的文件,这样会导致页面闪烁和加载变慢,所以平时并不常用。
Sass 改进了这条指令,它会在编译时将导入的资源直接替换并插入指令所在的位置。
因此,如果 @import 导入的资源位置在嵌套层级中,那么:
// _source.scss
$width: 10px;
p {
color: red;
font-size: 14px;
}
// index.scss
@import '_source';
$width: 20px;
.outer {
width: $width;
.inner {
@import '_source';
width: $width;
}
}
编译后
p { color: red; font-size: 14px; }
.outer { width: 20px; }
.outer .inner { width: 10px; }
.outer .inner p { color: red; font-size: 14px; }
在使用 @import 导入文件时,可以不写 .scss 或 .sass 后缀。
如果资源是作为专被引用的公共资源,规范的命名方法是在名称前加下划线。
以下几种情况,Sass 会将 @import 编译为原生的 CSS 指令:
@media 是 CSS 原生支持的指令,用于查询设备媒体,以便做响应式布局。
Sass 对 @media 做了一些改进,允许我们在嵌套的过程中书写媒体查询和响应代码。在编译时, Sass 会把媒体查询编译到文件最外层,并为子选择器加上父选择器前缀。
$media-prop: min-width;
$media-middle-width: 1200px;
$media-large-width: 1980px;
.container {
.left {
font-size: 12px;
@media screen and ($media-prop: $media-middle-width) {
font-size: 14px;
}
}
.right {
font-size: 14px;
@media screen {
@media ($media-prop: $media-middle-width) {
font-size: 18px;
}
@media ($media-prop: $media-large-width) {
font-size: 22px;
}
}
}
}
编译后
.container .left {
font-size: 12px;
}
@media screen and (min-width: 1200px) {
.container .left {
font-size: 14px;
}
}
.container .right {
font-size: 14px;
}
@media screen and (min-width: 1200px) {
.container .right {
font-size: 18px;
}
}
@media screen and (min-width: 1980px) {
.container .right {
font-size: 22px;
}
}
使用 Sass 媒体查询的好处: