应使用<section>包裹单门课程模块,因其语义化表达独立主题内容,需配<h2>~<h6>标题;课程时间须用<time datetime>标记,分类导航用<nav>并限2–3个,动态状态用<output aria-live>实时提示。

用 <section> 包裹单门课程模块,别套 <div>
教育网站的课程表不是表格数据,而是语义化的内容分组。每门课(含标题、简介、时间、教师、报名按钮)应独立为一个逻辑单元,<section> 正是为此设计的。用 <div> 套一层再加 class="course-item" 会丢失结构信息,影响屏幕阅读器识别和 SEO。
常见错误:把整张课程表塞进一个 <section>,或把课程时间单独提成 <section>——这违反“主题独立性”原则。
-
<section>必须有明确的<h2>~<h6>作为标题,不能空着 - 如果课程有子模块(如“课前准备”“配套资料”),可用嵌套
<section>,但层级不超过两层 - 避免在
<section>内再塞一个语义更强的标签(如<article>表示可独立分发的课程讲义)
课程时间用 <time> 标签,别只写纯文本
课程开始时间、持续时长、更新日期这些机器可读的时间信息,必须用 <time> 包裹,并提供 datetime 属性。搜索引擎和日历工具依赖这个字段提取事件;纯文本如“每周三 19:00–20:30”对爬虫毫无意义。
错误示例:<p>开课时间:2024-09-10</p> → 无法被解析为日期
立即学习“前端免费学习笔记(深入)”;
- 课程固定时段用
<time datetime="T19:00">19:00</time>–<time datetime="T20:30">20:30</time> - 具体开课日用
<time datetime="2024-09-10">9月10日</time> - 持续周期写成
<time datetime="P8W">8周</time>(ISO 8601 持续时间格式)
课程分类导航用 <nav>,但别滥用
顶部课程类别栏(如“编程|设计|语言|考试”)或侧边难度筛选(“入门|进阶|实战”)属于站点级导航,适合用 <nav>。但每门课内部的“上一节|下一节”按钮不是 <nav> 的使用场景——那是页面内跳转,应放在 <footer> 或用 <aside> 更合适。
容易踩的坑:给轮播图下方的课程标签云也套 <nav>,导致辅助技术误判为导航入口。
- 一个页面最多 2–3 个
<nav>,用aria-label区分用途,例如<nav aria-label="课程分类导航"> - 响应式折叠菜单需确保展开后仍保留在
<nav>内,不能动态移出 DOM - 移动端点击切换分类时,焦点管理要跟上,否则键盘用户会迷失
课程状态(已满/进行中/已结束)用 <output> + ARIA 实时提示
状态变化(如“剩余名额:3”变成“已满”)不是静态文案,而是需要主动通知用户的动态反馈。用 <output> 语义化包裹,并配合 aria-live="polite" 让屏幕阅读器自动播报,比单纯改文字更可靠。
<output id="seat-status" aria-live="polite">剩余名额:3</output>
注意:不要用 <span> + role="status" 替代 <output>,前者缺乏表单关联语义,在复杂课程表中易与表单控件混淆。
- 状态变更必须通过 JS 修改
<output>的textContent,而非 innerHTML(防 XSS) - 如果状态依赖异步加载(如实时查询余量),要在
fetch成功后立即更新<output>,不要等整个模块重绘 - “已结束”类状态建议加
aria-disabled="true"并视觉置灰,双重提示不可操作
<section>,什么时候该合并进一个 <article>;<time> 的 datetime 值是否覆盖所有用户时区场景——这些没法靠语法检查器发现,得对照真实用户动线反复验证。











