课程列表页需用语义化HTML(如<section><figure><aside><footer>)、响应式CSS Grid(auto-fill+minmax)、ARIA状态标签(role="status")及IntersectionObserver懒加载,确保所有用户感知状态变化。

课程列表页不需要复杂框架也能做得清晰易用,关键是结构语义正确、样式可维护、响应及时——否则用户划三屏都找不到“立即报名”按钮。
用 <section> 包裹每门课,别用 <div>
很多页面把课程硬塞进一堆 <div class="item">,结果屏幕阅读器读不出内容层级,SEO 也弱。课程是独立内容单元,<section> 才是语义正确的容器。
- 每个
<section>加aria-labelledby指向课程标题,辅助技术能准确定位 - 避免嵌套过深:课程封面图用
<figure>,描述用<aside>(如“已更新至2024版”),别全堆在<div>里 - 如果课程带讲师信息,用
<footer>放讲师名和头像链接,不是随便加个<p>
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) 是响应式列数的底线写法
固定写死 grid-template-columns: 3fr 3fr 3fr 或媒体查询切三段,后期改列数或加筛选就容易崩。用 auto-fill + minmax() 让浏览器自己算列数更稳。
- 最小宽度设
280px是因为手机横屏+小字体下,再窄就撑不开标题和价格 - 别漏掉
gap:建议gap: 1.5rem,比margin更可控,且不会和外层 padding 冲突 - 如果课程卡片高度不一,加
align-items: start,否则底部按钮会错位
课程状态标签必须用 <span role="status"> 而非纯 CSS
“限时优惠”“已开课”“仅剩2席”这类动态标签,光靠颜色和文字不够。用户开着语音朗读或色觉障碍时,需要明确的状态语义。
立即学习“前端免费学习笔记(深入)”;
- 写成
<span role="status" aria-live="polite">剩余名额:7</span>,变化时屏幕阅读器会自动播报 - 禁止用
title属性做提示:“hover 显示详情”对触屏和键盘用户无效 - 状态色值要满足对比度:比如红色标签文字至少用
#d32f2f(非#ff0000),背景用#ffebee
加载更多按钮卡在“点击无反应”,大概率是没处理 IntersectionObserver 的 rootMargin
懒加载课程项时,如果按钮总要拉到底部才触发,说明 rootMargin 没设缓冲区,浏览器判定它“还没进入视口”。
- 初始化 Observer 时至少写
rootMargin: '200px',让按钮提前 200px 开始监听 - 点击“加载更多”后,按钮本身要
disabled并加aria-busy="true",防止重复提交 - 接口返回空数组时,要显式替换按钮为
<span>没有更多课程了</span>,不能只隐藏
课程列表页最难的不是排版,而是让“状态变化”被所有用户感知到——价格变动、名额减少、章节更新,这些信息一旦脱离语义结构和 ARIA 约束,就只剩视觉在自说自话。



















