从 div 到语义标签:一次真实项目 HTML 重构经验分享

域名注册
域名注册 正式会员超兽战士 👑年卡会员
发布于 2026-10-08 04:35 ·1 浏览 ·0 回复

结论先行:把 div 换成语义标签,真正值钱的只有两件事——用 <header>/<nav>/<main>/<aside>/<footer> 搭出屏幕阅读器能一键跳转的地标骨架,以及用 <button>/<a>/<label> 替换掉那些用 div 硬凑的交互控件。这两类改完,可访问性收益能拿到八成以上;剩下的装饰性 div 留着不影响任何事,不必为了「语义纯净」把项目改到吐。

语义标签到底比 div 强在哪?

结论:语义标签的核心价值不是代码好看,而是给浏览器、屏幕阅读器和爬虫免费提供了一份结构元数据,而 <div> 对这三者都是完全透明的。

具体来说,浏览器会把特定标签自动映射成 WAI-ARIA 地标角色:<header>(不在 article/section 内时)映射为 banner,<nav> 映射为 navigation,<main> 映射为 main,<aside> 映射为 complementary,<footer> 映射为 contentinfo。用户用 NVDA 按一下 D 键就能在地标之间跳转,用 VoiceOver 按 VO+U 打开转子选「地标」列表,就能直接看到「导航」「主内容」这些条目。如果你全用 div,这个列表是空的,屏幕阅读器用户只能从头听到尾。

第二块收益是 CSS。选择器从 .page .content .card .card-body .card-title 这种五层嵌套,塌缩成 article > h3,层级深度直接砍掉三到四层,样式覆盖的调试时间明显下降。

一次真实项目重构:我们改了什么?

结论:我们重构的是一个后台管理系统,共 63 个页面模板。首页 DOM 里的 div 数量从 412 个降到 158 个,Lighthouse 可访问性评分从 71 涨到 96。

改动集中在四处,按收益排序:

  1. 页面骨架:原来整页只有 3 个 div 加类名 <div class="header">、<div class="container">、<div class="footer">,改成 header/nav/main/footer。
  2. 重复内容块:商品卡片、评论条目这类「能独立拿出来放到别处也讲得通」的内容改成 <article>,每张卡片内部用 <h3> 做标题。
  3. 交互控件:12 个 div + onclick 的「按钮」换成真 <button>,3 个跳转用的改成带 href 的 <a>。
  4. 表单:给每个 <input> 补上 <label for>,多选组用 <fieldset><legend> 包起来。

重构的具体步骤是什么?

结论:按「盘点 → 搭骨架 → 换控件 → 补标题 → 验收」五步走,不要一边改一边调样式。

第一步,先量基线。在控制台执行 document.querySelectorAll('div').length,把每个页面的数字记下来,改完再跑一次对比,这是唯一能拿给团队看的量化证据。

第二步,搭五大地标。记住四条硬规则:一个页面只能有 1 个 <main>;<main> 不能嵌套在 <article>/<aside>/<nav>/<header>/<footer> 内部;<header> 和 <footer> 一旦放进 <article> 或 <section> 里就不再是地标,只表示该区块自己的头尾;<nav> 只用给主要导航,页脚那堆友情链接用 <ul> 就够。

第三步,换交互控件。<div onclick> 不进入 Tab 顺序、不响应 Enter 和 Space、没有默认焦点样式,你要补齐 role="button" + tabindex="0" + keydown 监听三件事,大约 15 行 JS;而原生 <button> 需要写的只是 button { appearance: none } 这类 3 到 5 行样式重置。这笔账怎么算都该用原生标签。

第四步,补标题层级。标题从 h1 开始,不要从 h2 跳到 h4。Lighthouse 里有一条独立审计项「标题元素不按顺序递增」,跳级会直接扣分。

第五步,验收。跑 axe DevTools 插件,再手动开一次屏幕阅读器听一遍地标列表,最后跑 Lighthouse。三项都过再合并代码。

section 和 article 到底该怎么选?

结论:<article> 的标准是「抽出来单独发到别处,读者依然看得懂」,<section> 的标准是「有一个标题,且能归入文档大纲」。

评论区的一条评论、一篇博客正文、一张商品卡,都是 <article>。一个章节、一个「相关推荐」分组,是 <section>。

最容易踩的坑是滥用 section:如果一个 <section> 没有可访问名称(也就是没有 aria-labelledby 指向它内部的标题,或者没有 aria-label),它在辅助技术里跟 <div> 没有任何区别,而且还会污染地标列表。判断方法很简单——这个 section 里有没有一个明确的标题?有就用 section 并让它关联标题,没有就老实写 div。

另外一个常被问到的点:HTML5 允许一个页面出现多个 <h1>(每个 section 一个),但实际项目里为了兼容老版本屏幕阅读器和 SEO 工具,仍建议整页只保留一个 <h1> 作为页面主标题。

重构后要注意什么坑?

结论:语义标签本身不会弄坏样式,弄坏样式的是你原来写着 div > div > div 的 CSS 选择器。

第一条,样式钩子必须挂在类名上,不要挂在标签名上。你写了 .card div { padding: 8px },把中间一层 div 换成 <header> 的瞬间就会掉样式。

第二条,别在 <nav> 里放十几个链接就完事,给个 aria-label="主导航" 区分开侧边栏导航和面包屑导航,否则屏幕阅读器里会出现三个都叫「导航」的地标。

第三条,IE 时代需要引入 html5shiv 才能识别新标签,但 IE 已于 2022 年 6 月 15 日终止支持,现在这个补丁可以彻底删掉了。

总结一下:语义化重构的优先级是地标骨架 > 交互控件 > 内容块 > 表单标签,改完用 axe 和屏幕阅读器验收一次。其余那些纯粹用来挂布局样式的 div,它们本来就该叫 div,不用内疚。

版权声明:本文来自 GJ站长论坛《从 div 到语义标签:一次真实项目 HTML 重构经验分享》
原文链接:https://www.gj0.com/thread-745.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~