选择最后一个连续的兄弟

Posted

技术标签:

【中文标题】选择最后一个连续的兄弟【英文标题】:Selecting last consecutive sibling 【发布时间】:2014-04-30 05:14:58 【问题描述】:

如何选择相邻元素序列中的最后一个元素?

考虑以下标记:

HTML

<ul>
    <li class="foo">...</li>
    <li class="foo">...</li>
    <li class="foo">...</li> <!-- bingo -->

    <li class="bar">...</li>
    <li class="bar">...</li>
    <li class="bar">...</li>
    <li class="bar">...</li> <!-- bingo -->

    <li class="foo">...</li> <!-- bingo -->

    <li class="bar">...</li>
    <li class="bar">...</li> <!-- bingo -->
</ul>

连续的foobar 元素的数量是动态的。另外,假设不能以任何方式修改标记。

选择相邻元素非常简单:

CSS

.foo + .foo, 
.bar + .bar  /* do something */ 

但是选择一系列连续元素中的最后一个元素,这可能吗?

【问题讨论】:

不,你需要javascript。 css 可以做 .foo + .bar 或 :last-of-type @HashemQolami 我想不同的课程是唯一的方法。 @HashemQolami - 听起来好像无法避免修改标记。也许添加一个类是侵入性最小的选择。 问这个问题已经过去几年了。是否有任何新的选择器添加到可以处理这种情况的 css 规范中? 【参考方案1】:

:has 的 CSS 支持仍然很差,但可以解决问题:

/* selects any .foo that has no .foo immediately after it  */
.foo:has(+ :not(.foo)) 

【讨论】:

这绝对是非常有前途的,只要它有任何支持的孩子!当时,只有 Safari Technology Preview 是支持它的浏览器,它是 0%:caniuse.com/css-has 我会支持你的答案,但是在我验证它是否有效之前不能选择它作为答案:) 非常狡猾的发现!【参考方案2】:

您必须动态设置列表....在这种情况下,为最后一个元素指定名称或 id 并添加您想要的 css 效果....

除非您有某种方式可以识别最后一个元素(可能是 id 或名称,如果您可以控制,请再次设置),否则您的要求是不可能的。

【讨论】:

我希望有某种方法可以组合选择器,以便 .foo + .foo 可以与 last-child 组合 - 但我想真的没有办法做到这一点(或者也许永远)。【参考方案3】:

我不相信有办法在不改变 html 或生成它的方式的情况下做到这一点。但是,如果您通过.append() 方法生成它,那么使用它(理论上)只需将其更改为.prepend()。如果你这样做,你可以改变 ul 的 css 让它向后选择,然后你可以像这样使用 + 选择器:

(编辑:我不知道如何重新排序 sn-p,但 JS 是最不重要的,只有当你想看到 .prepend() 的实际作用时才在那里)

//some generation examples just for fun

foo.addEventListener('click',addKnown);
bar.addEventListener('click',addKnown);
r.addEventListener('click',addRandom);

function addKnown(e) 
  let li = document.createElement('li');
  li.className = e.target.id;
  li.textContent = e.target.id;
  document.querySelector('ul').prepend(li);

function addRandom(e) 
  let li = document.createElement('li');
  let type = ['foo','bar'][Math.round(Math.random())];
  li.className = type;
  li.textContent = type;
  document.querySelector('ul').prepend(li);
 
ul 
  display: flex;
  flex-direction: column-reverse;


li:first-of-type,
.foo+.bar,
.bar+.foo 
  color: red
<ul>
  <li class="bar">bar</li> <!-- bingo -->
  <li class="bar">bar</li>

  <li class="foo">foo</li> <!-- bingo -->

  <li class="bar">bar</li> <!-- bingo -->
  <li class="bar">bar</li>
  <li class="bar">bar</li>
  <li class="bar">bar</li>

  <li class="foo">foo</li> <!-- bingo -->
  <li class="foo">foo</li>
  <li class="foo">foo</li>
</ul>

<!-- some generation examples just for fun-->
<button id="foo">Add foo</button>
<button id="bar">Add bar</button>
<button id="r">Add random</button>

我还建议为 ul 提供某种类或 id,除非您只有一个或希望页面上的所有 ul 都是这种情况。

很抱歉,我知道这不是您想要的(因为它在技术上确实会通过将标记倒退来更改标记),但我希望它至少是可能的或有助于找到合适的东西。

【讨论】:

【参考方案4】:

似乎有一个 nth-last-child 选择器:

http://css-tricks.com/almanac/selectors/n/nth-last-child/

您应该能够将它与零参数一起使用以获取最后一个

编辑:nth-​​last-child 确实会选择最后一个与宾果游戏不匹配的孩子

希望你能改变结构:

<ul>
   <ul>
       <li class="foo">foo 1</li>
       <li class="foo">foo 2</li>
       <li class="foo">foo 3 bingo</li>
   </ul>
   <ul>
       <li class="bar">bar 1</li>
       <li class="bar">bar 2</li>
       <li class="bar">bar 3</li>
       <li class="bar">bar 4 bingo</li>
    </ul>
    <ul>
       <li class="foo">foo 1</li>
       <li class="foo">foo 2 bingo</li>
    </ul>
</ul>

这个css可以工作:

.foo:nth-last-child(1),
.bar:nth-last-child(1)

    background-color: blue;

【讨论】:

要获得最后一个元素,last-child 就足够了 - 但这仍然不能解决在连续的一系列兄弟元素中选择最后一个匹配元素的问题(请参阅标记中的宾果游戏标记)。 真正的技术恐惧症,错过了。也许它不能回答你的问题,但如果你可以改变无序列表的结构,那么它就会起作用。 (将来可能对其他人有所帮助) 我假设,根据 OP 所说的,它是动态的,他们一次添加一个 lis 一个类或另一个类,不知道他们会在列表中的哪个位置在那个时候。如果是这样的话,这将是一个巨大的麻烦。

以上是关于选择最后一个连续的兄弟的主要内容,如果未能解决你的问题,请参考以下文章

如何连续选择第一个和最后一个TD?

如何连续选择第一个和最后一个TD?

[ jquery 位置选择器 :first-child :last-child ] 强化说明:选取属于其父元素和所有兄弟元素中子元素集合中处于第一个(最后一个)位置上符合条件的元素

点击事件和选择器

jquery如何获取某一个兄弟节点,不是全部的,是指定的兄弟节点

求解css相邻兄弟选择器该怎么去理解