10

在这个问题“ CSS3 Selector That Works like jQuery's .click()? ”中,我使用 , of 的状态发布了一个答案,用于切换元素的显示。:checkedinputtype="checkbox"

这是我在该答案中发布的演示的 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 小提琴演示

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

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

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

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

简化/基本 JS Fiddle 演示

This did not work, in that while the selector matched while the inputwas in its unchecked state (and the labelshowed Show navigation), the selector failed to match when the state of the inputchanged. 请注意,转换仍然对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 小提琴演示

令我惊讶的是,这奏效了(改变contentlabel改变状态以响应改变的状态input)。

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

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

而且,更进一步,虽然这是 Chrome 中的一个错误(感谢@Boltclock),但有一个有点可笑的“无所事事”动画修复了非工作演示(尽管存在其他可能更好的替代方案,如 Scott 的答案显示):

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 小提琴演示

注意:我之所以用这个“修复”更新问题,而不是将其作为答案发布,仅仅是因为问题不是“我该如何解决这个问题?” 但是(基本上)“为什么它不起作用?”

4

2 回答 2

16

错误解决

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

这些工作(见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()的组合,但没有一个允许它工作。

**最佳选择**

#switch:checked + nav:nth-child(n) + label::before
于 2013-06-20T17:34:57.940 回答
9

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

我不知道是否有人提交了错误报告,但这在网站上经常看到:

奇怪的是,还报告说 Chrome 与通用兄弟组合器存在问题,但正如您所注意到的,它在您的给定场景中有效:

所以要么是固定的,要么是其他东西触发/触发了它。

于 2013-06-20T17:06:58.783 回答