Sass 嵌套(Nested)

1. 前言

在企业的实际项目开发中,Sass 的嵌套可以说是非常非常有用的,它可以让你的 CSS 代码易于管理和维护,看起来也比较清晰,这也是 Sass 中很基础的一个知识点,首先掌握这个至关重要!在此章节我们将学习 Sass 嵌套中的嵌套规则、属性嵌套、父选择器和占位符选择器。Sass 嵌套式一个很基础也很简单的语法,关键在于要多多练习使用!

2. 什么是嵌套?

在一般编写 CSS 的时候呢,我们一遍一遍的编写相同的选择器去处理深层级的样式,而 Sass 给你一种轻松的方式,你可以在一个样式规则中直接编写另一个样式规则,而不是重复相同的选择器,Sass 将自动组合内外部的选择器。

通俗点说就是:你可以在父选择器的样式中直接编写子元素的样式,同理你可以在一个子元素的样式中再去编写孙元素的样式,可以一层一层的嵌套着去写样式。

3. 语法详情

我们先举一个简单的例子体验下 Sass 的嵌套语法,看不懂没关系,后面会逐一讲解:

.father {
  color: red;
  .child {
    color: green;
    &:hover {
      color: red;
    }
    &:active {
      color: blue;
    }
    &-item {
      color: orange;
    }
  }
}

这段 Sass 代码最终会转换为如下的 CSS 代码:

.father {
  color: red;
}
.father .child {
  color: green;
}
.father .child:hover {
  color: red;
}
.father .child:active {
  color: blue;
}
.father .child-item {
  color: orange;
}

4. 使用场景

一般来说 Sass 中的嵌套应用于以下几种场景:

  • 样式的嵌套
  • 父选择器
  • 占位符选择器
  • 属性嵌套

4.1 样式的嵌套

Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器,我们用编写一个导航的样式来举例,假定我们的导航 nav 下面有 ul 标签,ul 标签下又有 li 标签,li 标签下呢又有 a 标签,下面我使用 Sass 来处理导航中的样式:

nav {
  width:200px;
  background:white;
  ul {
    width:100%;
    background:red;
    li {
      width:100%;
      background:blue;
      a {
        color:green;
        font-size:20px;
      }
    }
  }
}

我们可以看到在上面的代码中,我们在 nav 的样式规则中,可以直接通过选择器去编写另外一套样式规则,并且可以一直嵌套,这段代码将会被编译成如下的 CSS :

nav {
  width: 200px;
  background: white;
}
nav ul {
  width: 100%;
  background: red;
}
nav ul li {
  width: 100%;
  background: blue;
}
nav ul li a {
  color: green;
  font-size: 20px;
}

写起来是不是方便很多,但使用嵌套的时候同时需要注意:

嵌套规则很有用很方便,但是你很难想象它实际会生成多少 CSS 语句,嵌套的越深,那么编译为 CSS 的语句就越多,同时消耗的资源也会越多,所以开发者尽量不要嵌套特别深的层级!

4.1.1 嵌套选择器列表 (Selector Lists)

嵌套规则可以很方便的处理选择器列表,由逗号分隔的选择器列表会被 Sass 组合到一个选择器列表中,我们举个例子看下:

.alert, .warning {
  ul, p {
    margin-right: 0;
    margin-left: 0;
    padding-bottom: 0;
  }
}

上面这种写法会被转为如下的 CSS 代码:

.alert ul, .alert p, .warning ul, .warning p {
  margin-right: 0;
  margin-left: 0;
  padding-bottom: 0;
}

4.1.2 嵌套组合符选择器 (Selector Combinators)

如果你对选择符很陌生的话,一定要先看下什么是 CSS 选择符

我们还可以嵌套使用带有选择符的选择器,我们可以将选择符放在外部选择器的末尾,或者内部选择器的开始位置,这里我们举一个官网的例子:

ul > {
  li {
    list-style-type: none;
  }
}

h2 {
  + p {
    border-top: 1px solid gray;
  }
}

p {
  ~ {
    span {
      opacity: 0.8;
    }
  }
}

上面这种写法会被转换为如下的 CSS 代码:

ul > li {
  list-style-type: none;
}

h2 + p {
  border-top: 1px solid gray;
}

p ~ span {
  opacity: 0.8;
}

4.2 父选择器 (Parent Selector)

父选择器是 Sass 中一种特殊的选择器,用于嵌套选择器中,用来引用外部的选择器;通俗的讲就是,当你使用嵌套的时候,可能你会需要使用到嵌套外层的父选择器,比如为一个元素 添加伪类 (hover、active、before、after) 的时候,可以用 & 代表嵌套规则外层的父选择器,我们举个例子来更直观的感受下:

a {
  &:hover {
    color:red;
  }
  &:active {
    color:blue;
  }
  &:before {
    content:'';
  }
  &:after {
    content:'';
  }
  span {
    &:hover {
      color:green;
    }
  }
}

在上面的 Sass 代码中我们编写了几个伪类,在编译的时候 & 将会被替换为嵌套外层的父选择器,有多层嵌套的话将会把父选择器一级一级的传递下去,最终转换为如下的 CSS 代码:

a:hover {
  color: red;
}
a:active {
  color: blue;
}
a:before {
  content: "";
}
a:after {
  content: "";
}
a span:hover {
  color: green;
}

4.2.1 添加后缀 (Adding Suffixes)

可以使用 & 向外部选择器添加后缀,举个例子看下:

.box {
  width:100px;
  &-head {
    width:100%;
    &-title {
      color:red;
    }
  }
  &-body {
    width:100%;
  }
  &-footer {
    width:100%;
  }
}

上面这个例子将会转换为如下的 CSS 代码:

.box {
  width: 100px;
}
.box-head {
  width: 100%;
}
.box-head-title {
  color: red;
}
.box-body {
  width: 100%;
}
.box-footer {
  width: 100%;
}

4.3 占位符选择器 (Placeholder Selectors)

在 Sass 中这是一种特殊的选择器,称为 "占位符";它以 % 开头,必须通过 @extend 指令调用,如果单独使用的话是不会编译到 CSS 中的,后面会讲到 @extend 指令,这里我们先举个简单的例子感受一下:

%placeholder {
  width:100px;
  height:100px;
  color:red;
  &:hover {
    color:blue;
  }
}

.btn {
  @extend %placeholder;
  font-size: 18px;
}

.btn2 {
  @extend %placeholder;
  font-size: 16px;
}

请记住,占位符必须通过 @extend 指令调用才会转换为如下的 CSS 代码:

.btn2, .btn {
  width: 100px;
  height: 100px;
  color: red;
}
.btn2:hover, .btn:hover {
  color: blue;
}

.btn {
  font-size: 18px;
}

.btn2 {
  font-size: 16px;
}

4.4 属性嵌套

当我们在写 CSS 样式的时候,有些 CSS 属性具有相同的命名空间 (namespace),比如定义字体样式的属性: font-size ; font-weight ; font-family ; 它们具有相同的命名空间 font 。再比如定义边框样式的属性:border-radius ; border-color ; 它们具有相同的命名空间 border 。当然还有很多其他这种的属性,为了方便管理和避免重复输入,Sass 允许将属性嵌套在命名空间中,同时命名空间也可以具有自己的属性值,我们举例看一下:

.box {
  border: {
    radius: 5px;
    color:red;
  }
  font: {
   family:'YaHei';
   size:18px;
   weight:600;
  }
  margin: auto {
    bottom: 10px;
    top: 10px;
  };
}

上面这种写法将会被转换为如下的 CSS 代码:

.box {
  border-radius: 5px;
  border-color: red;
  font-family: "YaHei";
  font-size: 18px;
  font-weight: 600;
  margin: auto;
  margin-bottom: 10px;
  margin-top: 10px;
}

5. 实战经验

我们一起来看看在实际的项目开发中,Sass 嵌套是怎么应用的;如下图所示,这是一个比较常见的中后台系统的页面,我们使用 Sass 嵌套来编写左侧导航菜单的样式。

图片描述

这里左侧导航我们用到了 element-ui 组件库的导航组件,同时我们需要把左侧导航的样式修改为如图所示的样式,左侧导航的主要 DOM 结构是这样的:

图片描述

基于这样的一个 DOM 结构,在写样式的时候需要从 根节点 .catalyst-gui-menu 开始来依次选择子节点并编写样式,那么这里我们就可以直接使用 Sass 嵌套来编写:

.catalyst-gui-menu {
  width: 100%;
  height: 100%;
  .logo{
    width: 100%;
    height: 48px;
    background: none;
    color: #ffffff;
    line-height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    img {
      width: 40px;
      margin: 0px 8px 0px 0px;
    }
    span {
      font-weight: 600;
      font-size: 18px;
    }
  }
  .menus {
    width: 100%;
    height: calc(100% - 48px);
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    padding-top: 16px;
  }
  .el-menu {
    height: 100%;
    .el-menu-item {
      width:100%;
      &:hover {
        background: red;
      }
    }
  }
}

可以看到我们编写样式的结构就像 DOM 结构一样,是一层一层向下嵌套的,同时还使用了 & 为元素添加伪类,那么这段 Sass 代码最终会转换为如下的 CSS 代码:

.catalyst-gui-menu {
  width: 100%;
  height: 100%;
}
.catalyst-gui-menu .logo {
  width: 100%;
  height: 48px;
  background: none;
  color: #ffffff;
  line-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.catalyst-gui-menu .logo img {
  width: 40px;
  margin: 0px 8px 0px 0px;
}
.catalyst-gui-menu .logo span {
  font-weight: 600;
  font-size: 18px;
}
.catalyst-gui-menu .menus {
  width: 100%;
  height: calc(100% - 48px);
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  padding-top: 16px;
}
.catalyst-gui-menu .el-menu {
  height: 100%;
}
.catalyst-gui-menu .el-menu .el-menu-item {
  width: 100%;
}
.catalyst-gui-menu .el-menu .el-menu-item:hover {
  background: red;
}

可以对比两段代码看下,使用 Sass 嵌套写出来的样式代码更有层次感更易于维护 (尤其是在企业级应用,多人开发的时候),同时你不需要一遍一遍重复的去编写当前节点的父选择器,所以说 Sass 嵌套在企业的前端项目开发中应用特别广泛,如果你接触的公司的项目中有使用 Sass ,那么嵌套的写法一定是项目中最普遍的!

6. 小结

本节内容我们主要讲了 Sass 中的嵌套规则,Sass 的嵌套是最基本也是最常用的功能,主要包括如下几个重点:

  • 样式的嵌套
    • 基本的样式嵌套
    • 嵌套选择器列表 (Selector Lists)
    • 嵌套组合符选择器 (Selector Combinators)
  • 父选择器
    • 添加后缀 (Adding Suffixes)
  • 占位符选择器
  • 属性嵌套

你来根据下面这张图来复习一下本节的内容:
图片描述
学会了 Sass 中的嵌套规则,快使用这种方式来改造一下你的 CSS 代码吧~