原生无法实现真实产品排名,因其仅机械递增编号,不支持并列、跳位或动态重排;须用css计数器配合js排序与打标,并添加aria-label保障可访问性。

原生 <ol></ol> 标签做不了真正的产品排名——它只负责递增编号,不处理并列、跳位、分数计算或动态重排。
为什么直接用 <ol></ol> 会出错
浏览器对 <ol></ol> 的序号是“机械递增”的:无论数据是否并列、是否跳过名次,它都从 start 值开始 +1、+1、+1。比如两个产品同分第2,下一名必须是第3,但真实排名应为“2、2、4”。<ol></ol> 无法表达这种语义,强行用 value 属性硬调还会破坏可访问性(屏幕阅读器可能误读)。
- 用户看到“2、2、4”,但
<li value="4">实际让第3项被读作“第4名” -
reversed只倒序编号,不能按分数降序排列内容 - 没有排序逻辑,HTML 本身不会读取
data-score并重排 DOM
用 CSS 计数器实现可控名次
真正可控的排名显示靠 counter-reset + counter-increment + ::before,每个 <li> 是否触发计数由 JS 决定。
.rank-list { counter-reset: rank; }
.rank-item { position: relative; }
.rank-item.is-tied::before { content: "● " counter(rank) "名"; }
.rank-item:not(.is-tied)::before {
counter-increment: rank;
content: "● " counter(rank) "名";
}
- JS 遍历排序后的数组,比较相邻项分数:相等就加
is-tied类,跳过counter-increment - 这样“95、95、87”会渲染为“● 1名”“● 1名”“● 3名”,视觉与语义一致
- 前缀(如图标、颜色、单位)可自由加在
content里,<ol></ol>做不到
排序逻辑必须由 JavaScript 完成
HTML 不会自动按销量、评分或价格排序;你得用 JS 处理原始数据,再生成带正确类名的 DOM。
- 原始数据是对象数组:
[{name: "A", score: 95}, {name: "B", score: 95}, {name: "C", score: 87}] - 先
.sort((a, b) => b.score - a.score)得到降序 - 再遍历打标:
if (i > 0 && item.score === prev.score) item.rank = prev.rank; else item.rank = i + 1 - 最后用
.map()生成带is-tied或rank-1类的<li>字符串,innerHTML = ...或append()
别忽略可访问性和 SEO 影响
用 CSS 计数器时,屏幕阅读器默认不读 ::before 伪元素内容——名次信息对视障用户不可见。
- 必须给每个
<li>加aria-label,例如aria-label="产品A,排名第1" - 如果 JS 未加载,纯 HTML 应 fallback 为语义清晰的结构(如用
<dl></dl>表示“名次→产品”映射) - 搜索引擎不执行 JS,所以关键排名数据最好也以结构化方式保留在 HTML 中(如隐藏
data-rank属性)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











