freeCodeCamp 应用无障碍课程:用 nav 地标让屏幕阅读器导航更轻松
2026/9/7 20:08:50 网站建设 项目流程

freeCodeCamp 应用无障碍课程:用 nav 地标让屏幕阅读器导航更轻松

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

本篇技术指南围绕 freeCodeCamp 课程中的挑战「Make Screen Reader Navigation Easier with the nav Landmark」(用 nav 地标让屏幕阅读器导航更容易)展开,讲清楚 HTML5nav语义元素的内置地标(landmark)特性、为何用div包裹导航链接会损害可访问性,以及如何用一段可验证的测试断言来确认你的语义化改造是否达标。读完本文,你将掌握:把无语义容器替换为语义元素的完整实操流程、该挑战的完整初始代码与参考解答,以及 freeCodeCamp 课程仓库中这道题在 Responsive Web Design 课程里的定位与前后衔接关系。

挑战在课程结构中的位置

这道挑战位于课程仓库curriculum目录下,文件为 nav 地标挑战,属于 Applied Accessibility(应用无障碍)模块。该模块的组织信息由 applied-accessibility.json 描述,其中helpCategory标记为HTML-CSSchallengeOrder数组给出了全部 22 道挑战的完成顺序。按此顺序,本挑战排在第 7 位:

  • 前置挑战:Make Screen Reader Navigation Easier with the header Landmark——先把页面顶部的div改为header地标;
  • 当前挑战:把header内包裹导航链接的div改为nav地标;
  • 后置挑战:Make Screen Reader Navigation Easier with the footer Landmark——把页脚版权信息的div改为footer地标。

从源码结构看,这三道挑战共享同一个「Camper Cat 忍者训练页」的场景骨架,形成 header → nav → footer 的地标递进练习。再往上一层,responsive-web-design.json 显示 Applied Accessibility 是 Responsive Web Design 课程的第 4 个 block(位于 basic-html-and-html5、basic-css、applied-visual-design 之后),即学习者先掌握基础 HTML/CSS 与视觉设计后,才进入本模块学习语义化与无障碍。

核心概念:nav 元素与内置地标特性

挑战文档的核心说明(原文 description 部分)只有一句话,但信息密度很高:

nav元素是另一个带有内置地标特性的 HTML5 元素,用于方便屏幕阅读器导航。这个标签应包裹页面中的主要导航链接。

这里的关键点有两层:

  1. 地标(landmark)是浏览器自动赋予的nav不需要额外的 ARIA 属性——role="navigation"是隐式默认角色。屏幕阅读器和辅助技术(AT)通常提供「跳转到导航区域」之类的快捷操作,用户无需逐个朗读整个页面就能在多个区域之间跳跃。这与前面几道挑战中mainheader元素共享同一种机制:语义元素本身即地标。
  2. nav的语义边界是「主要导航」。它应当包裹页面的主导航链接(如站点菜单、页内锚点跳转),而不是包裹一切看起来像链接的列表。

文档同时给出了一条重要的边界规则:如果页面底部存在重复的站点链接,不必再用nav标记它们,用footer(下一道挑战的内容)即可。这条规则避免了把「页脚辅助链接」也声明为导航地标,从而防止地标导航树中出现语义重复的导航区域。

练习场景:把 div 换成 nav

挑战的 instructions 部分设定的场景是:Camper Cat 在他的训练页面顶部加入了导航链接,但把它们包在了一个div里。任务是把这个div改为nav标签,以提升页面可访问性。

挑战文件中的 seed(初始代码)如下,注意header内部第二个子元素就是那个「问题 div」:

<body> <header> <h1>Training with Camper Cat</h1> <div> <ul> <li><a href="#stealth">Stealth &amp; Agility</a></li> <li><a href="#combat">Combat</a></li> <li><a href="#weapons">Weapons</a></li> </ul> </div> </header> <main> <section id="stealth"> <h2>Stealth &amp; Agility Training</h2> <article><h3>Climb foliage quickly using a minimum spanning tree approach</h3></article> <article><h3>No training is NP-complete without parkour</h3></article> </section> <section id="combat"> <h2>Combat Training</h2> <article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article> <article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article> </section> <section id="weapons"> <h2>Weapons Training</h2> <article><h3>Swords: the best tool to literally divide and conquer</h3></article> <article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article> </section> </main> </body>

这段初始代码已经完成了上一道挑战的改造:页面顶部是header,正文主体是main,每个训练分类用section+h2组织,具体课程条目用article+h3。唯一残留的无语义容器,就是包裹导航ul的那个div

参考解答

挑战文件 solutions 部分给出的完整答案,只改动了导航容器这一处——<div>变为<nav>,闭合标签同步替换,其余内容原样保留:

<body> <header> <h1>Training with Camper Cat</h1> <nav> <ul> <li><a href="#stealth">Stealth &amp; Agility</a></li> <li><a href="#combat">Combat</a></li> <li><a href="#weapons">Weapons</a></li> </ul> </nav> </header> <main> <section id="stealth"> <h2>Stealth &amp; Agility Training</h2> <article><h3>Climb foliage quickly using a minimum spanning tree approach</h3></article> <article><h3>No training is NP-complete without parkour</h3></article> </section> <section id="combat"> <h2>Combat Training</h2> <article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article> <article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article> </section> <section id="weapons"> <h2>Weapons Training</h2> <article><h3>Swords: the best tool to literally divide and conquer</h3></article> <article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article> </section> </main> </body>

值得注意的结构细节:nav包在header内部,而不是独立于页头。这符合文档「包裹页面主要导航链接」的定位——导航属于页头区块的组成部分,同时nav作为独立地标仍可被辅助技术单独定位。

测试断言:如何验证改造达标

挑战 hints 部分实际上就是判定你代码是否通过的 4 条测试断言(基于 Jest/Chai 风格断言,其中code是你的原始代码文本,document是解析后的 DOM)。逐条拆解:

断言 1:页面中应恰好有一个nav标签。

assert.lengthOf(document.querySelectorAll('nav'), 1);

querySelectorAll('nav')在文档中查找所有nav元素,长度必须为 1。这既排除了「忘记改」,也排除了「多加了一个 nav」——与文档中「重复的站点链接不必再包nav」的规则相呼应:多个导航地标会稀释地标导航的意义。

断言 2:nav必须包裹ul及其列表项。

const nav = document.querySelector('nav'); const children = nav?.querySelectorAll(`:scope ${'ul'}`); assert.lengthOf(children, 1);

:scope前缀确保querySelectorAll('ul')只在nav元素内部查找,验证ul(及三个li导航项)确实处于nav内部,而不是被挪到了nav外面。这保证了地标语义覆盖的是完整导航集合。

断言 3:代码中不能再出现任何div标签。

assert.lengthOf(document.querySelectorAll('div'), 0);

这条断言把「替换」锁死为「替换」而非「新增」:不允许在保留div的基础上另加nav。页面此时应当完全由语义元素构成(headernavmainsectionarticle、标题与列表)。

断言 4:nav必须成对闭合。

assert.isTrue( code.match(/<\/nav>/g)?.length === code.match(/<nav>/g)?.length );

这条断言直接对原始代码文本做正则匹配,比较<nav>开标签与</nav>闭标签的数量是否相等。在 HTML 中nav是双标签元素(不同于imgbr等空元素),漏写闭合标签会导致 DOM 树被浏览器隐式修正,地标的语义边界随之不可预期。

规则要点与前后挑战的衔接

把文档内容归纳为三条可复用的实践规则:

  1. 主要导航用nav包裹:页面顶部的站点菜单、页内锚点导航等「主导航链接」集合应放进nav,获得内置地标特性;
  2. nav不是链接容器:页脚等位置重复出现的站点辅助链接,交给footer地标即可,不要声明第二个nav
  3. 地标要成对闭合、数量克制:本挑战的 4 条断言(恰好一个nav、包裹完整ul、零div、开闭标签配对)本质上就是这三条规则的可执行版本。

完成本挑战后,footer 地标挑战 的 seed 代码会直接复用本挑战的解答作为起点:页头中已是headerh1nav结构,待改造的是页面底部那个包裹&copy; 2018 Camper Catdiv。可以看到课程设计上前一道挑战的 solution 就是后一道挑战的 seed,形成连续演进的页面语义化改造链。

延伸阅读(仓库内路径)

  • 挑战本体:587d7788367417b2b2512aa2.md
  • 模块结构与挑战顺序:applied-accessibility.json
  • 所属课程(superblock)配置:responsive-web-design.json
  • 前一道(header 地标):587d7787367417b2b2512aa1.md
  • 后一道(footer 地标):587d7788367417b2b2512aa3.md

课程仓库中的挑战文件采用统一的 Markdown 格式组织:frontmatter 声明idtitlechallengeType(本挑战为0,即经典 HTML/CSS 代码挑战)与dashedName,正文按--description----instructions----hints----seed----solutions--等标记分段,hints 中的 JS 片段即为平台侧的验收测试代码。理解这一格式后,你可以按同样方式在curriculum/challenges/english/blocks/下查阅任意一道挑战的知识点、验收逻辑与参考解答。

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询