为什么通用兄弟组合器允许切换伪元素的内容,而不是相邻的兄弟?

时间:2013-06-20 16:48:14

标签: html css css-selectors

在此问题“CSS3 Selector That Works like jQuery's .click()?posted an answer:checked使用input的{​​{1}}状态type="checkbox"来切换元素的显示。< / p>

这是我在答案中发布的演示的HTML:

<input type="checkbox" id="switch" />
<nav>
    <h2>This would be the 'navigation' element.</h2>
</nav>
<label for="switch">Toggle navigation</label>

CSS(为了简洁而剥离了转换):

#switch {
    display: none;
}
#switch + nav {
    height: 0;
    overflow: hidden;
    /* transitions followed */
}
#switch:checked + nav {
    height: 4em;
    color: #000;
    background-color: #ffa;
    /* transitions followed */
}

label {
    cursor: pointer;
}

JS Fiddle demo

在我发布答案后,我发现我们可以切换用于触发该复选框状态更改的label文本,使用以下选择器(已将label的文本修改为“导航”):

label {
    display: inline-block;
    cursor: pointer;
}

#switch + nav + label::before {
    content: 'Show ';
}

#switch:checked + nav + label::before {
    content: 'Hide ';
}

Simplified/basic JS Fiddle demo

这不起作用,因为当input处于未选中状态且label显示Show navigation时)选择器匹配时,选择器失败匹配input的状态发生变化时。请注意,转换仍然在nav元素上生效,原始匹配选择器指示下一个兄弟组合器最初匹配。上面的链接显示了不工作(在Chrome 27 / Windows XP中)选择器的简化演示。

然后我尝试使用通用兄弟组合器来减少选择链。这导致了以下CSS(为简洁而再次剥离转换):

#switch:checked + nav {
    background-color: #ffa;
}

label {
    display: inline-block;
    cursor: pointer;
}

#switch ~ label::before {
    content: 'Show ';
}

#switch:checked ~ label::before {
    content: 'Hide ';
}

JS Fiddle demo

令我惊讶的是,这很有效(content的{​​{1}}已更改,以响应label的更改状态。

所以,问题是:为什么通用兄弟组合子允许更新后来的兄弟,而链接的下一个同胞组合子(与DOM的元素和结构匹配)不会?

此外, 似乎适用于Firefox(21,在Windows XP上);所以我想问题稍有改动,包括:这是Chrome / Webkit中的一个错误,还是预期的行为?

而且,即使进一步,似乎虽然这是Chrome中的一个错误(感谢@Boltclock),但是有一些可笑的'do-nothing' animation修复了非工作的演示(尽管其他或许更好的替代品存在,正如斯科特的答案所示:)

input

JS Fiddle demo

注意:我使用此“修正”更新问题的原因,而不是将其作为答案发布,仅仅是因为问题不是“我怎样才能解决这个问题?”但(基本上)“为什么不起作用?”

2 个答案:

答案 0 :(得分:16)

Bug解决方法

显然,某些有效的伪类链接在一起允许它工作。

这些工作(见Fiddle #1Fiddle #2Fiddle #3):

#switch:checked + nav:only-of-type + label::before
#switch:checked + nav:nth-of-type(1) + label::before
#switch:checked + nav:nth-child(2) + label::before

这没有(见Fiddle #4):

#switch:checked + nav:not([class]) + label::before

我尝试了其他一些:not()组合,其中没有一个允许它起作用。

** Best choice **

#switch:checked + nav:nth-child(n) + label::before

答案 1 :(得分:9)

这是WebKit浏览器中一个长期存在的错误,与使用具有下一个兄弟组合子的某些动态伪类有关。无论您是将样式应用于兄弟元素本身还是应用该兄弟元素的伪元素,都会发生这种情况。

我不知道是否有人提交了错误报告,但网站上经常出现这种情况:

奇怪的是,据报道,Chrome与普通兄弟组合器存在问题,但正如您所说,它适用于您的特定场景:

所以要么修复了,要么触发/触发它。