资讯动态

HTML5语义化标签实战指南:告别div堆砌,理清页面结构

发布时间:2026/10/20 19:20:59 来源:尧图企业网站定制
一次接手某内部项目时打开首屏 HTML 我的头就开始隐隐发胀外层是 div.page中间 div.content再往里 div.list-item、div.card、div.footer-info……每个 div 都戴着不同的 class 面具见不到一个语义标签。功能确实没什么毛病可当我想快速定位页面里“主要内容区”在哪时只能靠 class 名挨个猜猜错了再顺着 CSS 往回找效率低得很。HTML5 的语义化标签推出这么多年大量项目里 div 依然是最忙的标签。不是不能用而是用错了地方。这篇文章不谈“语义化很重要”这种空话我打算直接从一个前端开发者的实际项目视角出发把页面里的头部、导航、主体、文章、侧栏这些常见区域到底该用哪个标签、为什么该用它、哪些位置必须继续保留 div一次性说清楚。文章里会带一个完整的重构例子还有我在实际维护中踩过的坑适合那些写页面时总觉得“结构别扭”但说不清原因的同学参考。1. 语义化标签的受益清单SEO、无障碍与代码可维护性先说动机。很多人对语义化标签的态度是“别人都在说我也跟着用一点”并没有真正搞清楚它到底带来什么价值。这导致的结果就是文档标题用 header侧边栏也用 header文章正文用 div评论区还是 div。在我看来语义化标签的第一个受益人不是搜索引擎不是读屏用户而是三个月后的你自己。1.1 机器视角搜索引擎与爬虫如何“读”页面搜索引擎爬虫抓取网页之后会分析 DOM 结构来理解“这个页面讲的是什么”“哪里是核心内容”“导航放在哪个位置”。它并不是只看关键词密度而是会参考标题层级、段落结构、链接组织方式等信息。语义化标签相当于给爬虫画了一张结构图这是导航、这是主体、这篇文章可以单独抽出去分发、这个侧栏只是补充信息。举个例子同样一段“前端开发入门指南”的正文放在article里爬虫更容易识别出它是页面的核心内容在生成搜索结果摘要时也更容易提取到正文开头。放在一堆层层嵌套的div classcontent里爬虫也能猜但猜的成本更高结果自然就不够精确。所以不要相信“加几个语义标签就能上排名第一”的说法但也不要怀疑语义化能让页面的内容被更准确地理解。说白了语义化是给机器指路不是给机器喂药。1.2 用户视角读屏软件与键盘导航的真实体验视力障碍用户依赖读屏软件浏览页面时它们会从 HTML 里读出“地标”信息。这就像一个网站的目录或路标系统。比如nav是导航区、main是主内容区、aside是补充信息区。读屏用户可以通过快捷键在这些区域之间跳转直接进入主要内容跳过一大段重复导航。如果页面全是 div读屏软件就只能从头到尾把整页内容全部朗读一遍用户每次切换页面都要忍受一长串无意义的导航菜单。这体验有多糟你可以闭上眼睛找个页面亲自听一遍。语义化标签在这里不是锦上添花而是刚需。尤其是做面向公共服务、教育、电商这些场景的网站无障碍合规已经是硬性要求。1.3 开发者视角让结构成为可视化目录如果你维护过一个几百行的页面你应该有这种体会一个结构良好的语义化页面HTML 本身就相当于可视化目录。header告诉你这里是页面顶部nav告诉你这是导航main告诉你这里是重点article告诉你这是一篇完整内容footer告诉你这里是底部信息。这种清晰度直接决定了你的开发效率。调试样式时你可以直接写main article h2而不是.main-container .post-wrapper .content-wrapper h2这样又长又脆弱的嵌套选择器。写自动化测试时语义标签也比 class 名稳定得多——别人顺手改了个类名你的选择器可能就挂了但main不会因为重构而消失。所以语义化其实是一个前期省心、后期更省心的投资。2. 逐个拆解核心语义标签的职责边界与典型场景明白了为什么之后就进入最核心的问题每个标签到底管什么。我平时看代码时发现很多同学的困惑不是“不知道有这些标签”而是“不知道它们之间的边界到底在哪”。这节我把常用标签按三类拆开讲注意每个标签的关键词和典型场景。2.1 页面骨架四件套header、footer、main、asideheader表示的是“一组引导性或介绍性内容”可以出现在页面级也可以出现在 article、section 内部。页面顶部通常用它做横幅区里面放 logo、站点标题、导航文章开头用它放标题、作者、发布时间也很合理。一个页面可以有多个 header但它们各自对应自己所在区块的“头部”不是全局的。footer表示“区块底部的元信息”常见内容是版权声明、相关链接、作者信息、联系方式。它同样可以出现在页面级也可以出现在 article 或 section 内部。比如一篇文章底部放“关于作者”的卡片用footer包一层就非常合适。要注意的是footer 不一定必须放在页面最底部。main表示页面的核心主体区域一个页面只能有一个而且不应该被放到 article、nav、aside 这些标签里面去。它就是用来说明“这页最重要的内容都在这里”。爬虫和读屏软件拿到main可以直接锁定正文不需要挨个 div 找。这也是对比 div 版本时最立竿见影的一个改进。aside表示与主内容“间接相关”的内容常见形态是侧边栏、相关推荐、广告位、引文、注释。判断方式很简单如果把它从主内容里删掉主内容仍然完整成立那它就是 aside 的料。注意侧边栏不一定要放在视觉上的右边语义上是“补充信息”跟 CSS 布局无关。这四件套组合起来就是绝大多数页面的基础骨架body header站点标识、主导航/header main核心内容/main aside相关推荐、广告/aside footer版权、备案信息/footer /body除此之外浏览器还会给这些标签默认映射无障碍角色header 映射 banner、footer 映射 contentinfo、main 映射 main、aside 映射 complementary。这意味着读屏软件天然能识别它们的功能不需要你额外写角色属性。2.2 内容组织两兄弟article 与 sectionarticle的定义很有意思它是一个“可独立分发或复用”的内容单元。什么叫独立分发就是你可以把它单独拿出来放到别的地方人家依然看得懂。一篇博文、一条新闻、一个论坛帖子、一条评论、一个产品卡片都符合这个特征。判断时问自己一个问题如果我只把这个区块发给朋友他能否在不看页面其他内容的前提下理解它讲的是什么能就用 article。section表示一个“有主题范围的分区”强调的是主题上的分组关系而不是独立性。比如一篇长文里有“背景介绍”“实现方案”“性能对比”三个部分它们有各自的标题放在一起才组成完整文章那就适合用 section 来分。section通常建议带一个标题这个标题能很自然地形成文档的章节感。两者经常搭配出现一个 article 内部可以用多个 section 拆分论点一个页面也可以用多个 article 平铺多条新闻。反过来不要用 section 去包一组毫无主题的 div也不要因为某个区域“感觉很重要”就硬给它套上 article。一个没有独立语义的内容套 article只会让爬虫读到一堆结构错位的“独立内容”。2.3 容易被忽视的语义小部件figure、time、mark、blockquote、details除了页面骨架和内容组织HTML5 还提供了一批“零件级”的语义标签它们个头不大但用对了非常提升语义准确度。figure配合figcaption是给插图、代码块、表格、图表这类“被主体内容引用”的内容做包裹的。图注 figcaption 相当于图的解释文字这种“图与注释的关联关系”是普通 div p 表达不了的。time用来标记时间关键是 datetime 属性。如果你只写“昨天”机器是无法知道具体日期的写成time datetime2025-07-29昨天/time机器和人都能读懂。在排序、日历类应用里这个标签能省去很多猜测。mark表示“因为上下文原因需要被标注出来的文字”比如搜索结果里的关键词高亮、引文中被你特别标出的话。很多人会把 mark 和 strong、em 混在一起其实它们是不同的维度strong 表示重要性em 表示语气强调mark 表示上下文相关性。blockquote负责长引文引文来源可以用cite属性或cite标签标记details配合summary做一个默认隐藏、点击展开的折叠区域用来放“进阶说明”“FAQ 答案”这类次要内容很顺手。这些标签单个看起来不起眼但一个页面上语义信息的密度往往就是靠这些细节攒起来的。3. 语义化不等于消灭 div什么时候必须继续用 div每次讲语义化我都担心读者走向另一个极端把页面上所有 div 都替换成语义标签连一个 10 像素的间距容器都要找一个“表意词”来套。这个方向与“滥用 div”同样有害。div 本身没有任何语义但它的价值恰恰在于“没有语义”。3.1 div 的合法用途之一纯视觉容器与 CSS 承载点布局里经常有一些纯粹为视觉而存在的容器一条分割线、一个圆角卡片的外壳、一个 flex 网格里包裹整行的 wrapper。它们不承载任何“内容含义”只是在 CSS 层面承担间距、背景、排列方式。这种情况下div 是最诚实的选择。你要是硬找一个语义标签反而会让爬虫和读屏软件产生误解。举例来说一个商品卡片整体用article描述商品信息没问题但卡片里的图片和文字之间需要一个 flex 容器来控制排列方向这个容器就该用div。它不表达“这是一个独立内容”它只是排版的工具人。3.2 div 的合法用途之二JavaScript 钩子绑定点前端框架兴起之后页面里大量 div 是作为组件的根节点存在的。比如 Vue 或 React 组件里一个组件的模板最外层常见div classuser-card。这个 div 的功能是给组件提供一个挂载点让 class 和事件绑定有一个稳定的宿主。这就是很典型的“没有语义含义但确实需要存在”的场景。同样一些自定义交互控件——比如日期选择器、拖拽排序列表——它们需要包裹层来承载定位、事件监听、状态 class这些包裹层语义本身并不重要用 div 是合理选择。3.3 用语义化之前先设计结构层级我在 review 别人代码时发现很多滥用语义的情况根因是“没有先设计结构直接边写边套标签”。结果是 header 里套 headernav 里再放 nav整个结构跟套娃一样。正确的做法是先画出页面结构草图明确每个区块的职责再决定标签。一个页面从上到下通常是页面头部→主导航→主体区可含文章、侧栏→页面底部。主体区内部再细化文章→章节→段落侧栏→小组件。这张草图画完了每个区域对应哪个标签基本就清楚了div 的用武之地反而很明确——没有职责可言的区块。所以我的建议是不要把“语义化”当成一个需要完成的指标而是把它当成一个始终在问自己的问题——“这个区域到底在表达什么”。能回答就用语义标签回答不了就老老实实用 div。语义化是帮人理解结构不是为了证明你不用 div。4. 面对一个模块迅速选标签我的三步提问法在实际开发中我们大半时间不是在设计整站骨架而是在处理一个个具体模块一个评论区一个商品列表一个页脚链接组。这时候每次都要翻文档显然不现实。我总结了一个自己的三步提问法按顺序走基本能在十秒内决定该用哪个标签。4.1 三步提问从独立内容到兜底方案第一步问自己这个模块如果单独拿出来是否依然有意义比如一条评论、一篇博客、一款商品的完整信息单独拿出来别人也能理解那它应该进入article。第二步如果它不能单独成立那么它是否是一个有清晰主题的区块并且内部有自己的一组信息比如文章里的“实现原理”这一节、页面的“评论区列表”区域它们和周围内容有边界适合用section。注意 section 应该尽量带标题形式上是“章节的感觉”。第三步思考它和页面主内容的关系。如果它是主内容的铺陈、补充、延伸比如相关文章、广告、侧栏的个人介绍那用aside更合适。如果它不是主内容的组成部分删掉也不影响页面完整度aside 就很贴合。走完这三步还没有落点再看它属于几种“角色型”标签之一吗导航栏用nav页脚版权区用footer页面核心主内容用main作者联系信息用address。再不行就大方使用div——因为那些没有被语义识别需求的部分本来就该由 div 来兜底。4.2 常用模块的速查对照表为了方便日常快速参考我整理了一张模块对照表你完全可以把它存成笔记页面模块首选标签理由反面写法博客正文article独立内容可单独分发div.post文章内的章节section有主题的分区依赖标题组织div.part1单条评论article单条评论本身可独立理解div.comment-item评论区容器section多条评论的集合是主题区块div.comments页面主内容区main全页面唯一核心区域div.main主导航nav页面主要导航区块div.navbar侧边栏相关推荐aside主内容的补充信息div.sidebar页脚版权区footer区块底部元信息div.footer文章配图及图注figurefigcaption图与被引用注释的关联语义div span用户信息卡片article完整独立的用户信息单元div.card价格对比数据table数据行展示表格本身有语义div.grid纯网格布局容器div无语义含义仅为排版不需要换成语义标签这张表不是为了让你机械对照而是帮你建立一个直觉每个模块先想语义再想视觉先想内容独立性再想主题分组真正没有语义的排版层才轮到 div 出场。5. 实战重构把一个博客文章页从 div 海改成语义化结构理论讲再多不如看一次真实改动。下面我拿一个典型的博客文章页做例子先展示原始版本的“div 全家桶”再展示语义化版本并且逐条说明每一步的改动理由。这是我实际协助某项目重构时用到的思路比较有代表性。5.1 原始版本一个典型的“div 全家桶”原始页面结构大概是这样的div classpage div classheader div classlogo img srclogo.png alt站点标识 span我的博客/span /div div classnavbar a href/首页/a a href/archive归档/a a href/about关于/a /div /div div classmain div classpost div classpost-title h1手写一个轻量级前端项目脚手架/h1 /div div classpost-meta span发布于 昨天/span span分类前端工程化/span /div div classpost-content div classsection-1 h2为什么需要自己的脚手架/h2 p……/p /div div classsection-2 h2核心设计思路/h2 p……/p /div /div /div div classsidebar div classwidget h2相关阅读/h2 div classwidget-list div classwidget-itema href#前端项目目录结构设计/a/div div classwidget-itema href#构建工具的底层原理/a/div /div /div /div /div div classfooter div classcopyright© 2025 我的博客/div /div /div你能看到整篇 HTML 除了 class 名之外识别不出任何“区块身份”。想了解这个页面的重点在哪得靠人脑去猜.main、.post、.post-content之间的从属关系。这种结构在维护时非常容易出错尤其是当后手接手的人对业务不熟的时候。5.2 语义化版本结构对比与每处改动理由改完之后的语义化版本长这样body header p classlogo img srclogo.png alt站点标识 我的博客 /p nav aria-label主导航 ul lia href/首页/a/li lia href/archive归档/a/li lia href/about关于/a/li /ul /nav /header main article h1手写一个轻量级前端项目脚手架/h1 p classpost-meta 发布于 time datetime2025-07-297月29日/time · 分类前端工程化 /p section aria-labelledbysection-why h2 idsection-why为什么需要自己的脚手架/h2 p……/p /section section aria-labelledbysection-design h2 idsection-design核心设计思路/h2 p……/p /section /article aside aria-label相关阅读 h2相关阅读/h2 ul lia href#前端项目目录结构设计/a/li lia href#构建工具的底层原理/a/li /ul /aside /main footer p© 2025 我的博客/p /footer /body逐条看关键改动第一最外层.header改成header包裹整个站点头部navbar改成语义上更准确的nav并给aria-label主导航标明这一组导航在整站中的角色。导航内部用ul和li组织链接列表而不是一堆diva/a/div。这样读屏用户能直接知道这里共有多少个导航项爬虫也能清楚识别导航结构。第二.main改成main直接声明“本页核心内容在这里”而且只保留这一个。这一步对无障碍和搜索理解影响最大。如果页面同时有多个 main辅助技术会无所适从规范也明确只允许一个 main。第三post改成article。因为这篇博客正文本身就是可以单独分发的完整内容——别人复制过去照样成立。标题 h1 直接作为文章标题省掉了div.post-title这一层纯包装。发布时间用time datetime2025-07-29标记机器可读。第四文章内部两个区块改成section并且给每个 section 配上可见的 h2 标题因为没有标题的 section 在可访问性树里经常被忽略。我还加上了aria-labelledby指向标题 id让辅助技术能把这个 region 当作一个有名字的独立区块来播报。第五侧栏改成aside因为它属于“相关阅读”和主内容只有间接关联删掉不影响文章完整性。相关阅读列表也用了ulli而不是 div 套 div。第六底部的版权信息放进footer这是整份文档的收尾元信息。如果你项目里还有“关于作者”这类文章级底部信息完全也可以在 article 内部再放一个 footer只要它描述的是当前区块的底部信息就行。5.3 重构后带来的实际变化这些改动带来的反馈不是玄学。重构之后调试时我用main article h2就能直接命中标题样式不再需要.main .post .post-content h2那串又长又脆弱的选择器。无障碍审核时工具列出的地标列表变成了“banner、main、complementary、contentinfo”层次分明。用键盘配合读屏软件操作时用户可以直接从 banner 跳到 main跳过三次重复出现的导航链接。对内容型网站来说这种体验改进是肉眼可见的。还有个容易被忽略的好处是自动化测试。我后来写端到端测试时选择器直接写main article h1不依赖任何 class 名。哪怕项目里某个类名被重命名了测试依然稳定因为语义标签是文档结构的一部分不会被轻易重构掉。6. 语义化避坑清单这些问题踩过才记得牢这一节写的是我在实际项目里踩过、也帮别人 review 时经常见到的坑。每个看起不起眼但积累多了整页语义化就形同虚设。6.1 article 里嵌套 section 没问题反过来要小心article里可以有多个section这是一篇长文章常见的结构但当你在section里再嵌套多个article就要多想一层这些 article 是不是真的可以独立如果你的 section 表示“产品列表”里面每个产品确实可以单独理解那每个产品用article很合适。但如果 section 里的 “article” 只是一些零散段落它们根本不能独立那就别套。我见过最夸张的写法是sectiondivsectiondivsection这种连环套。这跟 div 嵌套一样令人抓狂因为它并没有增加任何语义价值。规则很简单只有在内容语义上确实需要分层时才嵌套语义标签。6.2 一个页面只允许有一个 main这句话不能打折main代表页面的核心主体规范明确一个文档只能有一个。我在部分项目里见过“首屏一个 main详情弹窗又写一个 main”的情况。这会让辅助技术无法判断到底哪个才是真正的主体。如果需要做一个全屏弹窗或者模态框请让弹窗内容保持普通元素身份不要使用 main 强调它。弹窗本身的语义可以由roledialog或aria-modal来表达而不是抢 main 的位置。6.3 header 不是只能出现在页面顶部很多人习惯把header理解成“顶部横幅”实际它表示的是“一组引导性内容”所以它也完全适合出现在article、section、aside内部。比如一篇文章开头放作者、日期、标签的一组信息用header包裹是合理的它不是页面级头部而是这篇文章的头部。反过来不要因为你视觉上把它放在页面底部就拒绝使用footer。一篇文章末尾的“作者卡片”用 footer 是合适的因为它就是这篇文章区块的底部元信息。6.4 hgroup 已被移除别再用老理写组合标题HTML5 早期规范里有hgroup用来把主标题和副标题组合在一起但后来的规范已经移除了它。现在你用它浏览器虽然能渲染但它已经不具备规范的语义含义还会让标题结构变得混乱。目前推荐的做法是用p放副标题或者直接用一个header包住标题组合。比如header h1前端工程化实践/h1 p从项目初始化到持续交付/p /header这样既保留了组合关系又不破坏标题结构。如果你还在项目里用 hgroup是时候清理掉了。6.5 address 只负责联系信息不是地址栏的通用品address表示的是文章作者或相关组织的联系方式比如邮箱、联系电话、公司地址而不是页面上随便哪个“地址栏”或“收货地址”。很多同学看到地名就套address这其实偏离了它的语义定义。如果你在写一个快递收货地址表单请用普通标签加合适的 aria 标注而不是address。真正的 address 场景是页脚里写“联系站长feedbackexample.com”这时候用它就非常合适。它是给“组织/作者联系信息”准备的不是给所有“地址”词汇准备的。6.6 section 的可访问名称没标题的 section 很可能被忽略section在无障碍树里默认映射为region角色但这个region只有在它有“可访问名称”时才会被读屏软件识别为地标。可访问名称的来源可以是可见的标题h2 等也可以是 aria-label。换句话说如果你写一个section里面却没有标题也没有加 aria-label读屏用户很可能根本感知不到它是一个独立区块。这也是为什么我在实战案例里给每个 section 都加可见标题或至少用 aria-label 标明用途。不加名字的 section跟一个普通 div 在无障碍体验上没有本质区别。6.7 details 与 summary 的交互好用但别承载关键信息details和summary能在不写 JavaScript 的情况下做出展开收起效果确实很香。但它有一个潜在问题折叠区里的内容默认是隐藏的部分辅助技术对它内部的播报支持也不统一。所以我的建议是把 details 用于“补充说明”“常见问题”“进阶阅读”这类非关键信息。如果一个信息是整个流程里用户必须看到的那就直接展示别收进折叠区。折起来谁也看不见的内容等于不存在。说到底语义化本身不是目的它只是为了让人和机器都能更好地理解页面。这套标签体系并不难难的是每次写结构时停下来想一下“我在表达什么”。我自己的习惯是写 HTML 之前先在草稿纸上把每个区块画出来标上它的职责再动手选标签。这样写出来的页面结构清晰维护省心也不会被“滥用 div”或“滥用语义标签”两种极端拉扯。希望这份从实际项目里总结出来的经验能让你下次写结构时更有底气。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑