:nth-child按dom物理位置计数,无视display:none等样式隐藏,仅当节点被remove()或条件渲染移除时序号才重排;:nth-of-type虽过滤标签类型但仍计入隐藏元素;纯css无法实现按可见性重算序号,需js干预或框架条件渲染。

:nth-child 选择隐藏元素时序号“不连续”,其实是你误以为它该连续——它根本就不是按可见性计数的,从来就没打算连续。
为什么 :nth-child 无视 display: none
它只认 DOM 树里子节点的物理位置,连换行符、注释、<script></script> 都算一个节点,更别说 display: none 这种纯样式控制了。浏览器在解析 :nth-child(n) 时,压根不查 getComputedStyle(el).display,只遍历父元素的 childNodes 列表,从索引 0 开始数到 n−1,然后匹配对应位置上的元素类型。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 写
tr:nth-child(2),哪怕第 2 个<tr> 被 <code>style="display:none"盖住,只要它还在 DOM 里,就仍算第 2 个子节点 - 删掉它用
el.remove(),或用框架条件渲染(如 React 的{show && <tr>})让它彻底不出现在 DOM 中,序号才会重排 <li> <code>visibility: hidden和opacity: 0同样不影响计数——它们只是让元素“看不见”,不是“不存在” - 如果所有
<tr> 都是同级、没插其他标签,<code>tr:nth-of-type(2)和tr:nth-child(2)效果一样 - 一旦有
<tbody>、<code><thead> 或 CMS 插入的 <code><div class="ad">,<code>:nth-of-type就开始显优势 - 但它依然会把
display: none的<tr> 算进去——因为 DOM 节点还在,类型没变 <h3>真正按可见顺序样式化的可行路径</h3> <p>靠纯 CSS 实现“隐藏后自动重算奇偶/序号”目前无解,必须引入 JS 干预 DOM 或类名。</p> <ul> <li>最稳做法:过滤时用 <code>el.remove()或el.replaceWith()彻底移除节点,而不是切display - 次选方案:JS 遍历所有可见
<tr>,动态加 <code>data-index="1"、data-index="2"类,再用属性选择器tr[data-index="odd"] - 懒人折中:用
tr:not([style*="display:none"]):nth-of-type(odd)——但注意这仅在内联 style 且没空格时生效,不可靠,仅临时调试用 - 框架内(Vue/React)优先用条件渲染,避免
v-show(等价于display: none),改用v-if让节点真正进/出 DOM
:nth-of-type 能绕过隐藏元素吗?
不能。它也不感知显隐状态,但至少过滤掉了其他标签干扰。比如表格中混着 <div> 或 <code><comment></comment>,tr:nth-of-type(2) 会跳过那些非 <tr> 的节点,只数 <code><tr> 标签本身——所以它比 <code>:nth-child 更接近你“第几个可见行”的直觉,但依然不是真按可见性算。
别指望 CSS 伪类能响应运行时显隐变化;它的计算发生在样式引擎解析阶段,是静态的、一次性的。你看到的“序号错乱”,其实是 DOM 结构和 CSS 语义本就如此——问题不在你写错了,而在你期待它做它设计上就不做的事。










