<table>布局日历仍合理,因其语义清晰、可访问性好;须用<thead><th scope="col">定义星期头,空单元格用<td>占位并设aria-hidden,每个日期<td>必须含data-date属性。

用 <table> 布局日历为什么仍合理
纯 CSS Grid 或 Flex 实现日历更现代,但 <table> 在语义和可访问性上仍有优势:日历本质是行列对齐的二维时间数据表,屏幕阅读器天然理解 <table> 的行列关系。只要不滥用 colspan/rowspan 破坏结构,它仍是可靠选择。
<thead> 里放星期头,别用 <tr> + <td> 硬写
星期栏属于表头信息,必须用 <th>,且包裹在 <thead> 中。否则会丢失语义,影响键盘导航和读屏顺序。
<thead>
<tr>
<th scope="col">日</th>
<th scope="col">一</th>
<th scope="col">二</th>
<th scope="col">三</th>
<th scope="col">四</th>
<th scope="col">五</th>
<th scope="col">六</th>
</tr>
</thead>
-
scope="col"明确告诉辅助技术这是列头,不可省略 - 别用
<td>替代<th>—— 即使加了aria-label,语义完整性也打折扣 - 中文习惯“日一二三四五六”,顺序固定,别按 locale 动态重排(除非明确支持多语言日历)
每月第一天前的空格单元格要靠 <td> 占位,不是用 或 margin
日历网格要求每周 7 列对齐。若某月 1 号是周三,则前两列需为空白单元格,否则后续日期会错位、被读作“无效日期”。
- 用真实
<td>元素占位,内容可为空(<td></td>),或加aria-hidden="true"避免读屏干扰 - 绝对不要用
、padding、margin或伪元素模拟空白 —— 这会让表格结构失真,打印或缩放时易崩 - 空单元格的
tabindex="-1"可防止键盘焦点落入无意义位置
当月日期单元格必须带 data-date 属性,别只靠文本内容推断
用户点击“15”无法知道这是几月几日,DOM 文本不包含上下文。靠 JS 解析所在行/列推算日期既脆弱又难维护。
立即学习“前端免费学习笔记(深入)”;
- 每个日期
<td>加data-date="2024-07-15"(ISO 格式),JS 和 CSS 都能直接用 - 避免
data-day="15" data-month="7"拆分存储 —— 容易遗漏年份,跨年场景失效 - 如果需要高亮今日,用
class="today"+data-date双保险,不单靠 class 名判断逻辑
最易被忽略的是空单元格的语义处理和 data-date 的强制绑定 —— 表格结构看似简单,但缺失这两点,日历就只是个好看但不可靠的视觉栅格。



















