HTML语义化需真实落地而非仅套用标签名,核心是确保结构准确、可访问性完备、SSR安全及HTML与CSS/JS职责清晰,评审应聚焦内容意图而非样式行为。

HTML语义化是否被真实落地,而非仅套用标签名
很多团队把 <article>、<section> 当成“高级写法”来凑数,但实际结构混乱、嵌套错误、脱离上下文。语义化不是换标签,而是让屏幕阅读器、搜索引擎、后续维护者能准确理解内容层级和意图。
实操建议:
- 检查
<header>是否只用于页面或区块的标题区域,而非任意带 logo 的 div - 确认
<nav>内只包含导航链接,且不嵌套<main>或<footer> - 用浏览器开发者工具的「Accessibility」面板验证 heading 层级(
<h1>→<h2>→<h3>)是否连续、无跳级 - 避免用
<div role="button">替代原生<button>—— 这类“伪语义”会破坏键盘焦点与屏幕阅读器行为
是否存在不可见但影响渲染/可访问性的 HTML 问题
这类问题在视觉验收时完全“看不见”,却会导致 SEO 掉权、辅助设备失效、甚至 SSR 渲染异常。Code Review 必须主动查,不能等线上报错。
常见现象包括:aria-hidden="true" 错用导致重要内容被读屏器跳过;tabindex="0" 加在非交互元素上引发意外焦点;<img> 缺 alt 或设为空字符串但实际含信息。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 所有
<img>必须有alt:纯装饰图用alt="",图文内容图需描述性文字(避免 “图片”“图标” 这类无意义值) - 禁用
tabindex值大于 0 的写法(tabindex="1"),它会打乱自然 tab 顺序,且无法被自动化工具检测 - 检查
aria-*属性是否与对应组件逻辑一致:比如aria-expanded是否随折叠状态同步更新 - SSR 场景下,避免在服务端渲染中写入依赖客户端 JS 才能生效的
aria-live区域
模板引擎或框架生成的 HTML 是否引入冗余/冲突结构
Vue 的 v-for、React 的 map()、或后端模板(如 EJS、Thymeleaf)常因循环逻辑不严谨,产出重复 ID、缺失 key、无效嵌套。这类问题在单测里难覆盖,全靠人工 Review。
实操建议:
- 检查所有动态生成的
id属性:禁止硬编码(如id="modal"),必须拼接唯一标识(:id="'modal-' + item.id") - 确认列表渲染中
key值稳定且唯一(不用index,优先用业务 ID) - 警惕框架自动注入的 wrapper 元素(如 Vue 的
<template>编译后多一层<div>),是否破坏了语义流或 CSS 选择器预期 - 若使用
dangerouslySetInnerHTML或v-html,必须验证输入已做 XSS 过滤,且输出不含<script>、onerror等危险片段
HTML 与 CSS/JS 协作边界是否清晰、无隐式耦合
前端团队常把样式逻辑或行为控制“藏进 HTML”:比如靠 class 名触发 JS 功能(class="js-toggle-menu"),或用 data-* 属性传递复杂配置。长期看,这会让 HTML 变成“半声明半指令”的混合体,难以维护。
实操建议:
- 禁止用 class 名作为 JS 行为钩子(如
class="btn-primary js-submit")—— 改用data-action="submit"显式声明意图 -
data-属性值应为简单字符串或布尔(data-loading="true"),避免 JSON 字符串(data-config='{"delay":500}') - CSS 中避免强依赖 HTML 标签名(如
article h2 {…}),优先用语义 class(.article-title),否则重构 HTML 时样式会意外失效 - 表单控件必须有明确的
name和id,且label[for]与input#id严格匹配——这是 JS 拿不到 value 时最常被忽略的根因
HTML 不是容器,是契约。它定义“是什么”,而不是“怎么动”或“长怎样”。评审时盯住这一条,就能避开大多数后期返工。



















