关于css:原生CSS嵌套简介

107次阅读

共计 2755 个字符,预计需要花费 7 分钟才能阅读完成。

嵌套是应用 Sass 等 CSS 预处理器的外围起因之一。当初,该性能曾经以相似的语法呈现在规范浏览器 CSS 中。你是否在构建零碎时放弃对预处理器的依赖?

CSS 嵌套能够节俭输出工夫,并使语法更易于浏览和保护。迄今为止,你必须像这样键入残缺的选择器门路:

.parent1 .child1,
.parent2 .child1 {color: red;}

.parent1 .child2,
.parent2 .child2 {color: green;}

.parent1 .child2:hover,
.parent2 .child2:hover {color: blue;}

当初,你能够将子选择器嵌套在父选择器中,比方:

.parent1, .parent2 {

  .child1 {color: red;}

  .child2 {
    color: green;

    &:hover {color: blue;}
  }

}

你能够嵌套任意层级的选择器,但要留神不要超过两到三级。嵌套层级没有技术层面的限度,然而会让代码更难浏览,并且让最终 CSS 变得很简短。

直到 2023 年四月,暂没有浏览器反对 CSS 嵌套语法。你须要应用 CSS 预处理器(如 Sass、Less 或 PostCSS)进行构建步骤,以便将嵌套代码转换为惯例的全选择器语法。嵌套性能现已在 Chrome 112+ 和 Safari 16.5+ 中实现,Firefox 将在 2023 年晚些时候提供反对。

CSS 原生嵌套规定

你能够将任何选择器嵌套到另一个选择器中,但必须以符号结尾,如 &.(用于 HTML class),#(用于 HTML id),@(用于媒体查问),:::*+~>,或 [。换句话说,它不能间接援用 HTML 元素。上面的代码有效,<p> 选择器不会被解析:

.parent1 {

  /* FAILS */
  p {color: blue;}

}

修复该问题最简略的办法就是应用&,其与 Sass 雷同的形式援用以后选择器:

.parent1 {

  /* WORKS */
  & p {color: blue;}

}

或者,能够这么解决:

  • > p – 但这将仅对 .parent1 的间接子元素进行款式调整
  • :is(p) – 然而 :is() 应用最优先选择器的优先级
  • :where(p) – 然而 :where() 的优先级为 0

在这个简略的示例中,它们都能够工作,但在当前应用更简单的样式表时,你可能会遇到优先级问题。

&还容许你在父选择器上定位伪元素和伪类。例如:

p.my-element {&::after {}

  &:hover {}

  &:target {}}

如果你不应用 &,你的指标将是选择器的所有子元素,而不是p.my-element 自身。(在 Sass 中也会呈现同样的状况)。

须要留神的是,你能够在选择器的任何地位应用&,比方:

.child1 {

  .parent3 & {color: red;}

}

这会转换为下列非嵌套语法:

.parent3 .child1 {color: red;}

你甚至能够在一个选择器中应用多个 & 符:

ul {

  & li & {color: blue;}

}

这会作用于嵌套的 <ul> 元素(ul li ul),如果你不想被逼疯我倡议还是不要这么应用了!

最初,你能够嵌套媒体查问。上面的代码为段落元素利用了 cyan 色彩,除非浏览器宽度至多为 800px,否则将变为purple

p {

  color: cyan;

  @media (min-width: 800px) {color: purple;}

}

CSS 原生嵌套问题

原生嵌套在 :is() 中包裹父选择器,这可能会导致与 Sass 输入的差别。

思考下列的嵌套代码:

.parent1, #parent2 {.child1 {}
}

在浏览器中解析时,这实际上变成了以下内容:

:is(.parent1, #parent2) .child1 {}

.parent1中的 .child1 元素的优先级为 101,因为 :is() 应用了其最优先选择器的优先级 – 在本例中,是#parent2 ID。

Sass 编译的代码与此雷同:

.parent1 .child1,
#parent2 .child1 {}

在本例中,.parent1 中的 .child1 元素的特异性为 002,因为它匹配两个类(#parent2 被疏忽)。它的选择器比原生选项的优先级低,在级联中被笼罩的可能性更大。

你可能还会遇到一个更奥妙的问题。思考下列代码:

.parent .child {.grandparent & {}

}

原生 CSS 等价于:

.grandparent :is(.parent .child) {}

这与下列排序谬误的 HTML 元素相匹配:

<div class="parent">
  <div class="grandparent">
    <div class="child">MATCH</div>
  </div>
</div>

因为 CSS 解析器会执行以下操作,因而 MATCH 会扭转款式:

  1. 在 DOM 层次结构中的任意地位,找到所有类为 child 的元素,同时先人元素的类为parent
  2. 在找到蕴含 MATCH 的元素后,解析器会查看该元素是否有一个先人为 grandparent 的元素 – 同样是在 DOM 层次结构中的任意地位。找到后,解析器会相应地对该元素利用款式。

在 Sass 中不是这种状况,最终会编译成这样:

.grandparent .parent .child {}

下面的 HTML 没有款式化,因为元素的类没有遵循严格的 grandparentparentchild程序。

最初,Sass 应用字符串替换,所以像上面这样的申明是无效的,能够匹配任何具备 outer-space 类的元素:

.outer {&-space { color: black;}
}

而原生 CSS 会疏忽 &-space 选择器。

还须要 CSS 预处理器吗

在短期内,现有的 CSS 预处理器依然必不可少。

Sass 开发团队曾经发表,他们将反对 .css 文件中的原生 CSS 嵌套,并按原样输入代码。他们将判若两人地编译嵌套的 SCSS 代码,以防止毁坏现有代码库,但当寰球浏览器支持率达到 98% 时,他们将开始输入 :is() 选择器。

我猜想 PostCSS 插件等预处理器目前会扩大嵌套代码,但当浏览器支持率越来越高时,就会移除该性能。

当然,应用预处理器还有其余很好的理由 – 比方将局部代码捆绑到繁多文件中,以及精简代码。但如果嵌套是你惟一须要的性能,那么你当然能够思考在小型我的项目中应用本地 CSS。

总结

CSS 嵌套是最有用、最实用的预处理器性能之一。浏览器供应商努力创造了一个本地 CSS 版本,其相似性足以让 Web 开发人员称心。尽管两者之间存在细微差别,而且在应用(过于)简单的选择器时可能会遇到不寻常的优先级问题,但很少有代码库须要进行彻底批改。

原生嵌套可能会让你重新考虑对 CSS 预处理器的需要,但它们仍能提供其余益处。Sass 和相似工具依然是大多数开发人员工具包的重要组成部分。

以上就是本文的全部内容。如果对你有所帮忙,欢送点赞、珍藏、转发~

正文完
 0