在 CSS 中,我如何 select 元素*不是*具有符合可识别模式的 class 容器元素的后代?
In CSS, how may I select elements which are *not* the descendants of a container element with a class conforming to a recognisable pattern?
假设下面的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()
伪 class.
但我并不完全相信这是正确的方法,主要是因为我不确定 :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 年,伪 class :not()
已经存在了十年的大部分时间,但我一直倾向于避免使用它。我唯一知道的是 :not()
伪 class 函数只能采用简单(即非复合)选择器。
已添加:
根据 @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
。
为什么?因为即使它的 grandparent 有 class .filter-1
,它的直接 parent 没有 ...这足以满足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
得出以下结论:
We can only use :not()
to exclude descendants when we also explicitly
describe the HTML structure in the CSS.
我现在更清楚地理解了@G-Cyrillus
的意思:
You need to mind the structure too
后续步骤:
在我的 CSS 中描述无限数量的潜在后代结构显然是不切实际的,所以我:
1) 重新配置了我的体系结构以允许在其他地方描述更复杂的后代关系
和
2) 将我的排除查询优化为:
body > :not([id^="filter-"]):not([class^="filter-"])
再次感谢,@G-Cyrillus
- 由于您在评论部分的大力帮助,我才做到了这一点。
假设下面的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()
伪 class.
但我并不完全相信这是正确的方法,主要是因为我不确定 :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 年,伪 class :not()
已经存在了十年的大部分时间,但我一直倾向于避免使用它。我唯一知道的是 :not()
伪 class 函数只能采用简单(即非复合)选择器。
已添加:
根据 @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
。
为什么?因为即使它的 grandparent 有 class .filter-1
,它的直接 parent 没有 ...这足以满足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
得出以下结论:
We can only use
:not()
to exclude descendants when we also explicitly describe the HTML structure in the CSS.
我现在更清楚地理解了@G-Cyrillus
的意思:
You need to mind the structure too
后续步骤:
在我的 CSS 中描述无限数量的潜在后代结构显然是不切实际的,所以我:
1) 重新配置了我的体系结构以允许在其他地方描述更复杂的后代关系
和
2) 将我的排除查询优化为:
body > :not([id^="filter-"]):not([class^="filter-"])
再次感谢,@G-Cyrillus
- 由于您在评论部分的大力帮助,我才做到了这一点。