如何将nth-child样式应用于过滤后的一组div?

4

预期行为

对容器中每个可见的第三个子div应用样式(即1、3、5、7等),使用:

.card:nth-child(2n+1) {
    margin-right: 20px !important;
    background: pink; 
} 

实际行为

nth-child 样式应用于所有子 div,无论其是否可见(这是已知的行为)。

场景

一个包含子 div 的容器,在输入关键字时对其进行筛选。

enter image description here

在筛选后,nth-child 样式被应用于所有子 div,而不仅仅是可见的 div。

enter image description here
我尝试过的方法

下面链接中的答案提供了一个类似问题的解决方案,利用了 detach(),但我无法弄清楚如何在每次 keyup 筛选后动态重新插入分离的元素(并且不确定这是否是最佳方法)。

https://dev59.com/yFwY5IYBdhLWcg3wq5Qd#32380418

jsFiddle: 链接

$(document).on("keyup", ".my_input", function() {
  var input_val = $(this).val();
  var input_length = input_val.length;
  // minimum 2 chars for search
  if (input_length > 2) {
    filter_cards(input_val);
  } else if (input_length <= 2) {
    $(".card").show();
    // remove matched text styling
    // see: https://dev59.com/a2855IYBdhLWcg3woV7M#4232971
    $('span.matched_text').contents().unwrap();
  }
});

// filter function
function filter_cards(input_val) {

  // iterate over each card
  $(".card").each(function() {

    var match_counter = 0;

    // instance of card
    var $card = $(this);

    var text = $card.text();

    var exists_in_string =
      text.toLowerCase().indexOf(input_val.toLowerCase()) !== -1;

    if (exists_in_string === false) {
      $card.html(text);
    } else if (exists_in_string === true) {
      match_counter += 1;
      var reg = new RegExp(input_val, 'i');
      $card.html(text.replace(reg, '<span class="matched_text">$&</span>'));
    }

    if (match_counter > 0) {
      $card.show();
    } else {
      $card.hide();
    }
  });
}
* {
  box-sizing: border-box;
}

.my_input {
  width: 100%;
  font-size: 48px;
  margin-bottom: 20px;
}

.my_cards {
  display: flex;
  flex-wrap: wrap;
}

.card {
  width: calc(50% - 10px);
  font-size: 38px;
  border: 1px solid #000;
  margin-bottom: 30px;
}


/* add margin on child divs 1,3,5,7 etc */

.card:nth-child(2n+1) {
  margin-right: 20px !important;
  background: pink;
}

.matched_text {
  background: green;
  color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="my_input" placeholder="search for hello, min 2 chars...">

<div class="my_cards">

  <div class="card" data-initial_index="0">
    01 - apples and hello
  </div>

  <div class="card" data-initial_index="1">
    02 - oranges and hello
  </div>

  <div class="card" data-initial_index="2">
    03 - bananas
  </div>

  <div class="card" data-initial_index="3">
    04 - passionfruits and hello
  </div>

  <div class="card" data-initial_index="4">
    05 - mangos and hello
  </div>

  <div class="card" data-initial_index="5">
    06 - limes and hello
  </div>


</div>


2
这个分离解决方案似乎过于复杂了。我会选择 https://api.jquery.com/visible-selector/,然后添加/删除一个类来突出显示该集合中的每三个项目。 - misorude
我在三个地方添加了以下for循环:1)在内容加载时 2)如果输入少于2个字符(重置界面)的keyup处理程序内部,以及3)在filter_cards函数的末尾:$(“.card:visible”).each(function(index){ //如果是奇数 if((index + 1)%2 === 1){$(this).addClass(“odd_div_styling”);} else {$(this).removeClass(“odd_div_styling”);} }); 看起来可以工作:https://jsfiddle.net/rwone/29suzbw3/1/ 随意发布为答案。 - user1063287
1个回答

3
你可以尝试结合 visibleodd/even 伪选择器来改变你的 CSS 样式:
$('.card:visible:even').css({ 'background': 'pink'});
$('.card:visible:odd').css({ 'background': 'white'});

$(document).on("keyup", ".my_input", function() {
  var input_val = $(this).val();
  var input_length = input_val.length;
  // minimum 2 chars for search
  if (input_length > 2) {
    filter_cards(input_val);
  } else if (input_length <= 2) {
    $(".card").show();
    // remove matched text styling
    // see: https://dev59.com/a2855IYBdhLWcg3woV7M#4232971
    $('span.matched_text').contents().unwrap();
  }
  $('.card:visible:even').css({ 'background': 'pink','marginRight':'20px'});
  $('.card:visible:odd').css({ 'background': 'white','marginRight':0});
});

// filter function
function filter_cards(input_val) {

  // iterate over each card
  $(".card").each(function() {

    var match_counter = 0;

    // instance of card
    var $card = $(this);

    var text = $card.text();

    var exists_in_string =
      text.toLowerCase().indexOf(input_val.toLowerCase()) !== -1;

    if (exists_in_string === false) {
      $card.html(text);
    } else if (exists_in_string === true) {
      match_counter += 1;
      var reg = new RegExp(input_val, 'i');
      $card.html(text.replace(reg, '<span class="matched_text">$&</span>'));
    }

    if (match_counter > 0) {
      $card.show();
    } else {
      $card.hide();
    }
 
  });
}
* {
  box-sizing: border-box;
}

.my_input {
  width: 100%;
  font-size: 48px;
  margin-bottom: 20px;
}

.my_cards {
  display: flex;
  flex-wrap: wrap;
}

.card {
  width: calc(50% - 10px);
  font-size: 38px;
  border: 1px solid #000;
  margin-bottom: 30px;
  overflow:hidden;
}


/* add margin on child divs 1,3,5,7 etc */

.card:nth-child(2n+1) {
  margin-right: 20px;
  background: pink;
}

.matched_text {
  background: green;
  color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="my_input" placeholder="search for hello, min 2 chars...">

<div class="my_cards">

  <div class="card" data-initial_index="0">
    01 - apples and hello
  </div>

  <div class="card" data-initial_index="1">
    02 - oranges and hello
  </div>

  <div class="card" data-initial_index="2">
    03 - bananas
  </div>

  <div class="card" data-initial_index="3">
    04 - passionfruits and hello
  </div>

  <div class="card" data-initial_index="4">
    05 - mangos and hello
  </div>

  <div class="card" data-initial_index="5">
    06 - limes and hello
  </div>


</div>


1
我猜应该在过滤函数的末尾添加。 - Temani Afif
我已经为你的答案创建了一个jsFiddle,它似乎可以工作 - 你只做了一个调整吗?就是在keyup处理程序的末尾处理:even:odd吗?https://jsfiddle.net/rwone/g85yj2q7/2/ - user1063287
1
我修改了CSS,从边距中删除了important以及那两行代码。 - madalinivascu
1
参考我的情况是响应式的,即如果屏幕小于1200像素,则只显示一列卡片。使用上述解决方案,我发现如果筛选,然后调整窗口大小,jQuery的marginRight样式会保留(即使定义了其他响应式CSS)。所以我尝试捕获$(window).resize事件并有条件地处理,如下所示:if ($(window).width() < 1200) {$(".card").css("marginRight","0px");} else {$('.card:visible:even').css("marginRight","20px");$('.topic_card:visible:odd').css("marginRight",0);}它似乎有效。 - user1063287
我还在你的:odd/:even处理程序中添加了一个$(window).width()条件。 - user1063287

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