23. 使用导航菜单创建多页面

  • 打印

序言

在本篇文章中,我们将讨论网站导航和菜单。你们将了解到不同类型的菜单及如何在 HTML 中创建菜单。本文还将涉及导航菜单的可用性与可访问性。本文不会讲述对导航菜单进行样式化的内容,但会为本系列课程后面对应的 CSS 教程打下基础。本文中所使用的代码示例,可点击这里下载本文的内容目录如下:

HTML 中常用的菜单和导航术语有几种不同的类型,它们都与 linka(锚记)元素有密切的联系。概括地说:

  • link 元素描述多个文档间的关系。例如,通过链接你可以告诉用户代理当前的文档是一个由多个文档构成的课程的一部分,以及哪个文件是课程的目录。
  • 使用锚记(也称作 a )元素,你可以链接到另一个文档或当前文档的某个特定部分。锚记链接将由网站访问者使用任何可用的方式(鼠标、键盘、语音识别器……)激活,而不由“用户代理”自动跟踪。

如果你尚未阅读前面关于链接的文章关于列表的文章 ,我建议你去读一遍,为了避免重复,我将本文涉及到的一些信息放在这两篇文章中了。

锚记/链接并不会自己变成菜单——你需要对它们进行结构化和样式化,让浏览器和用户知道它们的功能是导航菜单,而不只是一组随机链接。如果网页的先后顺序不重要,你可以使用一个无序列表,如同这个无序列表菜单示例一样。

请注意,我为 ul 元素赋予了一个 id。这是为以后使用 CSS 对 ul 元素进行样式化,以及使用 JavaScript 为它添加专门的行为所提供一个钩子。使用 id,可以让其他技术很方便地选定 HTML 文档中的某个特定元素。

如果访问者遍历全部文档的先后顺序很重要,则需要使用一个有序列表。举个例子,假如你有一个由多个文档组成的在线课程,且课程是循序渐进的,那么你就可以使用一个有序列表,如同这个有序列表示例一样。

列表是创建导航菜单非常好的方式,原因包括:

  • 所有 HTML 都包含在一个单独的列表元素(如 ul 元素)中,这意味着你可以使用 CSS 中的层叠为各个元素设置不同的样式,而且便于用 JavaScript 自上而下地访问某个元素。
  • 列表可以嵌套,这意味着你可以容易地创建多层次的导航结构。
  • 即使没有为列表应用任何样式,浏览器对 HTML 的渲染也能让导航菜单一目了然,并易于让访问者知道这些链接构成一个逻辑单元,都是导航菜单的一部分。

在嵌套列表时,应当把嵌套的列表嵌 li 元素之中,而不是之后。这里是两个正确的和不正确的嵌套列表代码的示例

请注意,在浏览器中这两个列表显示出来的样子是一样的。但浏览器中显示出来的样子绝不应是衡量代码质量的标准。像上面那个不正确示例中的无效 HTML 结构将很难被样式化或是使用 JavaScript 为其添加行为,也难以转换成其他格式。嵌套的 UL 元素,其结构应为 <ul><li><ul><li></li></ul></li></ul>,而绝不应是 <ul><li></li><ul><li></li></ul></ul>

对灵活性的需要

网站的导航菜单一般不会长久保持不变——随着新功能的添加和用户群的增长,网站也会有系统地逐步扩展。因此,当你在创建导航菜单时,应随着站点发展而为菜单项的添加和删除留有余地,并为导航菜单被翻译成不同的语言(因此链接的长度将发生变化)预留出空间。此外,你还可能遇到这种情况:网站的导航菜单的 HTML 是由服务器端语言动态地创建的,而不是由静态的 HTML 创建的。当然这并不意味着 HTML 知识就已过时;实际上它甚至变得更为重要了,因为你仍然需要为服务器端的脚本创建 HTML 模板。

不同类型的导航菜单

当你在构建不同的网站时,有多种不同类型的导航菜单需要用 HTML 创建。多数导航菜单可使用列表来创建,不过有时候界面限制会让你不得不采用其他的方式来创建导航菜单(后面有详细介绍)。使用列表方式可创建的导航菜单包括:

  • 页面内导航:例如单个网页的目录,带有指向页面内不同部分的链接。
  • 网站导航:整个网站(或网站某个部分)的导航栏,带有指向网站内不同网页的链接。
  • 内容上下文导航:一张链接列表,指向与当前页面的主题密切相关的网页(同一网站上或其他网站上的网页)的链接列表。
  • 网站地图:指向网站所有不同页面的大型链接列表,并且为便于访问,它会被划分为相关的子列表。
  • 分页:指向与当前文档一起作为某个完整文档的章节或部分的其他网页的链接,例如,一篇文章的第 1 部分、第 2 部分、第 3 部分等。

页面内导航(目录)

在前面那篇讲述链接的文章中,我已经介绍过一部分关于页面内导航的内容,以下我将详细介绍页面内导航的功能以及如何创建好的页面内导航。

页面内导航示例中,我使用了一个链接列表来指向页面内其它内容的锚记。为把锚记连接起来,你需要为导航的锚记元素赋予一个 id 属性以及一个 href 属性,该属性由一个 # 符号和该链接要指向的那个元素的 id 属性值相同的名称构成。页面的每一部分都有一个按相同方式工作的“返回导航菜单”的链接,只不过链接指向的是导航菜单本身。

从技术上讲,要让页面内导航正常工作,像上面这样做就已经够了。不过由于 Internet Explorer 浏览器存在一个令人郁闷的漏洞,你还不得不多做一点工作。

你们可以按以下步骤,来对 Internet Explorer 浏览器的这个漏洞进行试验:

  1. 用 IE6 或 IE7 打开这个示例文档
  2. 不使用鼠标,而是使用键盘来导航文档。你可以使用 TAB 键从一个链接跳转到另一个链接,使用 Enter 键激活链接——以此跳转到链接所指向的页面部分。
  3. 当你这样做的时候,似乎一切正常——浏览器往下滚动到你想要跳转到的页面部分。
  4. 这时如果你再次敲击 TAB 键,浏览器应该将你带回到(聚焦在)你选择的页面部分之内的第一个链接,但 IE 浏览器会把你带回页面顶部的导航菜单!

造成这个问题的原因非常复杂,而且涉及到 IE 浏览器对自己的一个叫做 hasLayout 的特殊属性的处理方式。你可采用几种方法来触发这个漏洞,参见 Ingo Chao 那篇“关于布局处理”的出色文章。最简单的方法是使用 CSS 设置 div 元素的宽度,我在示例中就是这么做的。这就是 IE 想要的——让锚记处于带有 hasLayout 属性的元素之内。

不得不做这样的额外工作让人有点郁闷,不过如果你想为页面不同的区段设置不同的样式的话,这对你还是有帮助的。这也有助于解决 HTML 中标题的问题:即标题中不包含自己所应用到的区段,并且假定一个标题至下一个标题之间的所有内容都属于同一个页面区段。这样不加入 <div> 元素就无法为页面的不同区段设置不同的样式。其他一些标记语言提倡采用一个包裹有 <title> 标签的 <section> 元素,这与可让你标记表单的某些部分,就如同 <fieldset> 元素和 <legend> 元素一样。

附注:在 Opera 浏览器中使用键盘进行页面导航的方式稍微有些不同——你可以试试在 Opera 浏览器中打开以上那个示例页面,然后按住 Shift 键并使用箭头键来导航各个链接(这种方式也适用于导航表单元素)。这被称为空间导航。

网站导航栏很可能是你所需要创建的最见的导航菜单。它是整个网站(或网站某个部分)的导航菜单,指明网站访问者可选择访问的链接,并显示网站的结构。采用列表是创建网站导航菜单最好的方式,就如你在这个网站导航菜单示例中所看到的那样。

这个示例中并没什么让人惊奇的东西,至少从纯 HTML 的角度来看是没有什么好惊奇的。在后面的课程中,我们将讨论使用 CSS 为这类导航菜单添加样式以及使用 JavaScript 为它们添加行为。如何在导航菜单中强调显示当前页面、如何让用户感到自己正处于一个特别的位置、并且他们正在移动位置(即使他们只是端坐在电脑前,当然如果他们使用移动设备上网则确实是在移动位置),这些是需要考虑的重点问题,下面我将讨论这些问题。

让网站访问者感到“我在这里”

Web 开发和导航的一条基本原则就是当前文档绝不应与自身链接,而应与导航菜单上的其他条目有明显的区别。这会使访问者愿意在网站上停留,并知道自己现在正处于网站的哪个位置上。除极少数例外的 web 应用程序、博客上的永久链接以及所谓“只有一个页面”的网站等,在 99% 的情况下,创建指向访问者正在阅读的文档的链接都是多余的,况且这么做还会把访问者搞糊涂。

在前面那篇关于链接的专题文章中,我已经讲过,链接是一项协议,也是一项义务:通过链接你向访问者提供了一种方式,使得他们能获取所需的更多信息,但你在创建链接时需要格外小心——如果链接没有为访问者提供他们所想要的信息,或是导致了意料之外的行为的话,你将失去自己的信誉和访问者对你的信任。例如,你提供了一个指向当前文档的链接,激活这个链接将重新载入这个文档。用户是不希望有这样的链接的——点击它有什么用呢?这只会把用户搞糊涂。

这就是为什么绝不应通过导航菜单链接到当前页面的原因之所在。你可以将它从导航菜单中完全删掉,也可以不再将其作为链接,只仅仅强调显示当前页面(例如把它包裹在 strong 元素之中)——这样就可以告诉用户他们正在访问当前页面,并告诉盲人访问者这是重要内容,而且是导航菜单中的当前词条——你可以点击这里查看强调显示当前页面的示例

每次你应给用户几个链接选项?

另一个值得考虑的问题是你想给用户几个选项。你可以看到很多网站的导航菜单都试图确保网站的每一个页面都可以通过同一个导航菜单来访问。这就是脚本处理和 CSS 技巧之所在——让导航菜单的一些部分隐藏起来,直至用户选中了某些区域时才显示(有时被称为下拉菜单)。仅从技术角度上看,这是聪明的做法,但是使用这种方法存在以下一些问题:

  • 不是所有访问者都能按预期的那样使用这种聪明的花招,例如,使用键盘的用户就不得不使用 TAB 键在页面上所列出的全部链接中一个一个地寻找他们想访问的某个链接。
  • 使用这种方法创建导航菜单,你需要向网站内的每个文档添加许多 HTML 代码,对于许多页面来说这些代码的一大部分都是多余的。如果我仅需通过 3 个层级的链接就能访问到一个我想阅读的文件,那么我就不需要看到链接到第4、5、6层级的选项。
  • 如果你同时为用户提供了太多的选项,可能会让他们感到无所适从——人们都不喜欢做出决策。想一想从一个很长的餐馆菜单中选择想点的菜品可能要花多长时间,你就明白这个道理了。
  • 如果页面上内容不多,却有大量的链接,那么搜索引擎就会假定该页面内没有多少有效的信息,也就不会去关注这个页面,从而导致搜索网络的时候很难找到这个页面。

总的来说,在导航菜单上放入多少个条目是完全由你自己决定——不同的设计会要求做出不同的选择——不过如果你拿不准的话,你应当试着仅在导航菜单中列入那些指向网站各主要部分的链接。因为如果需要的话,你总是可以再创建子菜单的。

上下文导航菜单

上下文导航菜单是基于当前文档的内容的相关链接,提供与当前正在访问页面相关的更多信息。一个经典的例子就是在新闻的底部经常可以看到的“相关文章”链接,如图 1 所示。

Screenshot of a contexual menu, in this case related news items

图 1:上下文导航菜单的一个例子——在新闻的底部放置的相关新闻条目的链接。

这与在软件用户界面中的上下文菜单略有不同,软件中的上下文菜单会根据不同的访问目的提供不同的选项(就如同在桌面应用程序中可以看到的右键菜单,或者按住 Ctrl 单击左键的弹出菜单那样,它会根据当前鼠标的位置而提供专门的选项)。

在网站上使用上下文导航菜单,是推广网站其它部分上的内容的好方式,但从 HTML 方面来讲,它们只是另一个链接列表。

网站地图

网站地图可能正是你所期望的——网站所有网页(如果网站是大型网站,则是网站的主要部分)的地图。网站地图让访问者可以大致了解网站的总体结构,并访问他们想要快速访问的页面——即使该页面在页面层级中处在很深的位置。

对于向访问者提供在网站内找不到方向时的后备选项,以及为那些匆忙的访问者提供快速的入口,网站地图和站内搜索都是非常好的方式。

从 HTML 代码的角度看,网站地图可以是一个大型的充满链接的嵌套列表,或者——对大型网站而言——则是网站各部分的标题(带有各部分自身层级的嵌套链接)或者是每个部分的搜索表单。

分页

当需要为分割成多个页面的大型文档提供导航方式时,分页菜单是必须用到的。在大型的图像库网站或搜索结果网页(如 Google 或 Yahoo 搜索)中,你们都可以看到分页菜单的例子。

分页菜单与其他类型的导航有所不同,因为它们通常是链接回同一个文档的——不过有一个带有更多信息(如从哪一个页面开始)的链接。图 2 中就是一些分页菜单的例子:

Different types of pagination menus

图 2:分页菜单可以让访问者在浏览大型的数据集时,知道自己正在访问的页面的位置。

分页菜单的 HTML 代码不是什么开创性的东西——这里你又一次提供了一个包括当前链接的链接列表(指明正在显示的是哪一个数据块或者当前页面所处的位置),其中当前链接未与自身相链接,而是被强调显示(例如通过 strong 元素)。

分页菜单和网站导航菜单的区别在于,分页菜单要使用大量的编程逻辑。依据当前页面在数据集中的位置,你需要显示或隐藏前一个、后一个、第一个、最后一个链接。如果确实有数量非常庞大的信息需要导航,你会希望提供到标志性页面如第100页、第200页等页面的链接,以及其他更多的选项。在这种情况下,你可能不大会像那些在 HTML 中的菜单一样创建硬编码菜单,而可能会选择在服务器端创建它们——但编写规则还是一样的,即当前页面不应该与自身相链接,也不应有无效链接。

当列表不够用时——图像映射和表单

在 99% 的情况下,使用 HTML 无序列表或有序列表创建导航菜单就已经足够了,尤其是因为列表的逻辑顺序和嵌套还允许使用 CSS 为列表设置很好看的样式。不过在另一些情况下,可能需要采用不同的设计技巧。

使用图像映射设置热点

技巧之一就是客户端的图像映射。图像映射通过将图像的区域变为可以链接到不同文档的交互式区域,由此可以将一幅图像变成一个导航菜单。本部分所附的图像映射的示例,就把一个图像变为可点击的导航菜单。你可以对这个示例进行试验,请点击上面那个链接,并点击图像中的三角形(如图 3 所示)的各个部分。

Screenshot of an image with hotspots

图 3:通过使用 area 元素定义图像映射,你可以把一个图像的区域变为交互式元素。

你可以通过将一个图像映射定义为不同的区域(也被称为热点),把任何一个图像变成一个导航菜单。当你为图像映射赋予一个 name 属性,并在 img 元素中使用 usemap 属性时,就把图像与映射关联了起来。请注意,这种做法很像页面内的链接,意味着你需要在 usemap 属性的值前加上 # 符号。

每个区域应该有以下几个属性:

href
定义该区域须链接到的 URL 地址(或同一文档内的目标)
alt
定义在图像无法找到或用户代理不支持图像时所显示的替代文本
shape
定义区域的形状。长方形可使用 rect,圆形可使用 circle,定义为多边形的不规则区域可使用 poly
coords
定义图像中那些应成为热点的坐标——坐标值从图像的左上角开始算起,并可以像素或百分比衡量。对于长方形,你只需定义其左上角和右下角;对于圆形,你只需定义圆心和半径;对于多边形,你需要提供所有顶点的列表。

用 HTML 定义和加入图像映射是比较枯燥的,因此一些图像处理工具如 Adobe Image Ready 或 Fireworks 都提供了可视化创建图像映射的选项(它们会替你生成 HTML)

使用表单节省屏幕空间并防止链接过多

另一种技巧是使用 select 元素创建一个表单。你可以把不同的页面定义为 select 元素内的选项,这样访问者可以选定一个选项,然后提交表单,以跳转到不同的页面。你可以点击此处查看实际运行的表单导航菜单的示例

使用表单菜单最明显的优点是可以在不占用大量屏幕空间的情况下,提供大量的链接选项。浏览器会将表单菜单渲染成一行,如图 4 所示。

Screenshot of a menu created with a select box, open and closed

图 4:表单菜单在屏幕上只占据一行。

你还可以对表单菜单进一步进行处理,使用 optgroup 元素将菜单选项分组,如这个 optgroup 示例所示的那样。

在分组后,表单菜单将变为如图 5 所示的样子,其中分组的名称是不能选定的选项。

Screenshot of a menu created with a select boxincluding option groups

图 5:表单菜单可以将选项分组,以告诉访问者哪些选项属于同一个分组。以上为表单菜单在 Opera 9.5 浏览器中的渲染效果。

这个技巧具有只占用很小的页面空间的优点,不过也意味着你需要用一个服务器端脚本把访问者带到所选定的页面。你也可以使用 JavaScript 来让菜单中的链接生效,但你不能假定 JavaScrip 就一定可用——你得确保用户在 JavaScript 禁用的情况下还是能够使用这个菜单。

使用表单菜单还有另一个不那么显而易见的优点,即你不再需要在同一个文档内提供太多的链接。这意味着你就不会让那些使用辅助技术上网的用户无所适从了(他们常常是只能面对一个又长又大的列表中的链接)。同时也不会因链接到文本的比例而让文档显得像一个站点地图,从而使搜索引擎认为那些链接是没有价值的。不过很多辅助技术都可以生成一个页面链接的地图,如果重要的链接都在表单菜单中,那么使用辅助技术的用户就有可能失去发现这些链接的机会。因此,一个好的做法是既提供指向主要目标页面的锚记链接,又使用 select 元素创建表单菜单,以提供更多的链接选项。这样访问者将可以使用这些链接,而机器如搜索引擎机器人则不必知道这些链接的存在。

关于 HTML 导航菜单,最后需要指出的一点是,菜单放在页面的哪个位置是相当重要的。因为访问者可能没有滚动机制或可能有视力障碍,只能依靠键盘导航来访问网站。在他们载入文档时,首先将遇到的是文档地址和标题,然后至上而下地阅读文档,在遇到每个链接时都会停下,并询问访问者是否要跟踪该链接。其他选项还包括获取一个所有链接的列表或从一个标题跳转到另一个标题。

如果导航菜单位于文档顶部,那么它将是用户首先遇到的页面元素。在能读到任何内容之前,还得一个一个地跳过 15 或 20 个链接,这会让他们感到相当郁闷。要解决这个问题,有两个变通方法:第一,你可以把导航菜单放在文档主要内容之后(如果你愿意,依然可以使用 CSS 将菜单放置在页面顶部)。第二,你可以提供一个跳过链接。跳过链接是一个放置在主菜单之前,能直接链接到内容开始之处的链接,它可以让访问者跳过菜单而直接阅读内容。你还可以在文档的末尾添加另一个“回到菜单”的链接,让访问者可以轻松地返回文档顶部。点击这里,可查看跳过链接的示例

跳过链接不仅对残疾人有用,而且也有助于使用小屏幕移动设备上网的用户更方便地进行站点导航。

总结

在本篇文章中,我介绍了可能用 HTML 来编写的不同类型的导航菜单。我们讨论了:

  • 为什么带有锚记的列表是定义导航菜单的最佳 HTML 构造
  • 为什么说不要把导航菜单看成是一成不变的,而要为其预留改动的空间是很重要的
  • 页面内导航:链接到当前文档的各个部分,并返回导航菜单
  • 网站导航:提供一个显示当前站点的网页及它们的层级结构的导航菜单;我还介绍了为什么强调显示用户正在访问的当前页面是很重要的
  • 上下文导航:提供链接到当前网站(或其他网站上)的相关页面的链接
  • 网站地图:向那些在网站内找不着北的访问者或有特定需要的访问者提供的再定位工具
  • 分页:让访问者可以导航一个被分割为多个页面的文档
  • 图像映射:通过在图像上添加热点来创建图像菜单
  • 表单菜单:提供很多链接选项,而且不会占用大量页面空间,也不必在页面上放置太多链接
  • 跳过链接以及导航菜单的摆放位置

在本教程后面的 CSS 部分,我们还将回到上述某些内容,来介绍如何使用 CSS 让 HTML 结构的外观显得好看,并更明显地作为菜单展示在访问者的眼前。

练习题

  • 为什么说将导航菜单标记为列表是一个好主意?
  • 当你在设计一个导航菜单时,你需要为未来做哪些规划?
  • 使用 select 元素创建表单有哪些优点,又可能导致出现哪些问题?
  • 你用 area 元素来定义什么,该元素的 nohref 属性有什么用处?(这未在本篇文章中介绍,你需要上网搜索资料并研究)
  • 跳过链接有哪些优点?