CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
HTML 与 CSS 基础/课时/语义化与可访问性
RawBlame
课时目录12 节

HTML 与 CSS 基础

  1. 01网页如何工作
  2. 02HTML 文档结构
  3. 03文本、链接与媒体
  4. 04HTML 表单
  5. 05语义化与可访问性
  6. 06CSS 选择器与层叠
  7. 07盒模型与布局流
  8. 08Flexbox 布局
  9. 09Grid 布局
  10. 10响应式设计
  11. 11综合练习:静态课程页
  12. 12框架与下一步

语义化与可访问性

nav/main/article、alt、aria 入门。

30 分钟

HTML 语义化与 ARIA

这一课你将能做到

  1. 用 HTML5 语义标签(<header>、<nav>、<main>、<article>、<section>、<aside>、<footer>)构建页面骨架
  2. 为复杂组件补充 ARIA 属性(role、aria-label、aria-expanded、aria-live 等),提升无障碍访问体验
  3. 理解语义化对 SEO、屏幕阅读器和代码可维护性的综合价值

为什么要学

HTML5 引入了大量语义标签,不是为了让你多记几个单词,而是为了解决一个根本问题:「这段内容到底是什么?」搜索引擎爬虫、屏幕阅读器、RSS 阅读器、社交分享机器人——它们都看不到 CSS 渲染后的视觉效果,只能读取 HTML 标签来判断内容结构。

CodeForge 的课程列表页面如果用 <div class="card"> 堆砌,搜索引擎只知道「这里有几个 div」,不知道「这是课程卡片、有标题、有描述、有价格」。换成 <article> + <h2> + <p> + <time>,信息的可读性和可访问性会完全不同。

语义化和 ARIA 不是「加分项」,而是现代 Web 开发的底线要求。在很多国家和地区,Web 可访问性(Accessibility,简称 a11y)是法律要求。

先建立图像

CodeForge 首页语义化结构:

<body>
├── <header>
│   └── <nav aria-label="主导航"> ... </nav>
│
├── <main>
│   ├── <section aria-labelledby="hero-title">
│   │   └── <h1 id="hero-title">...</h1>
│   │
│   ├── <section aria-labelledby="courses-title">
│   │   └── <h2 id="courses-title">热门课程</h2>
│   │   └── <ul>
│   │       └── <li>
│   │           └── <article>
│   │               ├── <h3>课程标题</h3>
│   │               ├── <p>描述</p>
│   │               └── <time datetime="2026-10-07">...</time>
│   │
│   └── <aside aria-label="侧边栏">
│       └── <p>学习提示...</p>
│
└── <footer> ... </footer>

跟着做

步骤 1:用语义标签重写页面骨架

创建 semantic.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>语义化示例 | CodeForge</title>
  <style>
    :root { --primary: #2563eb; --surface: #fff; --text: #0f172a; --muted: #64748b; --border: #e2e8f0; }
    body { font-family: system-ui, sans-serif; margin: 0; color: var(--text); background: #f8fafc; }
    header, footer { background: var(--surface); border-bottom: 1px solid var(--border); padding: 1rem 2rem; }
    footer { border-top: 1px solid var(--border); border-bottom: none; text-align: center; color: var(--muted); }
    nav ul { display: flex; gap: 1.5rem; list-style: none; margin: 0; padding: 0; }
    nav a { color: var(--text); text-decoration: none; font-weight: 500; }
    main { max-width: 900px; margin: 2rem auto; padding: 0 1rem; }
    .hero { text-align: center; padding: 3rem 1rem; }
    .hero h1 { font-size: clamp(1.75rem, 4vw, 2.5rem); margin: 0 0 0.5rem; }
    .course-grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-top: 1.5rem; }
    article { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; }
    article h3 { margin: 0 0 0.5rem; font-size: 1.125rem; }
    article p { margin: 0 0 0.75rem; color: var(--muted); font-size: 0.9375rem; }
    time { font-size: 0.875rem; color: var(--muted); }
    aside { background: #eff6ff; border-left: 4px solid var(--primary); padding: 1rem 1.25rem; border-radius: 0 8px 8px 0; margin-top: 2rem; }
  </style>
</head>
<body>
  <header>
    <nav aria-label="主导航">
      <ul>
        <li><a href="#" aria-current="page">首页</a></li>
        <li><a href="#">课程</a></li>
        <li><a href="#">路线图</a></li>
        <li><a href="#">关于</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <section class="hero" aria-labelledby="hero-title">
      <h1 id="hero-title">构建你的前端技能树</h1>
      <p>从 HTML 语义化到现代 CSS 布局,系统化掌握网页开发。</p>
    </section>

    <section aria-labelledby="courses-title">
      <h2 id="courses-title">热门课程</h2>
      <div class="course-grid">
        <article>
          <h3>HTML/CSS 基础精讲</h3>
          <p>掌握语义化标签、盒模型、Flexbox 与 Grid 布局。</p>
          <time datetime="2026-10-07">更新于 2026年10月7日</time>
        </article>
        <article>
          <h3>JavaScript 核心原理</h3>
          <p>深入理解作用域、闭包、原型链与异步编程。</p>
          <time datetime="2026-09-20">更新于 2026年9月20日</time>
        </article>
      </div>
    </section>

    <aside aria-label="学习建议">
      <p><strong>提示:</strong>建议按顺序学习基础课程,再进入进阶内容。</p>
    </aside>
  </main>

  <footer>
    <p>&copy; 2026 CodeForge 学习平台. 保留所有权利。</p>
  </footer>
</body>
</html>

保存后打开,按 F12 → Elements 观察标签树。用 axe DevTools 或 Lighthouse 运行可访问性审计,得分应该很高。

步骤 2:理解每个语义标签的职责

标签用途不要这样用
<header>页面或区块的引导内容(logo、导航、搜索)仅为了放大顶部背景
<nav>主要导航链接组把页脚所有链接都包进去
<main>页面唯一的主要内容区一个页面出现多个 <main>
<article>可独立分发、复用的内容块(博客、课程卡片、评论)纯装饰性容器
<section>主题相关的分组,通常带标题单纯为了加样式而分组(用 <div>)
<aside>与周围内容间接相关(侧边栏、提示框)主要内容区
<footer>页面或区块的尾部信息(版权、相关链接)页面任意位置的底部

步骤 3:为导航添加 ARIA 当前状态

<nav aria-label="主导航">
  <ul>
    <li><a href="/" aria-current="page">首页</a></li>
    <li><a href="/courses">课程</a></li>
  </ul>
</nav>

aria-current="page" 告诉屏幕阅读器「这是当前所在页面」,用户不用猜测自己在哪。同理,分页组件中当前页可用 aria-current="true"。

步骤 4:为可展开内容添加 ARIA 状态

<button type="button" aria-expanded="false" aria-controls="course-menu" id="menu-toggle">
  展开课程目录
</button>
<div id="course-menu" role="region" aria-labelledby="menu-toggle" hidden>
  <ul><li>第 1 课:网页如何工作</li><li>第 2 课:HTML 文档结构</li></ul>
</div>

aria-expanded 表示展开状态,aria-controls 指向被控制的元素 ID。当用户点击按钮展开内容时,JavaScript 应将 aria-expanded 改为 "true",并移除 hidden 属性。屏幕阅读器会播报「展开,按钮」或「折叠,按钮」。

步骤 5:使用 aria-live 播报动态更新

<div id="toast-region" aria-live="polite" aria-atomic="true"></div>

当 JavaScript 向这个区域插入内容(如「保存成功」「网络错误」)时,屏幕阅读器会自动朗读。polite 表示等用户当前操作完成后再播报,不会打断;assertive 表示立即播报,仅用于关键错误。

讲清楚要点

  1. 语义化首先是给人读的:语义标签让代码结构一目了然。看到 <article> 你就知道这是独立内容块,看到 <nav> 就知道这是导航。维护成本显著低于满屏 <div class="nav">、<div class="main">。

  2. <section> 需要标题:如果一个 <section> 没有标题(<h2>-<h6>),那它很可能不该用 <section>,用 <div> 更合适。<section> 的存在意义就是「这是文档大纲中的一个主题分组」。

  3. <article> 强调可独立复用:一篇博客文章、一条评论、一个课程卡片、一条搜索结果,都是 <article>。测试方法:如果这段内容被单独分享到其他地方仍然有意义,它就是 <article>。

  4. ARIA 是补充,不是替代:优先使用原生 HTML 语义标签。如果原生标签不够用(如自定义下拉菜单、标签页组件),再用 ARIA 补充。不要给 <button> 加 role="button",它是多余的。

  5. 可访问性是法律责任,也是商业需求:在许多国家(包括中国),政府网站和公共服务必须满足 WCAG 标准。对于商业产品,无障碍改进通常能覆盖 15%-20% 的潜在用户(包括老年人、临时受伤者、低视力者)。

你可能会懵的地方

  • 「都用 <div> 也能显示,为什么要多记这么多标签?」 为了代码可读性、SEO、无障碍访问和未来可维护性。一个项目活过三个月,开发者就会感谢当初写语义标签的人。搜索引擎也会感谢——排名可能更高。

  • <section> 和 <div> 到底怎么选?」 如果这段内容需要一个标题来概括主题,用 <section>;如果只是为了 CSS 布局或 JS 操作而需要一个容器,用 <div>。简单规则:没有标题的 <section> 是可疑的。

  • 「<article> 和 <section> 可以互相嵌套吗?」 可以,但要符合逻辑。<section> 里可以包多个 <article>(如「评论区」是一个 section,每条评论是一个 article)。<article> 里也可以有 <section>(如一篇长文章分「引言」「方法」「结论」三个 section)。

  • 「ARIA 写多了会有副作用吗?」 会。错误的 ARIA 比没有 ARIA 更糟。例如给 <div> 加 role="button" 但不处理键盘事件(Enter/Space),会让屏幕阅读器用户以为这是按钮,但无法操作。ARIA 的第一原则是:能用原生 HTML 元素就不用 ARIA。

  • 「aria-label 和 aria-labelledby 有什么区别?」 aria-label 直接提供文本字符串,如 aria-label="关闭弹窗"。aria-labelledby 引用页面上另一个元素的 ID,如 aria-labelledby="dialog-title",这样标签文本可以复用已有内容,且支持多语言。

错法对照

错法问题正解
全站只用 <div> 和 <span>搜索引擎和屏幕阅读器无法理解结构根据内容含义选择语义标签
一个页面多个 <main>违反规范,辅助技术无法识别主内容每页仅一个 <main>
<nav> 包进页脚所有链接<nav> 应只用于主要导航区块页脚链接用 <footer> 内的 <ul> 即可
给原生按钮加 role="button"冗余,且可能覆盖原生行为原生元素不要加冗余 role
<section> 没有标题失去大纲意义,不如用 <div>每个 section 配一个标题
用 aria-hidden="true" 隐藏焦点元素键盘用户仍能聚焦到「看不见」的元素隐藏时同时从 Tab 顺序中移除(tabindex="-1" 或 display:none)

卡点急救

  1. Lighthouse 可访问性分数很低:常见原因包括图片缺少 alt、表单字段没有 label、颜色对比度不足(文字与背景色对比度应至少 4.5:1)、可点击元素尺寸太小(推荐至少 44×44 CSS 像素)。

  2. 屏幕阅读器不播报当前位置:检查导航链接是否有 aria-current="page";检查标题层级是否连续(不要从 <h1> 跳到 <h3>)。

  3. 自定义组件键盘无法操作:所有交互元素必须是可聚焦的(<button>、<a>、带 tabindex="0" 的元素)。确保可以通过 Tab 聚焦,Enter 或 Space 激活,且焦点顺序符合视觉顺序。

面试常问

  • 「什么是 HTML 语义化?常见的语义标签有哪些?」 HTML 语义化是指使用具有明确含义的标签来描述内容结构,而不是仅为了视觉效果。常见语义标签包括:<header>(页头)、<nav>(导航)、<main>(主内容)、<article>(独立内容块)、<section>(主题分组)、<aside>(侧边内容)、<footer>(页脚)、<time>(时间)。语义化有利于 SEO、无障碍访问和代码可维护性。

  • 「ARIA 是什么?什么时候需要使用?」 ARIA(Accessible Rich Internet Applications)是一套属性,用于补充 HTML 语义,让辅助技术更好地理解复杂组件和动态内容。当原生 HTML 元素无法满足需求时使用,例如自定义下拉菜单、标签页、模态框、动态加载内容等。第一原则是「能用原生 HTML 就不用 ARIA」。常用属性包括 role、aria-label、aria-labelledby、aria-expanded、aria-hidden、aria-live。

  • 「如何测试网页的可访问性?」 三层测试:一、自动化工具(Lighthouse、axe DevTools),快速捕获标签缺失、对比度不足;二、键盘测试,断开鼠标,只用 Tab、Enter、Space、方向键完成所有交互;三、屏幕阅读器测试(NVDA、VoiceOver),实际听读页面内容,验证标签和动态更新是否正确播报。

自测三问

  1. 你正在构建一个博客网站,首页有文章列表、侧边栏分类、页脚版权信息。请指出哪些部分应该使用 <article>、<aside>、<section>、<nav>。
  2. 为什么给 <div onclick="..."> 加 role="button" 是不够的?还需要做什么才能让它真正可访问?
  3. aria-live="polite" 和 aria-live="assertive" 有什么区别?分别适用于什么场景?

小结一句话

HTML5 语义标签让代码自己说话,ARIA 让复杂交互也能被所有人理解;语义化不是「额外的功夫」,而是专业前端工程师的基本功。

延伸

  • MDN:HTML5 语义元素
  • MDN:ARIA 入门
  • 下一课:CSS 基础——从选择器到层叠与继承。
加载本节练习…
← 上一课HTML 表单下一课 →CSS 选择器与层叠