导航

正如您在链接中了解到的,带有 <a> 元素和 href 属性会创建链接,用户可以通过点击或触摸来跟踪这些链接。在列表中,您学习了如何创建内容列表。在本模块中,您将了解如何将链接列表组合在一起以创建导航。

导航有几种类型,也有几种显示方式。文本中链接到同一网站内其他页面的命名锚点被认为是本地导航。本地导航由一系列链接组成,显示当前页面在网站结构中的层次结构,或者用户为到达当前页面而跟踪的页面,这称为面包屑导航。

页面的目录是另一种本地导航。包含指向网站上每个页面的分层链接的页面称为站点地图。指向网站顶级页面的导航(可能在每个页面上找到)称为全局导航。全局导航可以用多种不同的方式显示,包括导航栏、下拉菜单和飞出式菜单。同一个网站可能会根据视口大小以不同的方式显示其全局导航。

始终确保用户可以通过最少次数的点击导航到您网站上的任何页面,同时确保导航直观且不会让人感到不知所措。也就是说,对导航元素没有具体要求。MachineLearningWorkshop.com 是一个单页网站,在右上角有一个本地导航栏;多页网站通常将全局导航放在这里。

The Navigation module of Learn HTML.
如果您访问 web.dev 上的此页面,您会发现一些导航功能。标题上方有一个面包屑导航,一个“学习 HTML”目录,以及一个“本页内容”目录(取决于您的屏幕宽度)。

一些网站具有“跳到内容”链接,通常作为焦点顺序中的第一个元素。它可能看起来像这样

<a href="#main" class="skip-link button">Skip to main</a>

当点击或获得焦点并且用户按下 Enter 时,它会滚动页面并将焦点赋予具有 main ID 的元素,大概是主要内容。

<main id="main">

为了提高可用性和无障碍功能,重要的是让用户绕过在每个页面上重复的内容块,例如共享标题和主要导航项。使用跳过链接,当键盘用户按下 tab 时,他们可以快速转到页面上的新内容。这让他们可以避免必须通过广泛的菜单进行制表。

大多数设计师不喜欢页面顶部有这样一个链接的外观。从视图中隐藏该链接是可以的。但是,请记住,当链接获得焦点时(当键盘用户在页面上制表通过链接时会发生这种情况),该链接必须对用户可见。

仅在使用类似于 .visually-hidden:not(:focus):not(:active) 的选择器时,才在非聚焦和非活动状态下隐藏内容。

与所有链接文本一样,名称应清楚地表明链接将用户带往何处。链接目标应该是页面主要内容的开头。

目录

我们主要内容的第一个元素是 <h1> 标题,其中包含此页面的标题:<h1>Navigation</h1>。主标题后面是对此教程内容的简要描述。

On this page table of contents.
目录始终可见。

在较小的屏幕上,目录出现在标题之后。在较大的屏幕上,它显示在右对齐的侧边栏中。

用于导航部分的最佳元素是 <nav>。它会自动通知屏幕阅读器和搜索引擎,某个部分具有 navigation 的角色,这是一个地标角色。

包含 aria-label 属性以简要描述导航的目的。在本例中,由于该属性的值将与文本“本页内容”重复。要引用可见文本,请改用 aria-labelledby

使用 id,可能如下所示

<nav aria-labelledby="tocTitle">
  <p id="tocTitle">On this page</p>
...
</nav>

除了减少冗余之外,可见文本会被翻译服务翻译,而属性值可能不会。如果可能,如果存在提供足够标签的文本,请引用该文本而不是使用属性文本。

“本页内容”导航是目录。如果您想使用 aria-label,请提供该上下文,而不是重复可见文本

<nav aria-label="Table of Contents">
  <p>On this page</p>
...
</nav>

要在元素上提供可访问的名称,您不应包含元素的名称。屏幕阅读器会向用户提供元素的名称。例如,当使用 <nav> 元素时,请勿包含单词“navigation”,因为该信息已包含在语义元素中。

虽然导航项不必嵌套在列表中,但使用列表可以让屏幕阅读器用户知道导航中有多少列表项,即链接。

<nav aria-labelledby="tocTitle">
  <p id="tocTitle">On this page</p>
  <ul role="list">
    <li>
      <a href="#skip">Skip to content link</a>
    </li>
    <li>
      <a href="#toc">Table of contents</a>
    </li>
    <li>
      <a href="#bc">Page breadcrumbs</a>
    </li>
    <li>
      <a href="#ln">Local navigation</a>
    </li>
    <li>
      <a href="#global">Global navigation</a>
    </li>
  </ul>
</nav>

避免更改 Tab 键顺序

目录可能在较小屏幕上出现在标题之后,或者在右对齐的侧边栏中。包含两组相同的导航,仅显示一组,将是一种反模式。

我们已使用 CSS 将导航显示为宽度大于 1254 像素的页面上的侧边栏。

虽然用户习惯于内容是自适应的,并且在他们更改设备或增大字体大小时会更改位置,但他们不希望在这样做时 Tab 键顺序发生变化。页面布局应在整个站点中易于访问、可预测且一致。在这里,目录的位置是不可预测的。

面包屑导航提供辅助导航,以帮助用户了解他们在网站上的位置。面包屑导航通常指示当前文档的 URL 层次结构以及当前页面在网站结构中的位置。

从用户角度来看,网站结构可能与服务器上的文件结构不同,这没关系。用户不需要知道您如何组织文件,但他们确实需要能够在您的内容中导航。

面包屑导航让用户深入了解您网站的组织结构。这有助于用户导航到任何上级部分,而无需使用 back 功能返回到每个先前访问过的页面。

如果网站具有分层目录结构(web.dev 就是这种情况),则面包屑导航通常包括指向主页或主机名的链接,以及指向 URL 路径中每个目录的索引文件的链接。是否包含当前页面是可选的,并且需要稍加注意。

const url = new URL("https://webdev.ac.cn/learn/html/navigation");
const sections = url.hostname + url.pathname.split('/');
// "web.dev,learn,html,navigation"

面包屑导航的各个部分显示了从当前页面到主页的路径,显示了每个中间级别。

Breadcrumbs indicating the path to the Navigation page.

每个“学习 HTML”模块页面都有相同的面包屑导航,显示了 web.devLearn 部分中 HTML 课程的层次结构。

代码应类似于以下内容

<nav aria-label="breadcrumbs">
  <ol role="list">
    <li>
      <a href="/">web.dev</a>
    </li>
    <li>
      <a href="/learn">Learn</a>
    </li>
    <li>
      <a href="/learn/html">HTML</a>
    </li>
  </ol>
</nav>

<nav> 元素(一个地标角色)告诉辅助技术将面包屑导航呈现为页面上的导航元素。使用 aria-label 提供的“面包屑导航”的可访问名称将此导航与同一文档中的其他导航地标区分开来。

每个链接之间是一个内容分隔符。这些分隔符可以使用 CSS 生成,以显示在每个列表项之前,从第二个列表项开始。

[aria-label^="breadcrumbs" i] li + li::before {
  content: "";
  display: block;
  width: 8px;
  height: 8px;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
  rotate: 45deg;
  opacity: .8
}

屏幕阅读器“看不到”这些图标,这是最佳实践。面包屑导航链接之间的分隔符应从屏幕阅读器中隐藏。它们还必须与背景有足够的对比度,与页面上的任何其他文本和视觉元素相同。

我们的示例代码使用有序列表,这比无序列表更可取,因为项目是枚举的。添加了 role="list",因为某些 CSS display 属性值会删除某些元素的语义。

通常,面包屑导航中指向主页的链接应读取“主页”,而不是站点名称或站点徽标。由于面包屑导航位于文档顶部,因此可以理解为什么使用了这种反模式。

当前页面“导航”未包含在面包屑导航中。

当前页面

当当前页面包含在面包屑导航中时,文本最好不要是链接,并且应在当前页面的列表项上包含 aria-current="page"。如果未包含,则最好使用图标或其他符号指示后面的标题是当前页面。

让我们看一下面包屑导航的替代版本,其中采用了这种做法

<nav aria-label="breadcrumbs">
  <ol role="list">
    <li>
      <a href="/">Home</a>
    </li>
    <li>
      <a href="/learn">Learn</a>
    </li>
    <li>
      <a href="/learn/html">Learn HTML!</a>
    </li>
    <li aria-current="page">
      Navigation
    </li>
  </ol>
</nav>

面包屑导航可能与用户为到达当前页面而遵循的线性步骤不同。到目前为止遵循的步骤列表可以嵌套在 <nav> 中,但不应标记为面包屑导航。

本地导航

Learn HTML chapter navigation.

下一个导航组件在大多数中型和大型设备上显示在左侧边栏中,其中包含过滤器栏和指向“学习 HTML”中每个部分的链接。这些链接和过滤器栏是位置导航。

如果您在移动设备上访问此网站,或者屏幕较窄,则在加载此页面时,侧边栏会被隐藏。您可以使用顶部导航中的 访问它。

宽屏幕上的永久本地导航与窄屏幕上的本地导航之间的主要区别在于,箭头会引导您返回到主顶部导航,然后关闭导航。

指向此文档的链接看起来与本地导航中的其他链接相同。但是,它可以与其他链接略有不同的外观,以向有视觉障碍的用户指示这是当前页面。这种视觉差异应使用 CSS 创建。

也可以使用 aria-current="page" 属性标识当前页面。这会通知辅助技术,链接指向当前页面。

理想情况下,本地导航中此列表项的 HTML 应类似于以下内容

<li>
  <a aria-current="page" aria-selected="true" href="/learn/html/navigation">
    Navigation
  </a>
</li>

全局导航指向网站的顶级页面,并且在网站的每个页面上都相同。网站的全局导航也可能由选项卡组成,这些选项卡打开嵌套的链接列表,这些链接指向网站或其他菜单的所有子部分。它可能包括标题部分、按钮和搜索小部件。这些附加功能不是必需的。必需的是导航显示在每个页面上,并且在每个页面上都相同,当然,在指向当前页面的任何链接上都带有 aria-current="page"

全局导航提供了一种在应用程序或网站中的任何位置进行一致旅行的方式。Google 的网站在其页面顶部没有全局导航。Yahoo! 有。虽然所有主要的 Yahoo! 属性都有不同的样式,但大多数部分的内容是相同的。

A poorly-contrasted navigation header.
Yahoo! 导航,其中包括灰色背景上的黑色选择器。

新闻和体育全局导航标头的内容是相同的。但是,显示用户位于体育页面上的图标没有足够的对比度来使其可访问,即使对于视力完美的访问者也是如此。这两个部分都有一个全局导航,其下方有一个特定于部分的本地导航。

A well-contrasted navigation header, with a white picker on a black background.
这是一个导航的更好版本,具有更高的对比度。

与全局导航类似,页脚在所有页面上都应相同。但这是唯一的相似之处。全局导航允许从产品角度导航到站点的所有部分。页脚中的导航元素没有具体要求。

通常,页脚包括公司链接,例如法律声明、关于公司的信息、招聘页面以及指向相关外部来源(例如社交媒体)的链接。

此页面的页脚包含两组导航元素:一组三列的 web.dev 相关导航和一组单独的 Google 条款和隐私权导航。页脚导航包括如何为 web.dev 做贡献、web.dev 团队提供的相关内容以及外部社交媒体链接。

接下来,我们将了解标记数据表。

检查您的理解情况

测试您对导航的知识。

哪个元素用于标记网站的主要导航?

<navigation>
再试一次。
<breadcrumb>
再试一次。
<nav>
正确!

一个页面上可以有多个导航元素吗?

错误。
再试一次。
正确。
正确!