先记住这个答案
<header> 用于包含一组介绍性或导航性内容,常用于页眉或文章头部;<footer> 包含版权、联系信息等页脚内容;<main> 包裹页面独有主体内容。文档中不能有超过一个未加 hidden 的 <main> 元素,否则违反 HTML 规范,影响可访问性和语义正确性。
- 每页最多一个不带 hidden 的
<main>。 <header>和<footer>可多次出现。<main>内容应页面唯一,不含侧栏等重复块。
结构性元素的语义分类
HTML 规范将 <header> 定义为 section 的头部,包含标题、logo、作者信息或导航,属于纯语义容器。<footer> 表示最近父级 section 的页脚,补充版权、法律链接或反馈入口。两者均允许一个页面出现多次,分别附着在不同的内容区块(如 <article>、<section>)而非仅限 body。
<main> 代表文档或应用的主导内容,其内容必须与整篇文档中心主题直接相关,且不能重复导航、侧栏、版权信息等跨页面共有部分。规范要求:文档不得有超过一个未带 hidden 属性的 <main>。因为一个页面若出现多个可见主内容区域,辅助技术将无法确定哪一个是真正的主入口,导致跳转导航失效。
从可访问性看,<main> 隐式映射到 ARIA landmark 角色 main,屏幕阅读器的转子菜单会把它作为可跳转的顶级区块。优先使用原生 <main> 而非手动添加 role="main",只在需要支持不支持 <main> 的旧浏览器时才使用后者。
博客文章页结构组织实践
假设构建一篇带顶部导航、侧边栏、文章内容和版权信息的博客页。页面结构可写为:<body> 内先有 <header> 包含站点名称与主导航 <nav>;随后 <main id="post-main"> 只包裹 <article> 的文章主体和元数据;侧栏属于辅助内容,应放在 <aside> 中不应放进 <main>,因为侧栏通常包含其他文章链接和广告,并非本文核心。页脚 <footer> 在 <main> 外层放置站点级版权,而 <article> 内可再自设 <footer> 写作者信息,从而实现单页多个 header/footer 却不违反主语义。
此方案使阅读器模式能准确提取文章,因为 Safari Reader 等会优先寻找 <main> 元素。通过给 <main> 加 id="main",配合第一个链接 <a href="#main">跳至主要内容</a> 即可实现跳转链接,帮助键盘或屏幕阅读器用户跳过重复的导航。主内容区域唯一性也保证浏览器扩展或抓取工具能明确找出核心文本,而非纠结其他辅助区块。
规范的例外与失效条件
HTML 规范只限制“可见”的 <main> 个数:如果某个 <main> 带有 hidden 属性,它不会被用户代理渲染,此时页面可包含多个 <main>,其中仅一个未隐藏。但实际工程中仍应坚持只有一个 <main>,即便将其他隐藏用于单页应用路由容器,也容易造成辅助技术混乱,并且隐藏的 <main> 只有在移除 hidden 时才会成为可见主区域。
另一个边界是 <main> 不能作为 <article>、<aside>、<footer>、<header> 或 <nav> 的后代。W3C 合规性检查器会直接报错,因为主内容始终对应整个文档。如果遇到需要分组多个独立文章的页面(如首页列表),不应为每篇分设 <main>,而应将这些文章全部包在一个 <main> 内,用 <section> 区分。
容易答错的地方
- 每个区块都用 main 表示主内容
- 误区:在每个
<article>或<section>中加<main>强调主体。实际上<main>定义的是整个文档顶层主内容,规范禁止其作为<article>、<aside>、<footer>、<header>或<nav>的后代;虽然未明确禁止嵌套在<section>中,但若滥用会削弱文档大纲的清晰度,推荐将<main>作为<body>的直接子级,区块内部应使用标题结构和<article>/<section>来体现层级。 - 将页眉、页脚放入 main 中
- 失误:把站点导航、版权等重复块放进
<main>。规范要求<main>内容对当前页面唯一,全局导航和页脚会重复跨页面,放进 main 会破坏主导内容的独特性,并干扰阅读模式提取正文。它们应放在 main 外部,而不是作为 aside 处理,因为导航和页脚属于文档整体结构,应使用 header/footer 等语义元素。
面试官还会怎么问?
隐藏多个 `<main>` 而只留一个可见是否可用来做 SPA 切换?
可行但须谨慎。可以为不同路由各建立 <main>,用 hidden 控制显示,但初始文档仍必须只有一个不带 hidden 的 <main>,以保证符合规范。实际中切换状态要同步处理 hidden,避免同时出现多个不带 hidden 的 <main>。
`<header>` 可以在一个页面里出现多次吗?它与 `<body>` 下的 `<head>` 有何区别?
可以,每个 <article> 或 <section> 都可有自己的 <header> 作为区内引导。但 <head> 存放元数据、标题和样式表,是文档给机器信息的容器,和给用户看的 <header> 完全不同,一个 <head> 不可多次出现。
如何结构化一个包含主要内容和侧栏的两栏布局?
用 <main> 包裹该页面的主导内容,用 <aside> 包裹辅助性的次要内容。如果 <aside> 的内容仅与当前页面相关,可以放在 <main> 内部;如果是跨页面重复的全局侧栏(如通用导航、广告等),则应放在 <main> 之外。页面主体不一定直接作为 <body> 的子级,但推荐将 <main> 作为 <body> 的直接子级以方便辅助技术识别主内容区域。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。