如何让nth-child选择器跳过隐藏的div

31
我有几个随机块。每当块落在新行中时,我都会让它看起来不同。当用户点击按钮时,我通过 display:none 隐藏几个块,此时问题就出现了。 nth-child 选择器也会计算隐藏的元素。
是否有办法忽略那些特定的块,使得每一行再次具有不同的样式? 这是类似场景的一个示例。

$('.hide-others').click(function () {
    $('.css--all-photo').toggleClass('hidden');
})
.board-item--inner {
    height:200px;
    background:tomato;
    text-align:center;
    color:#fff;
    font-size:33px;
    margin-bottom:15px;
    border:2px solid tomato;
}
@media (min-width:768px) and (max-width:991px) {
    .board-item:nth-child(2n+1) .board-item--inner {
        border:2px solid #000;
        background:yellow;
        color:#000;
    }
}
@media (min-width:992px) and (max-width:1199px) {
  .board-item:nth-child(3n+1) .board-item--inner {
    border:2px solid #000;
    background:yellow;
    color:#000;
  }
}
@media (min-width:1200px) {
  .board-item:nth-child(4n+1) .board-item--inner {
    border:2px solid #000;
    background:yellow;
    color:#000;
  } 
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
    <div class="form-group">
        <button class="btn btn-info hide-others" type="button">Hide others</button>
    </div>
    <div class="row">
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">1</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">2</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">3</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">4</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">5</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">6</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">7</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">8</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">9</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">0</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">10</div>
        </div>
    </div>
    <div>

仅需查看代码片段或外部FIDDLE,您就可以理解我的问题。

我特别要求一个纯CSS的解决方案。 请为您的答案提供一个FIDDLE! 我不能永久删除这些块,我的用户有通过按钮点击来过滤文件的选项,这就是隐藏和显示的情况。


你可以像这样尝试使用伪类选择器 **.this-class:not(:nth-child(1)){}**。 - CodeRomeos
@CodeRomeos 我自己尝试了一下,但它没有起作用,所以正在等待有人展示一个可行的演示。 - Deepak Yadav
1
只需将用户ID用作类名...并将该类作为目标来切换可见性。 - Leo Javier
2
不好意思...我错了。:nth-of-type:nth-child将会计算所有相同类型的元素,无论它们是否隐藏。也许没有纯CSS的解决方案来解决这个问题。 - CaldwellYSR
1
我尝试了.board-item:not(.hidden):nth-of-type(count) .board-item--inner,但也没有起作用。 - Bmd
显示剩余16条评论
4个回答

28
当用户点击一个按钮时,我通过 display:none 隐藏了几个块,并且出现了问题。 nth-child 选择器也会计算隐藏的元素。
有没有办法忽略这些特定的块,使得每一行都有不同的样式?
问题在于 nth-child() 选择器查看同一父级下的所有兄弟节点,而不考虑样式。即使你应用了 display: none ,因为 CSS 不会将元素从 DOM 中删除,因此它仍然是一个兄弟节点。
从规范中可以看出:

6.6.5.2. :nth-child() 伪类

:nth-child(an+b) 伪类符号表示文档树中在它之前有 an+b-1 个兄弟元素,其中 n 是任何正整数或零,且具有父元素。 (强调是我的)

为了让您声明的nth-child规则在用户点击隐藏div后仍然有效,您需要从DOM中删除隐藏的divs,使它们不再作为兄弟元素存在。
在您的问题中,您要求使用CSS-only解决方案。但在您的评论中,您表示HTML是可以更改的。您还使用了一些jQuery来隐藏元素。
只需添加一行小代码到您的jQuery中,问题就可以得到解决:
$('.hidden').remove();

.remove() 方法 将元素(包括其子元素)从 DOM 中移除。在这种情况下,它会删除所有带有 hidden 类的元素。


更正

remove() 方法的问题在于使用该方法从 DOM 中获取的元素无法恢复,这会破坏切换功能。

幸运的是,jQuery 提供了一种替代方法:detach()

.detach() 方法与 .remove() 方法相同,但是 .detach() 会保留与删除元素相关联的所有 jQuery 数据。当需要在稍后的时间重新插入已删除的元素时,此方法非常有用。

因此,如果我们替换原始代码...

$('.hide-others').click(function () {
    $('.css--all-photo').toggleClass('hidden');
})

...使用此代码...

var divs;

$('.photos-board-item').each(function(i){
    $(this).data('initial-index', i);
});

$('.hide-others').on('click', function () {
    if(divs) {
        $(divs).appendTo('.row').each(function(){
            var oldIndex = $(this).data('initial-index');
            $('.photos-board-item').eq(oldIndex).before(this);
        });
        divs = null;
    } else {
        divs = $('.css--all-photo').detach();
    }
});

...网格按预期工作。(代码来源: @JosephMarikle)

演示

现在,无论隐藏了哪些div或有多少个,它们都可以被切换开关而不会破坏视觉设计,因为nth-child选择器仅计算“可见”的同级元素。CSS没有更改。HTML没有更改。


2

我会使用:nth-of-type选择器和对你的切换函数进行小修改来完成这个任务。

基本思路是不要从DOM中删除那些.css--all-photo元素,而是将它们包装在<hidden>容器中。然后使用unwrap()来恢复完整集合。在这种情况下,:nth-of-type将完全做到你使用:nth-child所做的事情。

var state = false;

$('.hide-others').click(function () {
    if( !state ) {
      $('.css--all-photo').wrap('<hidden>');
      state = true;
    } else {
      $('hidden').unwrap();
      state = false;
    }
})
hidden { display:none; } 

.board-item--inner {
    height:200px;
    background:tomato;
    text-align:center;
    color:#fff;
    font-size:33px;
    margin-bottom:15px;
    border:2px solid tomato;
}
@media (min-width:768px) and (max-width:991px) {
    div.board-item:nth-of-type(2n+1) .board-item--inner {
        border:2px solid #000;
        background:yellow;
        color:#000;
    }
}
@media (min-width:992px) and (max-width:1199px) {
  div.board-item:nth-of-type(3n+1) .board-item--inner {
    border:2px solid #000;
    background:yellow;
    color:#000;
  }
}
@media (min-width:1200px) {
  div.board-item:nth-of-type(4n+1) .board-item--inner {
    border:2px solid #000;
    background:yellow;
    color:#000;
  } 
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
    <div class="form-group">
        <button class="btn btn-info hide-others" type="button">Hide others</button>
    </div>
    <div class="row">
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">1</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">2</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">3</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">4</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">5</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">6</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">7</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item css--all-photo">
            <div class="board-item--inner">8</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">9</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">0</div>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 board-item photos-board-item">
            <div class="board-item--inner">10</div>
        </div>
    </div>
    <div>


0
你需要的是 nth-of-class,但不幸的是这个函数不存在!当你使用 JS 切换隐藏类时,隐藏和显示子元素之间唯一的区别就是这一点。所以你需要告诉 CSS 计算某个类别的 div 元素(比如 "shown"),但不幸的是,CSS 的 nth-child 选择器并不关心子元素的类别。你可以在这里阅读更多内容。

-2

这里是我所说的一个例子:https://jsfiddle.net/happy2deepak/g7gL5zfb/4/ 在这种情况下,它将忽略具有类.css--all-photo的元素...但您可以使用任何要忽略的类。

$('.hide-others').click(function () {
    $('.user-a').not('.css--all-photo').toggleClass('hidden');
})

谢谢Leo,但我不认为你理解我的问题!我的问题不在于隐藏或显示块,而是如果我使用display:none隐藏一些元素,nth-child(count)也会计算隐藏的元素,这会破坏CSS给出的样式并导致布局问题。因此,我正在寻找一种方法来防止这种情况发生。 - Deepak Yadav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接