语义失焦表现为html中大量无意义div套嵌、标题跳级、语义标签误用等;应优先替换header/nav/footer类div,按内容独立性区分article与section,并强制校验alt和label。

如何识别当前HTML是否“语义失焦”
直接看浏览器 DevTools 的「Elements」面板里有没有大量无意义的 <div class="header">、<code><div class="content"> 套嵌,或者标题标签跳级(比如 <code><h1></h1> 下直接是 <h4></h4>)——这说明结构已脱离内容本意,机器和人都在靠猜。
更隐蔽的问题是:一个 <section></section> 里没配 <h2></h2>~<h6></h6>,或 <nav></nav> 里塞了登录按钮、搜索框;<main></main> 出现两次,或被包在 <header></header> 里。这些不是样式问题,是语义契约被破坏。
- 用 axe-core 或 Lighthouse 的「Accessibility」审计跑一遍,重点关注 “Heading levels” 和 “Landmark roles” 报错项
- 打开屏幕阅读器(如 NVDA 或 VoiceOver),听它怎么朗读页面——如果跳过整块区域或把按钮读成“div”,基本就是语义缺失
- 检查 CMS 或模板引擎输出的 HTML,确认是否动态插入了无层级上下文的
<h3></h3>或<article></article>
哪些标签必须优先替换,且风险最低
别一上来就重写整个 DOM 树。先锁定三类高价值、低副作用的替换点:
<div class="header"> → <code><header></header>:只要它确实是页头(含 logo + 主导航),替换后几乎零兼容问题<div class="nav"> → <code><nav></nav>:前提是里面只有跳转链接,不含表单控件;若混有搜索框,拆出<form></form>单独处理<div class="footer"> → <code><footer></footer>:注意它必须是页脚,不是某个模块底部;每篇<article></article>内部也可有自己的<footer></footer>这类替换不改样式、不碰 JS 绑定,CSS 选择器只需把
.header改成header(或保留 class 兼容旧样式),上线即见效。article 和 section 到底怎么分,现场判断口诀
别背定义,用这个动作检验:删掉周围所有其他内容,这块还能不能被单独转发、RSS 订阅、或被搜索引擎当独立条目索引?
- 能 → 用
<article></article>:博客正文、新闻稿、用户评论、产品卡片(带标题+摘要+时间) - 不能,但它是按主题聚合的一组相关内容 → 用
<section></section>:侧边栏“热门话题”、文章末尾的“相关推荐”、表单里的“联系信息”区块 - 纯样式分组、无逻辑主题 → 老实用
<div>:比如为实现某段间距加的空 div,或仅用于 CSS Grid 容器的 wrapper <p>特别注意:<code><article></article>内部默认参与文档大纲,所以建议自带<header></header>包<h2></h2>;<section></section>必须显式配<h2></h2>~<h6></h6>,否则对 SEO 和辅助技术无效。alt 属性和 label 关联不是补救项,是上线前必验点
很多遗留项目把
<img>当装饰,留空 alt 或写“图片”;表单 input 全靠 placeholder 提示,没<label for="id"></label>—— 这些不是“体验优化”,是功能残缺。弱网、无图模式、屏幕阅读器下,这部分内容直接不可见、不可操作。-
<img src="logo.png">→ 必须加alt="公司名称";纯装饰图写alt=""(不是省略) -
<input type="text" name="email">→ 必须有<label for="email">邮箱地址</label>,且 id 与 name 一致 - 批量检查:用 Chrome 控制台执行
document.querySelectorAll('img:not([alt])').length和document.querySelectorAll('input:not([id]), input[id]:not(label[for])').length,结果非零就得修
真正麻烦的不是加标签,而是旧系统里大量图片路径失效、表单字段动态生成导致 id 不稳定——得配合后端接口返回的字段名做映射,而不是硬编码。
-
- 能 → 用











