应使用语义化HTML结构组织图书排行列表:用<ol>替代<ul>表达名次,每本书用<article>包裹于<li>内,书名用<h3>/<h4>,作者等次要信息置于<footer>或,封面图必设alt属性;CSS通过::marker或计数器定制序号样式,兼顾可访问性;动态加载后需设置tabindex="-1"并focus确保焦点管理。

用语义化 HTML 结构组织图书排行列表
读书排行页本质是有序的图书数据展示,<ol> 比 <ul> 更合适——它天然表达「名次」,支持 reversed、start 属性,且对屏幕阅读器更友好。每本书用 <li> 包裹,内部优先用 <article> 而非 <div>,明确内容独立性。
常见错误是直接用一堆 <div> 堆出“第1名”“第2名”文字,既无语义,也无法被辅助技术识别顺序。也不要手动写「1.」「2.」前缀,交给 <ol> 的计数机制。
- 书名用
<h3>或<h4>(根据页面整体标题层级),避免用<p>+ 加粗模拟标题 - 作者、评分、出版年份等次要信息统一放在
<footer>或<small>内,不提升标题层级 - 封面图必须带
alt属性,如alt="《三体》封面,刘慈欣著",不可留空或仅写“图片”
CSS 控制排行数字样式与悬停交互
<ol> 默认数字是左侧对齐、黑体、无背景,实际排行页常需高亮序号(比如圆角背景+白字)。不能靠伪元素硬加数字(破坏可访问性),而应利用 CSS 计数器 + ::marker:
ol.rank-list {
counter-reset: rank;
}
ol.rank-list li {
counter-increment: rank;
}
ol.rank-list li::marker {
background: #ff6b6b;
color: white;
border-radius: 50%;
padding: 0 8px;
font-weight: bold;
}
注意:旧版 Safari 不支持 ::marker 样式,需降级为 list-style: none + ::before 插入 content: counter(rank),但此时要确保 aria-label 补充序号,例如 <li aria-label="第3名:《百年孤独》">。
立即学习“前端免费学习笔记(深入)”;
- 鼠标悬停时,整行
<li>背景变浅灰,而非只给封面图加 box-shadow(行为不一致) - 避免在
::before里用大字号数字撑开高度,导致行高错乱;统一用line-height和vertical-align对齐 - 移动端需增加
@media (max-width: 768px)规则,让序号字体缩小、左右内边距收窄
处理动态加载与无障碍焦点管理
如果排行数据来自 API(比如调用豆瓣图书 Top250 接口),渲染后必须手动触发焦点重置:否则用户按 Tab 键可能卡在上一页末尾,无法自然进入新榜单。
关键动作不是滚动到顶部,而是把 tabindex="-1" 加到新 <ol> 上,再立即 .focus():
const newRankList = document.querySelector('ol.rank-list');
newRankList.tabIndex = -1;
newRankList.focus();
同时确保每个 <li> 有 role="article"(当不用 <article> 标签时),且封面图链接加 aria-describedby 关联描述段落,例如:<a href="/book/123" aria-describedby="desc-123">...id="desc-123">《活着》,余华,豆瓣评分9.2</p>。
- 不要用
display: none隐藏未加载项,改用visibility: hidden或移除 DOM,否则屏幕阅读器仍会读出占位符 - 加载中状态需有
aria-busy="true"和aria-live="polite"的容器,提示“正在加载最新排行…” - 排序切换(如“按评分”“按出版年”)按钮必须是
<button>,不可用<div onclick>
兼容低版本浏览器的数字序号回退方案
IE11 及更早版本不支持 ::marker,也不支持 CSS 计数器在 <ol> 外生效。此时最稳妥的做法是服务端或 JS 渲染时,把序号作为文本节点插入,但必须保留原生 <ol> 结构:
<ol class="rank-list"> <li><span class="rank-num">1</span><h3>《霍乱时期的爱情》</h3></li> <li><span class="rank-num">2</span><h3>《人类简史》</h3></li> </ol>
然后用 CSS 控制 .rank-num 样式,并在现代浏览器中用 .rank-list li::marker { display: none; } 隐藏原生数字,避免重复。
- 切勿用
list-style-type: none后全靠 JS 插入序号——JS 失败时页面将完全丢失排名信息 - 如果项目强制要求 IE11 支持,
<ol start="1">属性仍有效,可配合 JS 动态改start值实现分页续号(如第2页从 21 开始) - 所有自定义序号都要同步更新
aria-label,不能只改视觉文本



















