一个页面只能有一个main标签,是w3c规范强制要求;多写、嵌套或误放会导致读屏器跳转失效、seo摘要错乱、lighthouse报duplicate-main错误,因其是屏幕阅读器“m键直达主内容”的唯一语义锚点,且必须为body直接子元素,内部仅含不可跨页复用的核心内容。

一个页面只能有一个 main 标签,不是“建议”,是规范强制要求;多写、嵌套或误放,会导致读屏器跳转失效、SEO摘要错乱、Lighthouse 直接报 duplicate-main 错误。
为什么浏览器不报错,但必须当真
HTML 解析器对重复 main 宽容,不会中断渲染——但这不等于它被认可。屏幕阅读器(如 VoiceOver、NVDA)依赖 main 作为「按 M 键直达主内容」的唯一锚点,遇到第二个就可能随机忽略、跳过全部,或反复播报“主内容开始”,用户无法预测行为。Lighthouse 和 axe 工具会明确标红 duplicate-main,而 DevTools 却沉默,极易被忽略。
- SPA 中每个路由组件都写
<main>{children}</main>→ hydration 后 DOM 留下多个实例 - 服务端模板未做条件判断,列表页和详情页共用同一套
main包裹逻辑 → 渲染出并存或嵌套结构 - Next.js 的
app/layout.tsx里直接放<main></main>→ 全局壳层不该承载页面级语义
main 必须是 body 的直接子元素,不能嵌套在 header/nav/footer 里
这不是兼容性问题,是语义冲突:main 表达的是“整页不可替代的核心内容”,而 header、nav、footer 是全局分区元素。规范明文禁止 main 作为它们的后代。错误写法如 <header><main></main></header>,会让辅助技术降级或跳过该 main。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 正确结构只有一种:
<header></header><main></main><footer></footer> -
header作为main的子元素是允许的,但仅限当前页面独有元信息(如文章标题+发布时间),不是网站全局头部 - Vue/React 中注意:若组件模板用
<template></template>包裹多个根节点,需确保main不被意外塞进父级语义区块内
什么该进 main,什么必须踢出去
判断标准极简:如果这块内容复制粘贴到另一个页面还能原样用,那它就不该进 main。它不是“视觉上最显眼的区域”,而是“语义上不可复用的内容边界”。
- ✅ 应包含:
<article></article>正文、<ol></ol>商品列表、独立<form></form>、搜索结果页主体 - ❌ 不应包含:
<nav></nav>全局导航、<footer></footer>版权、<aside></aside>侧边推荐、面包屑、网站 Logo 或登录入口 - ⚠️ 容易混淆:
<header></header>内的“客服入口”按钮——它服务主题但不构成主题本身,应放在<section></section>或<div>,而非 <code>mainSPA 路由中如何安全更新 main 内容
React/Vue 最稳妥的做法是:只在根 Layout 组件中声明一次
<main></main>,所有子路由内容作为其直接子节点动态替换,而不是让每个页面组件自己渲染一个<main></main>。- ✅ 正确:
<main><outlet></outlet></main>(React Router v6),或<main><routerview></routerview></main>(Vue Router) - ❌ 错误:在
ArticlePage里写<main></main>,又在ProfilePage里重复 - ⚠️ 特殊情况(如 404 页面):不能靠
<main>{error ? <notfound></notfound> : <page></page>}</main>,要确保整个生命周期内main节点只存在一个实例——可通过状态控制是否渲染该节点本身
最容易被忽略的一点:它不是视觉容器,也不承担样式职责;滥用
main做布局撑开或 CSS 作用域,反而会掩盖真正的语义意图。 - ✅ 正确:










