【问题标题】:Why does the general-sibling combinator allow toggling pseudo-element's content, but not the adjacent-sibling?为什么通用兄弟组合器允许切换伪元素的内容,而不是相邻兄弟?
【发布时间】:2013-06-17 15:26:06
【问题描述】:

在这个问题“CSS3 Selector That Works like jQuery's .click()?”中,我posted an answer 使用input:checked 状态,type="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 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 987654366的选择器(和label 987654338 @),选择器失败 em>以匹配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.

令我惊讶的是,这有效(labelcontent 响应 input 的更改状态而更改)。

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

此外,这确实似乎可以在 Firefox(21,在 Windows XP 上)中工作;所以我猜这个问题会稍微改变一下,包括:这是 Chrome/Webkit 中的错误,还是预期的行为?

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

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.

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

【问题讨论】:

    标签: html css css-selectors


    【解决方案1】:

    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
    

    【讨论】:

    • :nth-child(n) 有效吗?如果是这样,那是最好的选择,因为它是有保证的匹配(嗯,技术上等同于 :not(:root),但根元素在这里无关紧要)。
    • 你的回答让我想起了this
    • 是的!我正在寻找一个“有保证的”匹配想法,这确实有效!
    • @Scott:我赞成,因为这真的很棒!但是我将按原样保留已接受的答案,因为解决方法不是问题本身(例如,对于另一种解决方法,请参见问题本身);但说真的:要走的路! =)
    • 是的,我没想到你会改变你接受的答案,因为它实际上是一个错误。但我确实觉得这对其他人有用。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 呃,我需要学习如何有效地搜索 Webkit 错误。
    • 别担心,他们很难故意找到。您只需要在工作时遇到它们。
    • 谢谢!而且,突然之间,我不知道该为 Opera 转向 Webkit 感到高兴(他们可能会修复错误)还是谨慎(他们可能会采用新的、令人沮丧的旧错误)。
    • 我们只需要相信 Opera 的优秀人才。 Presto 是一个很棒的引擎,在很多事情上都比 WebKit 做得更好,所以要么他们设法修补,要么我们基本上被淹没了。
    • 你应该知道,在这一点上,我对 WebKit 以及 Trident 和 Gecko 有极大的偏见:PI 特别赞赏微软将 IE8 重点放在 CSS2.1 合规性上的策略——它确实展示了,并提供了粗略的技术演示就像 Chrome 一样。
    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 2022-01-21
    相关资源
    最近更新 更多