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

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











