【问题标题】:Selecting a class and first 3 of the rest; nth-child and nth-of-type useless选择一个类和其余的前 3 个; nth-child 和 nth-of-type 没用
【发布时间】:2012-01-27 17:26:25
【问题描述】:

我有一个带有多个子元素的 DOM 元素 (#installations),其中只有一个具有 .selected 类。我需要选择这个类和其余的前 3 个(:not(.selected))并显示它们 - 目标是只显示 4 个元素,无论哪个元素具有 .selected 类。

问题在于,在表达式中:

#installations > *:not(.selected):nth-of-type(-n+3), .selected

:nth-of-type() 忽略 :not() 选择器,只选择#installation 的前 3 个子项。例如,如果我有这个 HTML:

<div id="installations">
    <div id="one"/>
    <div id="two"/>
    <div id="three" class="selected"/>
    <div id="four"/>
    <div id="five"/>
</div>

我只会选择一个、两个、三个而不是前四个。逻辑含义是 :nth-of-type() 将只有 (一、二、四、五) 可供选择,因为 :not() 已经排除了选定的一个,因此选择了 (一、二、四),然后选择器, .selected 的另一部分将添加所选元素。

如果 .selected 不在前四个元素中,假设它是第六个,我们将选择前三个 + 第六个元素。

澄清一下:选择 .selected 加上 3 个相邻元素也可以。但是,如果 .selected 在最后 3 个中(如果我们选择接下来的 3 个相邻元素),这也很困难

【问题讨论】:

  • 伪类不按顺序处理;他们都在你的每一个元素上一起评估。有关详细信息,请参阅 this answer(也包括 :not())。在您的情况下,:not(.selected):nth-of-type(-n+3) 选择前两个元素(第三个是 .selected),.selected 选择第三个。
  • 这就是问题所在。如果我能在选择器的第一部分(在第一个伪类之前)排除 .selected 就好了。或者,我可以在所有其他元素上放置一个“.unselected”类,但我希望有一个更清洁的解决方案。

标签: html css css-selectors


【解决方案1】:

正如我在评论中提到的,伪类不是按顺序处理的;他们都在你的每一个元素上一起评估。详情请见this answer

经过一番修改,考虑到您的 HTML 和选择元素的条件,我想出了以下 long 选择器列表:

/* The first three children will always be selected at minimum */
#installations > div:nth-child(-n+3),
/* Select .selected if it's not among the first three children */
#installations > div.selected,
/* If .selected is among the first three children, select the fourth */
#installations > div.selected:nth-child(-n+3) ~ div:nth-child(4)

为此,必须做出一个简单的假设:selected 类一次只会出现在一个元素上。

您需要在同一规则中组合所有三个选择器,以匹配您要查找的四个元素。注意我的代码中的逗号。

Interactive jsFiddle demo(用于测试选择器与不同子元素中的类)


不管怎样,如果您可以回退到 JavaScript,那就更容易了。举个例子,如果你使用 jQuery,它的:lt() selector 会让事情变得简单一些:

// Apply styles using this selector instead: #installations > div.with-jquery
$('#installations')
    .children('div.selected, div:not(.selected):lt(3)')
    .addClass('with-jquery');

Interactive jsFiddle demo(忽略此演示中的 JS 代码,它只是为了使其具有交互性)

【讨论】:

  • 是的,正是我想要的。谢谢。
  • @Ivo:没问题。假设我需要一个谜题来破解我的脑袋:)
【解决方案2】:

您需要使用的是相邻的兄弟选择器。这是我在 Safari 中编写的一个示例(未在其他地方测试)。仅显示“二”、“三”和“四”项。

<!DOCTYPE html>
<html>
  <head>
    <style>
      .the-list li {display:none;}
      .the-list li.selected {display:block;}
      .the-list li.selected + li {display:block;}
      .the-list li.selected + li + li {display:block;}
    </style>
  </head>
  <body>
    <ol class='the-list'>
      <li>One</li>
      <li class='selected'>Two</li>
      <li>Three</li>
      <li>Four</li>
      <li>Five</li>
      <li>Six</li>
    </ol>
  </body>
</html>

【讨论】:

  • 每个浏览器都支持相邻的兄弟选择器,尽管有业务需求(阅读:IE6 除外)。
  • 等一下,OP希望前三个+被选中,除非选中的是前三个,在这种情况下它会跳过它并选择它周围的其他三个元素?
  • 如果最后一个元素具有类“.selected”,则只会显示它。也不行。
  • 是的 - 看起来我没有足够彻底地阅读原始问题。在某种程度的复杂性下,单独的 CSS 不再是完成这项工作的好工具。我认为为此使用一些 JavaScript 会消除很多痛苦。即使你想出了一个可行的 CSS 规则,如果它的代码几乎是不可理解的,那么下次你必须维护它时会发生什么?
  • @Steve Jorgensen:你说得对,使用 JS 会省去很多痛苦。请参阅我的更新答案。它只是碰巧在这种情况下存在 CSS 解决方案......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2013-11-20
  • 1970-01-01
  • 2013-04-04
  • 2016-12-12
  • 1970-01-01
  • 2015-12-20
相关资源
最近更新 更多