简体   繁体   English

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

[英]Why does the general-sibling combinator allow toggling pseudo-element's content, but not the adjacent-sibling?

In this question " CSS3 Selector That Works like jQuery's .click()? " I posted an answer using the :checked state of an input , of type="checkbox" to toggle the display of an element. 在这个问题“ CSS3选择器,像jQuery的.click()? ”我发布了一个答案使用:checked input :checked状态, type="checkbox"来切换元素的显示。

This is the HTML of the demo I posted in that answer: 这是我在答案中发布的演示的HTML:

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

And the CSS (with transitions stripped for brevity): 和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 . JS小提琴演示

Once I'd posted the answer it occurred to me that we could also toggle the text of the label used to trigger the state-change of that checkbox, using the following selectors (having amended the label 's text to 'navigation'): 有一次,我张贴发生,我认为我们可以切换的文字答案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 . 简化/基本JS小提琴演示

This did not work, in that while the selector matched while the input was in its unchecked state (and the label showed Show navigation ), the selector failed to match when the state of the input changed. 这不起作用,因为当input处于未检查状态时选择器匹配(并且label显示Show navigation ),当input状态发生变化时,选择器无法匹配。 Note that the transitions were still effected on the nav element, and the original matching selector indicates that the next-sibling combinator matched originally. 请注意,转换仍然在nav元素上生效,原始匹配选择器指示下一个兄弟组合器最初匹配。 The above link shows a simplified demo of the not-working (in Chrome 27/Windows XP) selectors. 上面的链接显示了不工作(在Chrome 27 / Windows XP中)选择器的简化演示。

It then occurred to me to try the general-sibling combinator, to reduce the selector-chain. 然后我想到尝试使用通用兄弟组合器来减少选择链。 which resulted in the following CSS (with transitions again stripped for brevity): 这导致了以下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 . JS小提琴演示

Somewhat to my surprise, this worked (the content of the label changed in response to the changed-state of the input ). 令我惊讶的是,这很有效( labelcontent随着input的改变状态而改变)。

So, the question: why does the general-sibling combinator allow for updating of a later-sibling while chained next-sibling combinators (which match the elements and the structure of the DOM) does not? 所以,问题是:为什么通用兄弟组合子允许更新后来的兄弟,而链接的下一个兄弟组合子(匹配DOM的元素和结构)不是?

Further, this does seem to work in Firefox (21, on Windows XP); 此外,这似乎在Firefox(21,在Windows XP)的工作; so I guess the question is altered slightly to include: is this a bug in Chrome/Webkit, or an expected behaviour? 所以我想问题略有改变,包括:这是Chrome / Webkit中的一个错误,还是预期的行为?

And, even further , it seems that while this is a bug in Chrome (thanks @Boltclock), there's a somewhat ludicrous 'do-nothing' animation that fixes the non-working demo (though other, perhaps better, alternatives exist, as Scott's answer shows): 而且, 更进一步 ,似乎虽然这是Chrome中的一个错误(感谢@Boltclock),有一些有点可笑的“无所事事”动画修复了非工作演示(尽管其他可能更好的替代方案存在,如斯科特的答案显示):

body {
    -webkit-animation: bugfix infinite 1s;
}
@-webkit-keyframes bugfix {
    from {
        padding: 0;
    }
    to {
        padding: 0;
    }
}
#switch {
}
#switch + nav {
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}
#switch:checked + nav {
    background-color: #ffa;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}
label {
    display: inline-block;
    cursor: pointer;
}
#switch + nav + label::before {
    content:'Show ';
}
#switch:checked + nav + label::before {
    content:'Hide ';
}

JS Fiddle demo . JS小提琴演示

Note: the reason I'm updating the question with this 'fix,' rather than posting it as an answer, is simply because the question wasn't "how can I fix this?" 注意:我用这个“修复”更新问题的原因,而不是将其作为答案发布,仅仅是因为问题不是 “我该如何解决这个问题?” but (basically) "why doesn't it work?" 但(基本上)“为什么不起作用?”

Bug Work Around Bug工作

Apparently, certain valid pseudo-classes chained together allows it to work. 显然, 链接在一起的 某些有效伪类允许它工作。

These work (see Fiddle #1 , Fiddle #2 , Fiddle #3 ): 这些工作(见小提琴#1小提琴#2小提琴#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

This did not (see Fiddle #4 ): 这没有(见小提琴#4 ):

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

I tried some other :not() combinations, none of which allowed it to work. 我尝试了其他一些:not()组合,没有一个允许它工作。

** Best choice ** ** 最佳选择 **

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

This is a long-standing bug in WebKit browsers related to the use of certain dynamic pseudo-classes with next-sibling combinators. 这是WebKit浏览器中一个长期存在的错误,它与使用具有下一个兄弟组合子的某些动态伪类有关。 This happens whether you're applying styles to the sibling element itself or a pseudo-element of that sibling element. 无论您是将样式应用于兄弟元素本身还是应用该兄弟元素的伪元素,都会发生这种情况。

I don't know if anybody has filed a bug report yet, but this has been seen rather frequently on the site: 我不知道是否有人提交了错误报告,但网站上经常出现这种情况:

Strangely it was also reported that Chrome had issues with the general sibling combinator, but as you note it works in your given scenario: 奇怪的是,据报道,Chrome与普通兄弟组合器存在问题,但正如您所指出的那样,它适用于您的特定情况:

So either that was fixed, or something else triggers/triggered it. 所以要么修复了,要么触发/触发它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM