main 主体内容
<main> 元素表示文档的主体内容区域。每个页面应该只有一个 <main> 元素,它包含了页面的核心内容,排除导航栏、侧边栏、页脚、Logo 等非主要内容。它是无障碍访问中最重要的 landmark 之一。
前置知识
阅读本节前,建议先了解:nav 导航
基础概念
什么是 main
<main> 是 HTML5 引入的语义化标签,用于包裹页面的主要内容。它的核心特征是唯一性——一个文档中只能有一个 <main> 元素。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>main 示例</title>
</head>
<body>
<header>...</header>
<!-- 主内容区域:整个页面唯一 -->
<main>
<h1>页面标题</h1>
<p>这是页面的主要内容...</p>
</main>
<footer>...</footer>
</body>
</html>main 的核心特征
| 特征 | 说明 |
|---|---|
| 唯一性 | 每个页面只能有一个 <main> 元素 |
| 隐式角色 | 自动映射为 ARIA main 角色 |
| Landmark | 屏幕阅读器识别为 "main" landmark,支持快捷键跳转 |
| 内容排除 | 不包含 header、footer、nav、aside 等重复性内容 |
| 可聚焦 | 可通过 id 属性作为 skip-to-content 的目标 |
语法与使用
基本语法
html
<!-- 基本用法 -->
<main>
<!-- 页面的核心内容 -->
</main>
<!-- 带有 id(用于 skip-to-content) -->
<main id="main-content">
<!-- 页面的核心内容 -->
</main>main 的位置
<main> 通常位于 <body> 的直接子元素中,在 <header> 之后、<footer> 之前:
html
<body>
<header>...</header>
<nav>...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>
</body>main 可以包含的内容
<main> 内部可以包含任何流内容,通常包括:
<article>—— 独立文章<section>—— 内容章节<aside>—— 与主内容相关的辅助信息<h1>-<h6>—— 标题<figure>—— 图表<p>、<ul>、<ol>、<table>等常规内容
详细说明
Skip-to-Content 跳转链接
<main> 最常见的无障碍应用是作为"跳转到主内容"链接的目标:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Skip-to-Content 示例</title>
<style>
/* Skip link:默认隐藏,Tab 聚焦时显示 */
.skip-link {
position: absolute;
top: -100%;
left: 0;
background: #0078d7;
color: #fff;
padding: 0.75rem 1.5rem;
z-index: 10000;
text-decoration: none;
border-radius: 0 0 4px 0;
transition: top 0.2s ease;
}
.skip-link:focus {
top: 0;
outline: 2px solid #fff;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.6;
}
.site-header {
background: #1a1a2e;
color: #fff;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
}
.site-nav ul {
list-style: none;
display: flex;
gap: 1rem;
margin: 0;
padding: 0;
}
.site-nav a {
color: #e0e0e0;
text-decoration: none;
padding: 0.5rem 1rem;
}
main {
max-width: 800px;
margin: 2rem auto;
padding: 0 2rem;
}
.site-footer {
background: #1a1a2e;
color: #999;
text-align: center;
padding: 1rem;
margin-top: 2rem;
}
</style>
</head>
<body>
<a class="skip-link" href="#main-content">跳转到主要内容</a>
<header class="site-header">
<h1>我的网站</h1>
<nav class="site-nav" aria-label="主导航">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
<li><a href="/blog">博客</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<h1>欢迎来到我的网站</h1>
<p>这是页面的主要内容区域。键盘用户可以通过 Tab 键聚焦到
"跳转到主要内容" 链接,然后按 Enter 直接跳过导航栏到达这里。</p>
<section>
<h2>最新文章</h2>
<article>
<h3>HTML5 语义化标签</h3>
<p>语义化标签让网页结构更清晰...</p>
</article>
<article>
<h3>CSS Grid 布局</h3>
<p>CSS Grid 是二维布局系统...</p>
</article>
</section>
</main>
<footer class="site-footer">
<p>© 2024 我的网站. 保留所有权利.</p>
</footer>
</body>
</html>main 的排除内容规则
<main> 不应包含以下内容:
| 排除内容 | 原因 |
|---|---|
| 站点级 header/footer | 在多个页面重复出现,不属于"主体" |
| 站点级导航 | 导航是辅助功能,不是页面主要内容 |
| 侧边栏广告 | 与主内容无直接关系的辅助内容 |
| 全局搜索框 | 全局搜索不属于特定页面的内容 |
html
<!-- 错误:main 内包含重复性内容 -->
<main>
<header>
<h1>网站名称</h1>
<nav>全局导航</nav>
</header>
<h1>文章标题</h1>
<p>文章内容...</p>
<footer>版权所有</footer>
</main>
<!-- 正确:main 只包含页面特有的内容 -->
<body>
<header>
<h1>网站名称</h1>
<nav>全局导航</nav>
</header>
<main>
<article>
<header>
<h1>文章标题</h1>
</header>
<p>文章内容...</p>
<footer>文章标签</footer>
</article>
</main>
<footer>版权所有</footer>
</body>main 与文章级 header/footer
<main> 内可以包含文章级别的 <header> 和 <footer>,因为它们属于内容本身的一部分:
html
<main>
<article>
<header>
<h2>文章标题</h2>
<time datetime="2024-01-15">2024 年 1 月 15 日</time>
</header>
<p>正文内容...</p>
<footer>
<p>作者:张三</p>
</footer>
</article>
</main>实战示例
博客文章页面的 main
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客文章 - main 示例</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, sans-serif; color: #333; }
.skip-link {
position: absolute; top: -100%; left: 0;
background: #0078d7; color: #fff;
padding: 0.5rem 1rem; z-index: 10000; text-decoration: none;
}
.skip-link:focus { top: 0; }
.page-header {
background: #2c3e50; color: #ecf0f1; padding: 1rem 2rem;
}
.page-header-inner {
max-width: 1000px; margin: 0 auto;
display: flex; justify-content: space-between; align-items: center;
}
.page-header nav a {
color: #bdc3c7; text-decoration: none; margin-left: 1.5rem;
}
.page-header nav a:hover { color: #fff; }
.page-body {
max-width: 1000px; margin: 2rem auto; padding: 0 2rem;
display: grid; grid-template-columns: 1fr 300px; gap: 2rem;
}
main article {
background: #fff; padding: 2rem;
border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
main article header {
margin-bottom: 1.5rem; border-bottom: 1px solid #eee; padding-bottom: 1rem;
}
main article header h1 { font-size: 1.75rem; margin-bottom: 0.5rem; }
.article-meta { color: #7f8c8d; font-size: 0.875rem; }
main section { margin: 2rem 0; }
main section h2 { color: #2c3e50; margin-bottom: 1rem; }
main article footer {
margin-top: 2rem; padding-top: 1rem;
border-top: 1px solid #eee; color: #95a5a6; font-size: 0.9rem;
}
/* 侧边栏不在 main 内 */
.sidebar { display: flex; flex-direction: column; gap: 1.5rem; }
.sidebar-widget {
background: #f8f9fa; padding: 1.25rem; border-radius: 8px;
}
.sidebar-widget h3 { font-size: 1rem; margin-bottom: 0.75rem; color: #2c3e50; }
.sidebar-widget ul { list-style: none; }
.sidebar-widget li { margin-bottom: 0.5rem; }
.sidebar-widget a { color: #3498db; text-decoration: none; font-size: 0.9rem; }
.page-footer {
background: #2c3e50; color: #95a5a6;
text-align: center; padding: 1rem; margin-top: 2rem;
}
</style>
</head>
<body>
<a class="skip-link" href="#main-content">跳转到主要内容</a>
<header class="page-header">
<div class="page-header-inner">
<h1>TechBlog</h1>
<nav aria-label="主导航">
<a href="/">首页</a>
<a href="/articles">文章</a>
<a href="/about">关于</a>
</nav>
</div>
</header>
<div class="page-body">
<main id="main-content">
<article>
<header>
<h1>深入理解 CSS Grid 布局</h1>
<p class="article-meta">
作者:<address><a href="/author/zhangsan" style="color:#3498db">张三</a></address>
· <time datetime="2024-01-15">2024 年 1 月 15 日</time>
· 阅读时间:10 分钟
</p>
</header>
<section>
<h2>什么是 CSS Grid</h2>
<p>CSS Grid 布局是 CSS 中最强大的布局系统之一。它是一个二维系统,可以同时处理列和行。</p>
</section>
<section>
<h2>基础用法</h2>
<p>要使用 Grid 布局,首先需要创建一个网格容器...</p>
</section>
<footer>
<p>标签:CSS、布局、Grid、前端</p>
</footer>
</article>
</main>
<aside class="sidebar">
<div class="sidebar-widget">
<h3>相关文章</h3>
<ul>
<li><a href="#">Flexbox 完全指南</a></li>
<li><a href="#">CSS 定位详解</a></li>
<li><a href="#">响应式设计实践</a></li>
</ul>
</div>
</aside>
</div>
<footer class="page-footer">
<p>© 2024 TechBlog. All rights reserved.</p>
</footer>
</body>
</html>注意事项
常见错误
- 页面中有多个 main:违反规范,每个文档只能有一个
<main>
html
<!-- 错误:多个 main -->
<main><h1>第一部分</h1></main>
<main><h1>第二部分</h1></main> <!-- 错误! -->
<!-- 正确:使用 section 划分 -->
<main>
<section><h1>第一部分</h1></section>
<section><h1>第二部分</h1></section>
</main>- main 内包含全局导航:站点级导航不应出现在
<main>中 - 缺少 main 标签:每个页面都应该有一个
<main>来标识主内容区域
main 与 role="main"
html
<!-- 不需要手动添加 role,浏览器会自动处理 -->
<main role="main"> <!-- 冗余 -->
...
</main>
<!-- 正确写法 -->
<main>
...
</main>最佳实践
- 始终使用 main 包裹主要内容:即使页面很简单,也应该使用
<main> - 添加 id 用于 skip link:
<main id="main-content">作为跳转目标 - 配合 skip-link 使用:为键盘用户提供快速跳过导航的途径
- 不要在 main 内放置重复内容:全局 header、footer、nav 应该在 main 之外
- SPA 中动态更新 main:在单页应用中,只更新
<main>内的内容
下一节
继续学习:article 文章