交替表格行颜色,对于"display:none"设置具有鲁棒性

3
我有一个使用JavaScript制作的动态表格。根据不同的用户事件,有些行将被隐藏、重新排列等。更具体地说,我使用display:none;来实现这一点。问题是,行始终保持其原始背景颜色(想象一下如果所有行都可见,那么你可以看到交替的颜色)。如果整个表格可见,那就没问题了,但正如我所提到的,有时某些行将被隐藏或出现在不同的位置。这通常会导致两个或更多相同颜色的行堆叠在一起。
有一个类似的帖子: 即使删除行也要交替表行颜色 我尝试了尽可能多的解决方案。然而,我的问题仍然存在。可能是由于以下原因:
  • 我没有删除列,我只是设置了display:none;
  • 我不是在jquery环境中工作,因此我只能使用本机JavaScript解决方案
我的代码是:
tr:nth-child(even) {
    background:gray;
}
tr:nth-child(odd) {
    background:lightgray;
}

我已经尝试了tr:nth-of-type(odd)和许多类似的变体。在CSS或本地javascript中还有别的可以尝试的吗?
更多关于可见性/选择的信息:
CSS:
tr:not(.selected) {
  display: none;
}

JS:

my_circles.each(function(d,i) {
    if (my_bool===true) {
        d3.select(this).classed('selected',true);
        tableRows.get(this).classed("selected", true);
    }
});

我正在使用d3.js,但我认为我将省略d3标记,因为这似乎更多是CSS或JS问题。这只是一个小片段,主要是为了上下文,但本质上我们应该能够推断出可见性是通过类分配来切换的。如果你好奇的话,它是在用户选择相邻散点图上的圆圈时发生的。


用于切换行可见性的是什么?你有一些 JavaScript 在执行这个操作吗?请提供它。 - haxxxton
我更新了帖子,请告诉我是否还有什么可以做来澄清事情。 - Arash Howaida
保持表格行的顺序重要吗?还是它们可以被随意打乱? - haxxxton
它们可以被洗牌,但出于美学原因,我希望交替的颜色保持一致。 - Arash Howaida
4个回答

3
很遗憾,对于这个问题,没有纯CSS的解决方案。主要原因是:not选择器与nth-...选择器不兼容。
你最好的选择是通过JavaScript重新为行添加条纹。在页面加载时就为行添加条纹。之后,每当你更改任何一行的display属性时,再次调用你的条纹函数。
以下是一个简单的示例:

var tab = document.getElementById("tab"), 
  btns = tab.getElementsByTagName("a"), 
  show = document.getElementById("show"), 
  rows
;

stripe(); // Stripe the rows in beginning

// The stripe function itself
function stripe() {
  // select all rows which are not hidden
  rows = tab.querySelectorAll('tr:not(.hidden)');

  // add a class for every second such row
  for(var x = 0; x < rows.length; x++) {
    if (x % 2 == 0) { rows[x].classList.add('alt'); }
    else { rows[x].classList.remove('alt'); }
  }
}

// dummy buttons to hide each row in this demo
[].forEach.call(btns, function(elem) {
  elem.addEventListener('click', hide);
});

// your actual code where you hide your rows
function hide(e) {
  e.target.parentNode.parentNode.classList.add('hidden');
  stripe(); // fire re-striping when hiding rows
}

// dummy button to show rows in this demo
show.addEventListener('click', function(e) {
  rows = tab.querySelectorAll('tr.hidden');
  [].forEach.call(rows, function(row) {
    row.classList.remove('hidden');
  });
  stripe(); // fire re-striping when showing rows
});
table { width: 70%; border: 1px solid gray; border-collapse: collapse; }
td { border: 1px solid gray; padding: 4px; }
tr.hidden { display: none; }
#tab tr.alt { background-color: #ddd;}
<table id="tab"><tbody>
  <tr><td>Row 1</td><td><a href="#">Hide</a></td></tr>
  <tr><td>Row 2</td><td><a href="#">Hide</a></td></tr>
  <tr><td>Row 3</td><td><a href="#">Hide</a></td></tr>
  <tr><td>Row 4</td><td><a href="#">Hide</a></td></tr>
  <tr><td>Row 5</td><td><a href="#">Hide</a></td></tr>
</tbody></table><br />
<a id="show" href="#">Show All</a>

附带的fiddle:https://jsfiddle.net/abhitalks/dz5aq5fk/

.


我尝试了所有的解决方案,虽然你的有点冗长,但在页面响应速度方面似乎是最快的。感谢你聪明的解决方法。 - Arash Howaida
@ArashHowaida:这并不冗长。相关的“stripe”函数中实际代码只有4-5行,其余都是为演示设置。 - Abhitalks

2
这不是CSS或本地JS解决方案,但这里有一个基于d3的解决方案。每当表格中的行发生变化时,您可以更改行的类。
d3.selectAll("tr.selected").classed("grey",function(d,i){return i%2 == 0});

它会在每隔一行添加 grey 类并从所有其他行中删除它,然后您可以使用 CSS 来对行进行着色。
tr.grey {
    background:gray;
}
tr:not(.grey) {
    background:lightgray;
}

这里有一个展示该策略实际应用的jsbin

1
这不是一个完美的解决方案,但你可以在表格中使用渐变背景来达到想要的效果。
以下是使用渐变背景的表格示例。

tr:not(.selected) {
  display: none;
}

table {
  background-color: gray; 
  background-image: linear-gradient(transparent 50%, lightgray 50%);
  background-size: 100% 36px;
}
<table width="500" cellpadding="0" cellspacing="0">
  <tr  class="selected">
    <td>A</td>
    <td>B</td>
  </tr>
    <tr  class="selected">
    <td>C</td>
    <td>D</td>
  </tr>
    <tr>
    <td>E</td>
    <td>F</td>
  </tr>
    <tr class="selected">
    <td>G</td>
    <td>H</td>
  </tr>
    <tr>
    <td>I</td>
    <td>J</td>
  </tr>
      <tr>
    <td>E</td>
    <td>F</td>
  </tr>
    <tr class="selected">
    <td>G</td>
    <td>H</td>
  </tr>
  <tr class="selected">
    <td>G</td>
    <td>H</td>
  </tr>
  <tr class="selected">
    <td>G</td>
    <td>H</td>
  </tr>
    <tr>
    <td>I</td>
    <td>J</td>
  </tr>
  
</table>


但是这只适用于表格行高度相同的情况,如果行高度动态变化,这并不是一个实际可行的解决方案。 - Terry
非常有创意!我想具有许多行的表可能更难处理。 - Arash Howaida
@Terry,是的,你说得对,这个解决方案只适用于行高不变的情况。 - AG_

1
正如您正确指出的那样,CSS交替条纹不起作用的原因是您的行保持在原地,只是使用display:none隐藏。
诀窍是将可见和隐藏的行“分组”在一起,以避免出现未发生事件的条纹。鉴于您的行的顺序并不重要,我们可以将隐藏的行移动到其包含父级的顶部(使用.insertBefore)或底部(使用.appendChild)。类似于这样的东西:
my_circles.each(function(d,i) {
    if (my_bool===true) {
        d3.select(this).classed('selected',true);
        var row = tableRows.get(this);
        row.parentNode.appendChild(row);
        row.classed("selected", true);
    }
});

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