英文:
This CSS :is() Selector Isn't Working As I Think It Should
问题
CSS选择器.a ~ .b :is(body .b .c .d)
为什么会匹配以下简单的HTML标记中的.d
,当第一个.b
和 :is()
之间的空格明显是一个后代组合器,所以选择器应该试图选择任何.d
,它是body
的后代的后代的后代的后代的后代的.b
的后代的后代(由于.b
和 :is()
之间的空格,它是.a
的后继.b
的后继的后代的后代的后代的后代的后代的后代的.b
的后代的后代的后代的后代的后代的后代的.c
的后代的后代的后代的.d
的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的.d
的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的后代的.d
。但是body
不是.b
的后代,然而.d
被选中,.d
的背景颜色被设置为橙色。
我认为:is()
或:where()
内部的选择器列表是相对的,如果它以一个组合器(例如+
、>
、~
)开头,否则它会被赋予一个暗示的后代组合器,因此body .b .c .d
只有在它们是.b
的后代时才会匹配,但它们不是(.c .d
是,但不是.b .c .d
或body .b .c .d
)。
我尝试了上面的HTML和CSS,并期望.d
不会被选中,但事实上它被选中了,这让我对“我认为CSS是如何工作的”产生了疑问。
**注意:**我知道只有一个选择器列表时,:is
是不必要的,最初让我调查这个问题的CSS中有多个选择器列表在:is()
内部,但首先我需要理解仅有一个选择器的情况,然后才能开始添加更多选择器。
英文:
Why does the CSS selector .a ~ .b :is(body .b .c .d)
match .d
in the following simple HTML markup when surely the space between the first .b
and :is()
is a descendant combinator so the selector should be trying to select any .d
that is a descendant of a .c
that is a descendant of a .b
that is a descendant of body
which (due to the space between .b
and :is
) is a descendent of any .b
that is a following sibling of a .a
?
body
is not a descendant of .b
however .d
IS selected and .d
's background-colour is set to chartreuse.
I thought that the selector list inside :is()
or :where()
is relative if it starts with a combinator (e.g. +
, >
, ~
) else it is given an implied descendant combinator.so body .b .c .d
should be matched only if they are descendants of .b
which they're not (.c .d
are but not .b .c .d
nor body .b .c .d
)
<div class="a"></div>
<div class="b">
<div class="c">
<div class="d"></div>
</div>
</div>
.a {--bc: red;}
.b {--bc: green;}
.c {--bc: blue;}
.d {--bc: orange;}
:is(.a,.b,.c,.d) {
aspect-ratio:1;
border: 3px solid var(--bc);
margin: 20px;
width: 100px;
}
.a ~ .b :is(body .b .c .d) /* this colours .d but why? */
/* .a ~ .b :is(.b .c .d) -- so does this */
{
background-color: chartreuse;
}
I tried the above HTML and CSS and was expecting .d
to not be selected however the fact that it is has pulled the "how I think CSS works" rug from under me.
Note: I know the :is
isn't necessary with only one selector list, the CSS that originally started me investigating this does have multiple selector lists inside the :is()
but first I need to understand what is going on with just this one before I can start adding more selectors.
答案1
得分: 3
Your understanding of :is()
isn't 100% correct.
.a ~ .b :is(body .b .c .d)
意味着选择匹配以下选择器的任何元素:
.a ~ .b *
并且也匹配以下选择器:
body .b .c .d
:is()
内部的内容与外部部分无关,这是一个常见的错误,因为你可能将选择器视为:
.a ~ .b :body .b .c .d
但实际上并不是这样。
因此,你将选择任何是.b
的后代且同时也是body .b .c
的后代的.d
元素。
另一个示例以查看差异:
.a > .b > .c {
/* 我会选择 .c 元素 */
}
.a > :is(.b > .c) {
/* 我将选择为空! */
}
这两个选择器不相同。第二个意味着选择任何是.a
的直接后代且同时也是.b
的直接后代的.c
元素。
更多详细信息,请参阅:https://www.bram.us/2023/01/17/using-is-in-complex-selectors-selects-more-than-you-might-initially-think/
英文:
Your understanding of :is()
isn't 100% correct.
.a ~ .b :is(body .b .c .d)
means select any element that match the selector
.a ~ .b *
AND also match the selector
body .b .c .d
What is inside the :is()
has no relation with the outside part and this is a common mistake that everyone make because you see the selector as:
.a ~ .b :body .b .c .d
But it's not.
So you will select any .d
element that is a descendant of .b
and also a descendant of body .b .c
Another example to see the difference:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
.a > .b > .c {
/* I will select the .c element */
}
.a > :is(.b > .c) {
/* I will select nothing! */
}
<!-- language: lang-html -->
<div class="a">
<div class="b">
<div class="c">
</div>
</div>
</div>
Both selectors aren't the same. The second one means select any direct descendant of .a
that is a .c
element and a direct descendant of .b
.
A good reading for more detail: https://www.bram.us/2023/01/17/using-is-in-complex-selectors-selects-more-than-you-might-initially-think/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论