嵌套

嵌套 CSS 样式规则可让您的样式表更有条理、更易于阅读和维护。

概览

现在,您已经了解了选择器,接下来可能想知道如何在样式表中更好地整理它们。假设您要为网站上“功能”部分中的项目应用样式。通过嵌套,您可以将这些样式分组到 .feature 规则中,如下所示:

.feature {
  button {
    color: blue;
  }

  .link {
    color: red;
  }

  .text {
    font-size: 1.3em;
  }
}

这与单独写入每种样式相同:

.feature button {
  color: blue;
}

.feature .link {
   color: red;
}

.feature .text {
   font-size: 1.3em;
}

嵌套的层数可以根据需要任意设置。

.feature {
  .heading {
    color: blue;

    a {
      color: green;
    }
  }
}

分组和建立关系

通过嵌套,您可以更简洁地对样式规则进行分组并建立它们之间的关系。

默认情况下,嵌套规则将通过后代选择器与外部规则相关联。使用嵌套规则中的选择器更改关系。

/* targets headings that are siblings of the .feature element and come immediately after it */
.feature {
  + .heading {
    color: blue;
  }

/* targets all paragraphs that are direct children of the .feature element */
  > p {
    font-size: 1.3em;
  }
}

使用 & 选择器定义显式关系

您还可以使用 & 选择器在嵌套样式规则时更明确地指定目标元素。可以将 & 视为表示父级选择器的符号。

.feature {
 & button {
    color: blue;
  }
}

这相当于以如下方式编写样式:

.feature button {
  color: blue;
}

何时需要提供 &

如果没有 &,嵌套选择器将成为父选择器的后代选择器。如需构成复合选择器& 是必需的

.feature {
  &:last-child {
    /* Selects the .feature element that is the :last-child, equivalent to .feature:last-child */
  }
   
  & :last-child {
    /* Selects the :last-child inside of a .feature element, equivalent to .feature :last-child */
  }

  &.highlight {
    /* Selects .feature elements that also have a .highlight class, equivalent to .feature.highlight */
  }

  & .highlight {
     /* Selects elements inside of the .feature element with the class .highlight, equivalent to .feature .highlight */
  }
}

您还可以更改上下文,并将 & 选择器放在子选择器的末尾或两侧。


/* Targets buttons with an adjacent sibling button */
button {
  & + & {
    /* … */
  }
}
img {
  .my-component & {
    /* styles for images inside of `.my-component` ... */
  }
}

在最后一个示例中,我们为具有 .my-component 类的元素内的图片添加样式。如果您正在处理的项目无法向元素添加 classid,这会非常有用。

嵌套和特异性

:is() 类似,嵌套选择器的特异性取决于父选择器列表中特异性最高的选择器。

#main-header,
.intro {
  & a {
    color: green;
  }
}

.intro a {
  color: blue;
}

第一条规则以 #main-header.intro 元素内的所有链接为目标,并为其指定绿色。

第二条规则尝试覆盖此规则,以使 .intro 元素内的链接显示为蓝色。

如果我们查看每条规则的具体程度,就会明白为什么此方法行不通。

/* equivalent to :is(#main-header, .intro) a with a specificity of (1, 0, 1) */
#main-header,
.intro {
  & a {
    color: green;
  }
}

/* lower specificity of (0, 1, 1) */
.intro a {
  color: blue;
}

由于第一个规则的选择器列表中包含 id,并且嵌套规则采用具有最高选择器优先级的选择器的优先级,因此第一个规则的优先级高于第二个规则。即使对于不在具有 #main-header 选择器的元素内的 a 元素,链接也是绿色的。

嵌套无效

:is() 类似,嵌套选择器无法表示伪元素。

blockquote, blockquote::before, blockquote::after {
  color: navy;

  & {
    border: 1px solid navy;
  }
}

您可能认为 blockquote 及其伪元素都应具有 navy 彩色文字和边框,但事实并非如此。由于 & 选择器无法表示伪元素,因此嵌套的边框样式将仅应用于 blockquote。

使用 & 和类型选择器创建复合选择器时,类型选择器必须放在最前面,且两者之间不能有任何空格。

/* valid css nesting */
.feature {
  p& {
    font-weight: bold;
  }
}

/* invalid css nesting */
.feature {
  &p {
    font-weight: bold;
  }
}

此规则允许 CSS 嵌套与 Sass 等预处理工具协同工作。在 Sass 中,编写 &p 会将父级选择器附加到嵌套类型选择器,结果为 .featurep

嵌套 at 规则

CSS 条件组规则(例如 @container@media@supports@layer)也可以嵌套。

.feature {
  @media (min-width: 40em) {
    /* ... */
  }

  @container (inline-size > 900px) {
    /* ... */
  }
}

.feature {
  @supports (display: grid) {
    /* ... */
  }
}

.feature {
  @layer component {
    h2 {
      /* ... */
    }
  }
}

检验您的掌握情况

使用 CSS 嵌套时,& 选择器表示什么?

嵌套的子选择器
错误。
父级选择器
正确!
最近的同级选择器
错误。

您最多只能嵌套两层。

正确
错误。
错误
正确!

哪些 at 规则可以嵌套?

@media
正确!
@container
正确!
@import
错误。
@supports
正确!
@layer
正确!