图解CSS:CSS的嵌套

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

对于众多 CSSer 来说,多年来一直希望在原生的 CSS 有类似变量,嵌套和函数等特性。虽然近些年,CSS 得到快速的发展,比如说,大家期望的 CSS 变量已经可以直接在 CSS中使用了CSS也具备一些函数计算(甚至简单的逻辑判断)能力。今天要告诉大家的是,CSS 原生的嵌套很快就会出现在浏览器上。在今天这篇文章中就将和大家一起来聊聊 CSS 中原生的嵌套,以及如何使用它,在使用的过程需要怎样避免一些陷阱。

先从CSS处理器说起

十多年前,也就大约是2010年左右,CSS处理器开始被广大CSSer或Web开发者青眯,主要是因为这些CSS处理器(比如Sass、LESS、Stylus或PostCSS等)具备一些非常优秀的特性,就拿Sass这个CSS处理器来说,它具备变量,嵌套、混合宏和扩展器等。

Sass中的变量在过去是非常有用的,但现在逐步被原生的CSS自定义属性(也就是CSS变量)所替代。CSS原生的变量到今天能在众多主流浏览器上使用,成为规范的模块之一也是花了很长时间的。作为 CSS 语言的一部分,CSS变量比Sass这样的处理器的变量要强大得多,而且还可以使用 JavaScript来修改。

因此,对于Web开发者而言,特别是CSSer,他们得到了CSS原生变量带来的优惠,但同时也期待着CSS的原生嵌套能成为一模块,并且得到浏览器支持。

众所周之,CSS的嵌套能给开发得带来便利,让代码更易于维护,比如下面这段SCSS代码:

$M: 640px;
$color-grey-33: #333;

.key-Selector {
    width: 100%;

    @media (min-width: $M) {
        width: 50%;
    }

    .an-Override_Selector & {
        color: $color-grey-33;
    }
}

经过编译之后:

.key-Selector {
    width: 100%;
}

@media (min-width: 640px) {
    .key-Selector {
        width: 50%;
    }
}

.an-Override_Selector .key-Selector {
    color: #333;
}

虽然像Sass这样的处理器能给我们带来很多便利,但它并不能直接运行在客户端上(比如浏览器),它需要经过一些编译处理:

可能还会采用一些其他处理器(大家常称的后处理器)处理编译出来的CSS代码:

最终编译处理好的代码才能被客户端识别解析。

而原生的就不一样了,他不需要任何处理器处理就能直接在客户端上运行。这也是为什么希望在CSS中有原生变量,嵌套等特性。

真正的CSS嵌套

关于将嵌套纳入CSS规范的讨论已经持续了好几年(早在2005年 @Tab Atkins就提出了CSS的原生嵌套),同时在 Github上发起相关的讨论。在2019年3月初,CSS嵌套模块(CSS Nesting Module)的第一部分编辑草案发布了。该草案概述了一种未来的机制,通过这种机制,我们将能够对CSS选择器进行本地嵌套。例如,在纯CSS中,不使用任何处理器程序,也不需要经过任何编译器编译,就能被客户端识别,解析。

这个模块描述了对一个样式规则嵌套在另一个样式规则中的支持,允许内部规则的选择器引用外部规则所匹配的元素。这个功能允许相关的样式在CSS样式表中被聚合成一个单一的结构,提高了可读性和可维护性。

CSSWG已经同意发布该模夫的第份公共工作草案,使其成为建议的一部分。这样一来,事情变得正式了。也可以说,原生的CSS嵌套已经离我们越来越近了。

不过正如草案中所说:

它仅用于讨论,并可以在任何时候改变。在此公布并不意味着 W3C 对其内容认可。

简单地说,接下来讨论的东西,很有可能在未来或者任何时候都会改变,不建议直接用于生产中。但,不要让它影响我们的热情,因为它几乎与我们在处理器中所提到的嵌套功能相同。

接下来,我们通过和SCSS对比的方式,来看看CSS原生嵌套的相关规则和使用。

CSS 嵌套是什么样子的?

熟悉Sass的同学对嵌套应该不会感到陌生,它看起来像这样:

// SCSS
div {
    background: #fff;

    p {
        color: red;
    }
}

编译出来的CSS:

div {
    background: #fff;
}

div p {
    color: red;
}

可以使用 Sassmeister 在线查看编译后的代码!

用原生 CSS 的嵌套来编写,看上去和 Sass 的非常相似:

/* CSS */
div {
    background: #fff;

    & p {
        color: red;
    }
}

你会注意到在 p 选择器前面有一个 & 符号,这个符号在此称为 嵌套选择器,它将告诉浏览器,你想把p嵌套在div

其实在Sass处理器中也有这样的&符,比如:

// SCSS
div {
    background: #fff;

    & p {
        color: red;
    }
}

/*编译出来的 CSS*/
div {
    background: #fff;
}

div p {
    color: red;
}

但在Sass处理器使用 & 符,一般不像上面这样使用,因为有点多此一举,画蛇添足的感觉。在Sass中使用&符,一般只有当你想在前面的选择器中添加一些东西(比如一个类)时,才使用:

// SCSS
div {
    background: #fff;

    &.red {
        color: red;
    }
}

/* 编译出来的 CSS */
div {
    background: #fff;
}

div.red {
    color: red;
}

在 Sass 中,&除了可以放在一个选择器前面让其变成 .select1.select2之外,还可以让其放在一个选择器后面:

// SCSS
div {
    background: #fff;

    &.red {
        color: red;
    }

    .blue & {
        color: blue;
    } 
}

/* 编译出来的 CSS */
div {
    background: #fff;
}

div.red {
    color: red;
}

.blue div {
    color: blue;
}

& 放在一个选择器之后,将变编译成.select2 .select1这样。

但在原生的 CSS 嵌套中,这样使用是一种错误的语法规则,即,下面的代码不正确:

/* CSS */
div {
    background: #fff;

    .blue & {
        color: blue;
    }
}

虽然上面代码的嵌套规则语法不成立,但并不代表在原生CSS就没有类似的功能。在CSS原生嵌套中:

如果要成为嵌套前缀,一个嵌套选择器必须是选择器的第一个复合选择器中的第一个简单选择器。如果选择器一个选择器列表,列表中的每一个复合选择器都必须是嵌套的,才能使选择器作为一个整体嵌套。

简单地说,规范中提供了另一个特性,使用嵌套规则 @nest,就可以把 & 放在其他地方。通过给选择器加上 @nest 前缀,你可以选择你想让选择器嵌套的位置。

/* CSS */
div {
    background: #fff;

    @nest .blue & {
        color: blue;
    }
}

上面的代码和下面这段Sass代码达到同等的功能:

// SCSS
div {
    background: #fff;

    .blue & {
        color: blue;
    }
}

从上面的示例中,我们可以发现,CSS原生嵌套中 &@nest 对我们很重要。其中:

  • & 是一个选择器,称为 嵌套选择器
  • @nest 是一个规则(@规则),用来描述或定义选择器嵌套的规则

如果想彻底的了解和掌握CSS嵌套的使用,就必须对&@nest有深入的了解。

CSS嵌套选择器 &

当使用一个嵌套的样式规则时, 必须能够引用父规则所匹配的元素 ,这也是嵌套的全部意义所在。比如我们有一个这样的 HTML结构:

<!-- HTML -->
<div class="foo">
    <div class="faz"></div>
</div>
<div class="bar"></div>

下面两段代码,其中一段对于嵌套是无意义的:

/* 符合嵌套样式规则 */
.foo {
    background: #fff;

    & .faz {
        color: red;
    }
}

/* 不符合嵌套规则 */
.foo {
    background: #fff;

    & .bar {
        color: red;
    }
}

在 CSS 嵌套模块中,为了实现“样式嵌套必须能够引用父规则所匹配的元素”,规范中定义了一个新的选择器,即 嵌套选择器,也就是 & 符。

当在一个嵌套样式规则的选择器中使用时,嵌套选择器代表被父规则匹配的元素。当在任何其他情况下使用时,它不代表任何东西。也就是说,它是有效的,但没有匹配任何元素。

比如下面这个示例:

/* CSS */
.foo {
    color: red;

    & .bar {
        color: blue;
    }
}

示例中的 & 其实代表的就是父选择器 .foo

另外,CSS 的嵌套选择器可以通过用父级样式规则的选择来代替它,用一个 :is()选择器来包装。比如说:

/* CSS */
a, b {
    & c { color: blue; }
}

/* 等效于 */
:is(a, b) c {
    color: blue;
}
剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/css/css-nestting.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部