【问题标题】:Selector for element having one of two classes, but not both具有两个类之一但不是两者的元素的选择器
【发布时间】:2021-11-15 17:32:53
【问题描述】:

如何选择具有两个类之一但不能同时具有两个类的元素?

我尝试了:not(.class1, .class2):not(.class1):not(.class2),但它们似乎选择了缺少任一类的元素。我需要选择没有 both 类的元素。

我也试过:not([class='class1 class2'])as this accepted answer states,但似乎没有选择任何东西。

这是我想要的样本 -

ul.tabs > li.active:not([class='first last']) {
    background-color: #F00;
}
<ul class="tabs">
    <li class="first">1st</li>
    <li class="active last">2nd</li> <!-- Should be red -->
</ul>

<ul class="tabs">
    <li class="active first last">1st</li> <!-- Should NOT be red -->
</ul>

&lt;li&gt; 的其他课程我不负责。我想知道是否有办法忽略我尝试的最后一个选择器的其他类。

【问题讨论】:

  • :not(.class1):not(.class2) 完美运行
  • :not(.class1):not(.class2) 不起作用。它选择缺少至少一个类的元素,而不是两者。在第一个示例中意味着第二个选项卡不是红色的。为什么投反对票?
  • 我不认为 css :not() 在这里工作 jsfiddle.net/d9bk9m04
  • 我不知道,我没有投反对票,但现在我有点困惑。那 li.active.last 并没有错过这两个类 - 因为它确实有“最后一个”类。如前所述, :not(.first):not(.last) 将匹配没有任何类的元素。但这根本不是您想要的。
  • @BoltClock 我希望
  • 只要它有类 active 而不是 firstlast.

标签: css css-selectors


【解决方案1】:

您想要:not(.first), :not(.last),它是:not(.first.last) 的Selectors level 3 支持版本(来自Selectors 4,尚未被所有浏览器以及jQuery 支持):

ul.tabs > li.active:not(.first), ul.tabs > li.active:not(.last) {
    background-color: #F00;
}
<ul class="tabs">
    <li class="first">1st</li>
    <li class="active last">2nd</li>
</ul>

<ul class="tabs">
    <li class="active first last">1st</li>
</ul>

不过,正如 Rounin 指出的那样,您应该能够只使用 :first-of-type:last-of-type,或 :first-child:last-child,而不是使用“first”和“last”类来膨胀标记(如果这些类代表与伪类相同的东西)。

事实上,如果你确实切换到那些伪类,你可以通过将 :not(:first-of-type), :not(:last-of-type) 压缩到 :not(:only-of-type) 来将你的 CSS 简化为一个选择器:

ul.tabs > li.active:not(:only-of-type) {
    background-color: #F00;
}
<ul class="tabs">
    <li>1st</li>
    <li class="active">2nd</li>
</ul>

<ul class="tabs">
    <li class="active">1st</li>
</ul>

【讨论】:

    【解决方案2】:

    在这种情况下,你可以使用两个 CSS 伪类:

    • :first-of-type
    • :last-of-type

    并利用 CSS 级联,通过在 :last-of-type 的规则下方声明 :first-of-type 的规则。

    工作示例:

    .tabs li:last-of-type.active {background-color: rgb(255, 0, 0);}
    .tabs li:first-of-type.active {background-color: transparent;}
    <ul class="tabs">
    <li>1st</li>
    <li class="active">2nd</li> <!-- Should be red -->
    </ul>
    
    <ul class="tabs">
    <li class="active">1st</li> <!-- Should NOT be red -->
    </ul>

    【讨论】:

      【解决方案3】:

      如何使用 CSS 选择器选择具有两个类之一的 html 元素,但不能同时选择这两个类

      或者如何在 CSS 选择器中进行异或操作

      你需要的是XOR - Exclusive or

      独占 or 是一种逻辑运算,当且仅当其参数不同时(一个为真,另一个为假)。

      异或

      Input A Input B Outcome Q
      0 0 0
      0 1 1
      1 0 1
      1 1 0

      不幸的是,CSS 中没有 XOR 运算符,这使得这有点棘手。 但是我们有两个 AND ant NOT,这两个一起得到了我们 NAND(不是 AND)。 NAND 最酷的地方在于可以combine NAND to express any Boolean expression

      所以我们需要 XOR,可以像这样用 NAND 实现

      XOR = (A 与非 (A NAND B)) 与非 (B 与非 (A NAND B))

      假设 A = 首先是 CSS 类,B = 最后是 CSS 类,然后我们得到:

      li.active:not(:not(.first:not(.first.last)):not(.last:not(.first.last)))
      {
          background-color: #F00;
      }
      <ul class="tabs">
          <li class="first">1st</li>
          <li class="active last">2nd</li>
      </ul>
      
      <ul class="tabs">
          <li class="active first last">1st</li>
      </ul>

      让我们分解一下

      1. 在 CSS 中 AND 是通过将两个选择器链接在一起来实现的,因此为了获得 first NAND last 的 CSS 版本,我们执行 :not(.first.last)

      2. 接下来我们需要( first NAND ( first NAND last ) ),我们用:not(.first:not(.first.last))得到它,再次将first与上面第1点的表达式:not(.first.last)链接在一起。这给了我们完整表达式的左边部分。

      3. 表达式的第二部分和右侧部分与左侧部分几乎相同

        Part Expression
        Left ( A NAND ( A NAND B ) )
        Right ( B NAND ( A NAND B ) )

        所以我们需要做的就是将第一个 A 替换为 B,或者在我们的例子中,将第一个 first 替换为 last,这应该给我们表达式的右半部分和后半部分, :not(.last:not(.first.last))

      4. 我们现在需要做的就是将这两个部分加在一起,然后用 NOT 将它们取反。 因此,我们再次将这两个部分链接在一起,从而得到:not(.first:not(.first.last)):not(.last:not(.first.last))。 然后我们添加最后的 NOT 以获得not(:not(.first:not(.first.last)):not(.last:not(.first.last)))。 这就是用 NAND(NOT 和 AND)实现的完整 XOR 表达式。

      5. 最后一步是将整个 XOR 表达式限制为仅具有活动类的 li-tags。 所以我们将它与一个基本的标签+类选择器链接在一起,我们得到了最终结果:li.active:not(:not(.first:not(.first.last)):not(.last:not(.first.last)))

      【讨论】:

      • 大崩溃。选择器 4 现在还引入了 :is(),它实际上是一个不需要复制选择器其余部分的 OR 运算符。由于“A XOR B”也可以表示为“(A OR B) AND (NOT (A AND B))”,因此选择器可以简化为li.active:is(.first, .last):not(.first.last),从而无需任何 NAND。我不知道有任何选择器 3 兼容的解决方案比我回答的那个更简单,尽管级别 4 :not() 和 :is() 在这一点上得到了相当好的支持。
      猜你喜欢
      相关资源
      最近更新 更多
      热门标签