课表语义正确需严格遵循HTML表格规范:<thead>仅包<th>表头,<tbody>中每行首列用<th scope="row">标节次,跨节用rowspan且下一行跳过对应列,colspan/rowspan须准确表达逻辑单元跨度,<caption>和scope属性不可或缺。

用 <table> 做课表,哪些标签必须写对
语义错误是课表错位、屏幕阅读器读不出“第3节周三”的根本原因。关键不是能不能显示,而是浏览器和辅助工具能否理解结构。
-
<thead>必须只包表头行(如“节次”“周一”…),且内部用<th>,不能混用<td> -
<tbody>包所有课时行,每行首列用<th scope="row">标注节次(如“第1节”),这是让读屏软件知道“这一行对应哪个时间段”的唯一可靠方式 - 跨节课程(如连上两节)必须用
rowspan="2",且下一行对应列必须跳过——不能留空<td></td>,否则会多出一格破坏对齐 - 避免在
<table>上直接写border="1"调试,改用 CSS 的border-collapse: collapse,否则打印或缩放时边框易错位
colspan 和 rowspan 容易写反的三个场景
这两个属性不是“合并几格”,而是“占据几个逻辑单元”。写错会导致整行偏移、后续列全乱。
- 表头第一格写“时间\日期”,想横跨前两列 → 正确:
<th colspan="2">时间\日期</th>;错误:写成colspan="1"或漏掉colspan直接填内容 - “上午”要纵跨4节课 → 正确:
<th rowspan="4">上午</th>;错误:写成rowspan="3"(少占一格),或把rowspan加在后面的时间单元格上(位置错) - 某门课从周三第2节上到第3节 → 正确:在“周三第2节”的
<td>加rowspan="2",第3节那行的周三列不写<td>;错误:两行都写<td>还加rowspan,结果多出一格
响应式课表别硬套 <table>,什么时候该切 CSS Grid
纯 <table> 在手机上左右滚动体验差,且无法实现“课程块拖拽”“点击展开详情”等交互。但 Grid 不是万能替代,得看需求。
- 需要跨天合并(如“周五下午+周六上午”连上)、动态调整课时高度、或支持触控拖动 → 用
display: grid,配合grid-column/grid-row精确定位每个<div class="course"> - 列数固定(仅周一至周五)、无跨节合并、只需适配小屏 → 优先用
<table>+ 媒体查询:设font-size: clamp(12px, 3vw, 14px)+overflow-x: auto容器包裹,比 Grid 更轻量 - 有大量班级并行课表(如全校课表),需横向滚动浏览全部星期 → 用
display: flex+white-space: nowrap,比 Grid 渲染更快,也更易控制滚动精度
可访问性不是加个 role="grid" 就完事
加了 ARIA 属性但结构混乱,反而会让读屏软件更困惑。真正起作用的是底层 HTML 与属性的严格匹配。
立即学习“前端免费学习笔记(深入)”;
- 如果用了
<table>,就不要额外加role="grid"—— 表格本身已是语义化网格,加了反而干扰 - 如果用 CSS Grid 布局,必须为容器设
role="grid",每个课程单元设role="gridcell",并手动通过aria-rowindex/aria-colindex注明行列号(Grid 自动计算的索引读屏器不一定识别) -
<caption>必须存在且描述清晰,例如<caption>计应2307班 2026年春季学期课表</caption>,不能空着或只写“课表” - 所有
<th>必须有明确scope:列头用scope="col",行头用scope="row",否则读屏器无法关联课程和对应时间
复杂课表真正的难点不在布局,而在“同一门课在不同设备上被正确识别为同一个逻辑单元”。rowspan 写错一格、scope 漏一个,整张表对视障用户就失效了。



















