Skip to content

nav 导航

<nav> 元素表示页面的导航区域,包含一组导航链接。它是 HTML5 中最重要的语义化标签之一,让屏幕阅读器用户能够快速跳转到站点的不同部分,也帮助搜索引擎理解站点的链接结构。

前置知识

阅读本节前,建议先了解:header 页眉

基础概念

什么是 nav

<nav> 用于包裹页面中主要的导航链接集合。一个页面可以有多个 <nav> 元素,例如全局导航、面包屑导航、侧边栏导航等。浏览器和辅助技术会将 <nav> 识别为导航 landmark,提供快速导航功能。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>nav 导航示例</title>
</head>
<body>
  <!-- 全局主导航 -->
  <nav aria-label="主导航">
    <ul>
      <li><a href="/">首页</a></li>
      <li><a href="/about">关于</a></li>
      <li><a href="/blog">博客</a></li>
      <li><a href="/contact">联系</a></li>
    </ul>
  </nav>

  <!-- 页面主内容 -->
  <main>
    <article>
      <h1>文章标题</h1>
      <p>文章内容...</p>
    </article>
  </main>

  <!-- 页脚导航 -->
  <footer>
    <nav aria-label="页脚链接">
      <a href="/privacy">隐私政策</a>
      <a href="/terms">使用条款</a>
    </nav>
  </footer>
</body>
</html>
属性说明
隐式角色navigation自动映射为导航 landmark
可访问名称无(需要 aria-label 或 aria-labelledby)区分页面中多个 nav

<nav> 并不是用来包裹所有链接的。只有当一组链接构成主要导航区块时才使用 <nav>

  • 应该使用 <nav>:主导航、面包屑、目录、分页导航
  • 不应使用 <nav>:页脚的法律链接、文章内引用链接、广告链接、标签云

语法与使用

基本语法

html
<nav [aria-label="描述"] [aria-labelledby="id"]>
  <!-- 导航链接列表 -->
  <ul>
    <li><a href="/link1">链接1</a></li>
    <li><a href="/link2">链接2</a></li>
  </ul>
</nav>

<nav> 内部可以包含任何流内容,但最常见的模式是使用列表:

html
<!-- 模式 1:无序列表(最推荐) -->
<nav aria-label="主导航">
  <ul>
    <li><a href="/">首页</a></li>
    <li><a href="/about">关于</a></li>
  </ul>
</nav>

<!-- 模式 2:直接链接 -->
<nav aria-label="快速链接">
  <a href="#section1">第一节</a>
  <a href="#section2">第二节</a>
  <a href="#section3">第三节</a>
</nav>

<!-- 模式 3:带分组的链接 -->
<nav aria-label="分类导航">
  <details>
    <summary>前端开发</summary>
    <ul>
      <li><a href="/html">HTML</a></li>
      <li><a href="/css">CSS</a></li>
      <li><a href="/js">JavaScript</a></li>
    </ul>
  </details>
</nav>

详细说明

主导航 vs 辅助导航

页面中通常有以下类型的导航:

导航类型位置aria-label 示例是否必须
全局导航header 中"主导航"推荐
面包屑内容区顶部"面包屑"推荐
章节目录aside 中"目录"可选
页脚链接footer 中"页脚导航"推荐
分页导航列表底部"文章分页"可选
上下篇导航文章底部"文章导航"可选
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多导航示例</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }

    /* 页面头部 */
    .site-header {
      background: #2d3748;
      color: #fff;
      padding: 1rem 2rem;
    }

    .header-inner {
      display: flex;
      align-items: center;
      justify-content: space-between;
      max-width: 1200px;
      margin: 0 auto;
    }

    .site-name { font-size: 1.25rem; font-weight: 700; }

    /* 全局导航样式 */
    .global-nav ul {
      list-style: none;
      display: flex;
      gap: 1.5rem;
    }

    .global-nav a {
      color: #cbd5e0;
      text-decoration: none;
      font-size: 0.9rem;
      transition: color 0.2s;
    }

    .global-nav a:hover { color: #fff; }

    /* 面包屑样式 */
    .breadcrumb {
      max-width: 1200px;
      margin: 1rem auto;
      padding: 0 2rem;
    }

    .breadcrumb ol {
      list-style: none;
      display: flex;
      gap: 0.5rem;
      font-size: 0.85rem;
      color: #718096;
    }

    .breadcrumb li + li::before {
      content: ">";
      margin-right: 0.5rem;
      color: #a0aec0;
    }

    .breadcrumb a {
      color: #4299e1;
      text-decoration: none;
    }

    /* 内容区布局 */
    .content-layout {
      max-width: 1200px;
      margin: 1rem auto;
      padding: 0 2rem;
      display: grid;
      grid-template-columns: 1fr 250px;
      gap: 2rem;
    }

    /* 侧边目录 */
    .toc { background: #f7fafc; padding: 1rem; border-radius: 8px; }
    .toc h2 { font-size: 1rem; margin-bottom: 0.75rem; color: #2d3748; }
    .toc ul { list-style: none; }
    .toc li { margin-bottom: 0.5rem; }
    .toc a { color: #4a5568; text-decoration: none; font-size: 0.85rem; }
    .toc a:hover { color: #4299e1; }

    /* 文章导航(上下篇) */
    .post-nav {
      max-width: 1200px;
      margin: 2rem auto;
      padding: 0 2rem;
      display: flex;
      justify-content: space-between;
    }

    .post-nav a {
      color: #4299e1;
      text-decoration: none;
    }

    /* 页脚 */
    .site-footer {
      background: #2d3748;
      color: #a0aec0;
      text-align: center;
      padding: 1.5rem 2rem;
      margin-top: 2rem;
    }

    .footer-nav {
      margin-bottom: 0.75rem;
    }

    .footer-nav a {
      color: #cbd5e0;
      text-decoration: none;
      margin: 0 0.5rem;
      font-size: 0.85rem;
    }
  </style>
</head>
<body>
  <!-- 全局导航(主导航) -->
  <header class="site-header">
    <div class="header-inner">
      <div class="site-name">TechBlog</div>
      <nav class="global-nav" aria-label="主导航">
        <ul>
          <li><a href="/">首页</a></li>
          <li><a href="/tutorials">教程</a></li>
          <li><a href="/articles">文章</a></li>
          <li><a href="/tools">工具</a></li>
          <li><a href="/about">关于</a></li>
        </ul>
      </nav>
    </div>
  </header>

  <!-- 面包屑导航 -->
  <nav class="breadcrumb" aria-label="面包屑">
    <ol itemscope itemtype="https://schema.org/BreadcrumbList">
      <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
        <a itemprop="item" href="/"><span itemprop="name">首页</span></a>
        <meta itemprop="position" content="1">
      </li>
      <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
        <a itemprop="item" href="/tutorials"><span itemprop="name">教程</span></a>
        <meta itemprop="position" content="2">
      </li>
      <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
        <a itemprop="item" href="/tutorials/html"><span itemprop="name">HTML</span></a>
        <meta itemprop="position" content="3">
      </li>
      <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
        <span itemprop="name">语义化标签</span>
        <meta itemprop="position" content="4">
      </li>
    </ol>
  </nav>

  <!-- 主内容区 -->
  <div class="content-layout">
    <main>
      <article>
        <h1>HTML5 语义化标签教程</h1>
        <p>本文详细介绍了 HTML5 语义化标签的使用方法...</p>
      </article>

      <!-- 文章上下篇导航 -->
      <nav class="post-nav" aria-label="文章导航">
        <a href="/prev-article">&larr; 上一篇:HTML 表单基础</a>
        <a href="/next-article">下一篇:CSS Grid 布局 &rarr;</a>
      </nav>
    </main>

    <!-- 侧边目录导航 -->
    <aside>
      <nav class="toc" aria-label="文章目录">
        <h2>目录</h2>
        <ul>
          <li><a href="#section1">什么是语义化</a></li>
          <li><a href="#section2">语义化标签介绍</a></li>
          <li><a href="#section3">最佳实践</a></li>
          <li><a href="#section4">常见问题</a></li>
        </ul>
      </nav>
    </aside>
  </div>

  <!-- 页脚导航 -->
  <footer class="site-footer">
    <nav class="footer-nav" aria-label="页脚导航">
      <a href="/privacy">隐私政策</a>
      <a href="/terms">使用条款</a>
      <a href="/sitemap">网站地图</a>
      <a href="/rss">RSS 订阅</a>
    </nav>
    <p>&copy; 2024 TechBlog. All rights reserved.</p>
  </footer>
</body>
</html>

aria-label 区分多个 nav

当页面有多个 <nav> 时,必须使用 aria-labelaria-labelledby 来区分它们,否则屏幕阅读器用户无法区分不同的导航区域:

html
<!-- 错误:多个 nav 没有 aria-label,屏幕阅读器只能读到 "navigation" -->
<nav>
  <ul><li><a href="/">首页</a></li></ul>
</nav>
<nav>
  <ul><li><a href="/privacy">隐私政策</a></li></ul>
</nav>

<!-- 正确:每个 nav 都有描述性的 aria-label -->
<nav aria-label="主导航">
  <ul><li><a href="/">首页</a></li></ul>
</nav>
<nav aria-label="页脚导航">
  <ul><li><a href="/privacy">隐私政策</a></li></ul>
</nav>

<!-- 也可以使用 aria-labelledby 引用可见的标题 -->
<nav aria-labelledby="toc-title">
  <h2 id="toc-title">目录</h2>
  <ul>
    <li><a href="#s1">第一节</a></li>
  </ul>
</nav>

何时使用 nav

使用 <nav> 的判断标准:

适合使用 <nav> 的场景:

html
<!-- 1. 主导航 -->
<nav aria-label="主导航">...</nav>

<!-- 2. 面包屑 -->
<nav aria-label="面包屑">...</nav>

<!-- 3. 目录/索引 -->
<nav aria-label="文章目录">...</nav>

<!-- 4. 分页 -->
<nav aria-label="分页">
  <a href="/page/1">1</a>
  <a href="/page/2">2</a>
  <a href="/page/3">3</a>
</nav>

<!-- 5. 上下文导航(上一篇/下一篇) -->
<nav aria-label="文章导航">...</nav>

<!-- 6. 语言切换 -->
<nav aria-label="语言选择">
  <a href="/en">English</a>
  <a href="/zh">中文</a>
</nav>

不适合使用 <nav> 的场景:

html
<!-- 1. 文章内的引用链接(太多 nav 会干扰导航) -->
<p>更多信息请参考 <a href="https://example.com">MDN 文档</a>。</p>

<!-- 2. 页脚的少量法律链接 -->
<footer>
  <p>
    <a href="/privacy">隐私政策</a> |
    <a href="/terms">使用条款</a>
  </p>
</footer>

<!-- 3. 社交媒体图标链接 -->
<div>
  <a href="#" aria-label="Twitter"><img src="twitter.svg" alt=""></a>
  <a href="#" aria-label="GitHub"><img src="github.svg" alt=""></a>
</div>

<!-- 4. 标签列表 -->
<div>
  <a href="/tag/html">HTML</a>
  <a href="/tag/css">CSS</a>
</div>

实战示例

电子商务网站导航

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>电商网站导航示例</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }

    /* 顶部工具栏 */
    .top-bar {
      background: #1a202c;
      color: #a0aec0;
      font-size: 0.8rem;
      padding: 0.4rem 2rem;
    }

    .top-bar-inner {
      max-width: 1200px;
      margin: 0 auto;
      display: flex;
      justify-content: space-between;
    }

    .top-bar nav a {
      color: #a0aec0;
      text-decoration: none;
      margin-left: 1rem;
    }

    .top-bar nav a:hover { color: #fff; }

    /* 主 header */
    .main-header {
      background: #2b6cb0;
      color: #fff;
      padding: 1rem 2rem;
    }

    .main-header-inner {
      max-width: 1200px;
      margin: 0 auto;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .brand {
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .brand-name { font-size: 1.5rem; font-weight: 700; }

    /* 分类导航 */
    .category-nav {
      background: #2c5282;
    }

    .category-nav-inner {
      max-width: 1200px;
      margin: 0 auto;
      padding: 0 2rem;
    }

    .category-nav ul {
      list-style: none;
      display: flex;
      gap: 0;
    }

    .category-nav li {
      position: relative;
    }

    .category-nav a {
      display: block;
      color: #bee3f8;
      text-decoration: none;
      padding: 0.75rem 1.25rem;
      font-size: 0.9rem;
      transition: background 0.2s;
    }

    .category-nav a:hover {
      background: rgba(255,255,255,0.1);
      color: #fff;
    }

    /* 面包屑 */
    .breadcrumb {
      max-width: 1200px;
      margin: 1rem auto;
      padding: 0 2rem;
    }

    .breadcrumb ol {
      list-style: none;
      display: flex;
      gap: 0.5rem;
      font-size: 0.85rem;
      color: #718096;
    }

    .breadcrumb li + li::before {
      content: ">";
      margin-right: 0.5rem;
    }

    .breadcrumb a { color: #3182ce; text-decoration: none; }

    /* 分页 */
    .pagination {
      max-width: 1200px;
      margin: 2rem auto;
      padding: 0 2rem;
      text-align: center;
    }

    .pagination ul {
      list-style: none;
      display: inline-flex;
      gap: 0.25rem;
    }

    .pagination a, .pagination span {
      display: inline-block;
      padding: 0.5rem 1rem;
      border: 1px solid #e2e8f0;
      border-radius: 4px;
      text-decoration: none;
      color: #4a5568;
      font-size: 0.9rem;
    }

    .pagination a:hover { background: #ebf8ff; border-color: #bee3f8; }

    .pagination .current {
      background: #3182ce;
      color: #fff;
      border-color: #3182ce;
    }
  </style>
</head>
<body>
  <!-- 顶部工具栏导航 -->
  <div class="top-bar">
    <div class="top-bar-inner">
      <span>欢迎来到 ShopMall</span>
      <nav aria-label="账户导航">
        <a href="/login">登录</a>
        <a href="/register">注册</a>
        <a href="/orders">我的订单</a>
        <a href="/wishlist">收藏夹</a>
      </nav>
    </div>
  </div>

  <!-- 主头部 + 搜索导航 -->
  <header class="main-header">
    <div class="main-header-inner">
      <div class="brand">
        <span class="brand-name">ShopMall</span>
      </div>
      <nav aria-label="用户操作导航">
        <a href="/cart">购物车(3)</a>
        <a href="/help">帮助中心</a>
      </nav>
    </div>
  </header>

  <!-- 商品分类导航 -->
  <nav class="category-nav" aria-label="商品分类">
    <div class="category-nav-inner">
      <ul>
        <li><a href="/electronics">数码电子</a></li>
        <li><a href="/clothing">服装鞋帽</a></li>
        <li><a href="/home">家居生活</a></li>
        <li><a href="/books">图书音像</a></li>
        <li><a href="/food">食品生鲜</a></li>
        <li><a href="/beauty">美妆护肤</a></li>
      </ul>
    </div>
  </nav>

  <!-- 面包屑导航 -->
  <nav class="breadcrumb" aria-label="面包屑">
    <ol>
      <li><a href="/">首页</a></li>
      <li><a href="/electronics">数码电子</a></li>
      <li><a href="/phones">手机通讯</a></li>
      <li><span>智能手机</span></li>
    </ol>
  </nav>

  <main>
    <p>商品列表内容...</p>

    <!-- 分页导航 -->
    <nav class="pagination" aria-label="商品列表分页">
      <ul>
        <li><span class="current" aria-current="page">1</span></li>
        <li><a href="/phones?page=2">2</a></li>
        <li><a href="/phones?page=3">3</a></li>
        <li><a href="/phones?page=4">4</a></li>
        <li><a href="/phones?page=2">下一页 &rarr;</a></li>
      </ul>
    </nav>
  </main>
</body>
</html>

注意事项

常见错误

  1. 所有链接都用 nav 包裹<nav> 只用于主要导航区块,不是包裹链接的通用容器
  2. 缺少 aria-label:多个 nav 没有标签时,屏幕阅读器无法区分
  3. nav 内没有链接<nav> 应该包含导航链接,空 nav 没有意义
  4. 过度嵌套 nav:一个导航列表内不需要再嵌套另一个 nav
html
<!-- 错误:nav 内嵌套 nav(通常不合理) -->
<nav aria-label="主导航">
  <nav aria-label="子导航">
    <a href="#">链接</a>
  </nav>
</nav>

<!-- 如果确实需要分组,使用 section 或直接列表 -->
<nav aria-label="主导航">
  <section>
    <h2>前端</h2>
    <ul>
      <li><a href="/html">HTML</a></li>
      <li><a href="/css">CSS</a></li>
    </ul>
  </section>
</nav>

最佳实践

  1. 始终为 nav 添加 aria-label:即使是唯一的 nav 也建议添加,因为将来可能会增加更多 nav
  2. 使用列表结构<ul>/<li> 是导航最自然的结构,屏幕阅读器能播报"列表,共 N 项"
  3. 指示当前位置:使用 aria-current="page" 标记当前页面
  4. 面包屑使用 ol:面包屑是有序的,应该用 <ol> 而非 <ul>
  5. 分页使用 aria-label:帮助屏幕阅读器用户理解分页的目的

下一节

继续学习:main 主体内容

参考链接