在 CSS 中,如何选择*不是*具有符合可识别模式的类的容器元素的后代的元素?



想象一下下面的HTML和CSS已经设置好了。

我可以在已经编写的 CSS 下添加哪些 CSS 规则以使红色段落显示为红色?

body,
div {
display: flex;
flex-wrap: wrap;
}
p {
margin: 6px;
}
.one-filter-one p,
p[class^="one-filter-one"] {
color: blue;
}
.two-filter-two p,
p[class^="two-filter-two"] {
color: green;
}
.four-filter-four p,
p[class^="four-filter-four"] {
color: orange;
}
<p class="another-class">This is red.</p>
<p>This is red.</p>
<div class="one-filter-one">
<p>This is blue.</p>
<p class="one-filter-one--paragraph">This is blue.</p>
</div>
<p class="two-filter-two">This is green.</p> 
<p>This is red.</p> 
<p class="another-class-two">This is red.</p>
<div class="three-filter-three">
<p>This is unstyled (black).</p>
<div><p>This is unstyled (black) too.</p></div> 
</div>
<div class="four-filter-four">
<p class="four-filter-four--sentence">This is orange.</p>
</div>

<p class="five-filter-five">This is also unstyled (black).</p>
<div class="another-class-three">
<p>This is red.</p>
<p class="another-class-four">This is red.</p>
</div>


我最好的猜测是使用伪类:not()

但我并不完全相信这是正确的方法,主要是因为我不确定:not()能否处理此案。

我尝试使用:not()解决方案:

body,
div {
display: flex;
flex-wrap: wrap;
}
p {
margin: 6px;
}
.one-filter-one p,
p[class^="one-filter-one"] {
color: blue;
}
.two-filter-two p,
p[class^="two-filter-two"] {
color: green;
}
.four-filter-four p,
p[class^="four-filter-four"] {
color: orange;
}
p:not([class*="-filter-"]) {
color: red;
}
<p class="another-class">This is red.</p>
<p>This is red.</p>
<div class="one-filter-one">
<p>This is blue.</p>
<p class="one-filter-one--paragraph">This is blue.</p>
</div>
<p class="two-filter-two">This is green.</p> 
<p>This is red.</p> 
<p class="another-class-two">This is red.</p>
<div class="three-filter-three">
<p>This is unstyled (black).</p>
<div><p>This is unstyled (black) too.</p></div> 
</div>
<div class="four-filter-four">
<p class="four-filter-four--sentence">This is orange.</p> </div>

<p class="five-filter-five">This is also unstyled (black).</p>
<div class="another-class-three">
<p>This is red.</p>
<p class="another-class-four">This is red.</p>
</div>

显然不是这样,因为我没有正确选择:

不是[class*="-filter-"]后代元素.

但我根本不清楚该怎么做。

有没有办法做到这一点,或者鉴于 CSS 的当代功能,我希望在 2020 年实现不可能的目标?

<小时 />

注释:

虽然,在 2020 年,伪类:not()已经存在了十年的大部分时间,但我一直倾向于避免使用它。我唯一知道的是,:not()伪类函数只能接受简单(即不是复合(选择器。


新增:

根据@G-Cyrillus的精彩建议(在下面的评论中(,我想出了以下内容:

body > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]) {
color: red;
}

从好的方面来说,这确实有效。(所以,比我以前拥有的任何东西都要好得多(。

在减号方面:

  • 很啰嗦
  • 它不优雅
  • 它仅适用于元素嵌套的第四级
  • 我当然可以继续添加关卡,但这只会使它更冗长和不优雅

这是一项教育活动。

它教会我的最重要的事情是,鉴于:not()不能接受复合选择器,在应用:not()后处理后续嵌套级别的标记远非简单。

鉴于以下情况:

.filter-1 {
color: red;
}
:not([class^="filter-"]) p {
color: blue;
}
<div>
<div>
<p>Test.</p>
</div>
</div>
<div class="filter-1">
<div>
<p>Test.</p>
</div>
</div>

第二个<p>仍然出现在blue.

为什么?因为即使它的祖父母有类.filter-1,它的直系父母也没有......这足以满足 CSS 规则中p之前的任何后代选择器(即[SPACE](:

:not([class^="filter-"]) p

解决此问题的唯一方法是将规则替换为:

:not([class^="filter-"]) > * > p

这现在有效:

.filter-1 {
color: red;
}
:not([class^="filter-"]) > * > p {
color: blue;
}
<div>
<div>
<p>Test.</p>
</div>
</div>
<div class="filter-1">
<div>
<p>Test.</p>
</div>
</div>

但。。。

CSS 规则现在与 HTML 结构紧密绑定,上面修改后的 CSS 规则现在不适用于:

<div class="filter-2">
<p>Test.</p>
</div>

看:

.filter-1 {
color: red;
}
:not([class^="filter-"]) > * > p {
color: blue;
}
<div>
<div>
<p>Test.</p>
</div>
</div>
<div class="filter-1">
<div>
<p>Test.</p>
</div>
</div>
<div class="filter-2">
<p>Test.</p>
</div>

相反,我们现在需要使用两个规则

:not([class^="filter-"]) > p,
:not([class^="filter-"]) > * > p

得出以下结论:

我们只能在CSS 中显式描述HTML 结构时使用:not()来排除后代。

我现在更清楚地理解@G-Cyrillus的意思:

您还需要注意结构


后续步骤:

在我的 CSS 中描述无限数量的潜在后代结构显然是不切实际的,所以我:

1(重新配置了我的架构,以允许在其他地方描述更复杂的后代关系

2( 优化了我的排除查询,以:

body > :not([id^="filter-"]):not([class^="filter-"])

再次非常感谢,@G-Cyrillus- 由于您在评论部分的大量帮助,我只做到了这一点。

最新更新