电商平台HTML质量靠约束、校验与模块契约保障,而非堆砌语义标签;main须唯一且不嵌套,section必须含标题,data-module替代class作JS锚点,alt与label须覆盖动态节点,统一机器校验确保跨团队一致性。

大型电商平台的HTML代码质量不是靠“多用语义标签”堆出来的,而是靠约束、校验和可落地的模块契约来守住底线。不设防的语义化反而会放大错误——比如把整个商品瀑布流塞进一个 <section></section>,等于主动向搜索引擎和屏幕阅读器宣告“这段内容不重要”。
main 只能出现一次,且不能嵌套在 header/nav/aside 里
这是 W3C 强制要求,也是 axe、Lighthouse 等无障碍与 SEO 工具的硬性报错点。电商首页常见错误:用 <header></header> 包住 logo + 搜索框 + 用户登录入口,再把整个商品列表包进 <main></main>,结果 <main></main> 被无意写在了 <header></header> 内部。
- 检查方法:DevTools → Elements → 搜索
main,确认它直接子元素是的子节点(即层级为 2) - 服务端模板(如 Handlebars、Nunjucks)中,禁止在 partial 里输出
<main></main>;只允许 layout 模板定义一次 - 构建时加校验:用
html-validate配置 rule"no-duplicate-main": "error"和"no-main-in-main": "error"
section 必须自带标题,否则优先用 div
<section></section> 不是“带边框的 div”,它的语义是“主题独立、可单独分发的内容区块”。电商页中大量误用:商品列表容器、筛选栏容器、推荐位容器,全被套上 <section></section>,但里面没有 <h2></h2>~<h6></h6>。
- 正确用法示例:
<section><h2>热销商品</h2><ul class="product-list">...</ul></section> - 错误场景:商品卡片循环渲染时,每个卡片外层用
<section></section>—— 单张卡片不具备独立主题,应改用<article></article>或纯<div> <li>CI 流程中加入 remark-lint 插件,规则 <code>remark-lint-heading-has-content+remark-lint-no-unused-definitions可拦截缺失标题或无效 section - 统一约定:每个逻辑模块根节点加
data-module="cart-drawer"、data-module="sku-selector" - JS 查询写成
document.querySelectorAll('[data-module="cart-drawer"]'),稳定且可预测 - 配合
data-version="2.1",上线前 CI 校验 HTML 片段是否匹配当前前端组件版本文档 - 禁止用
class承载模块身份,保留 class 仅用于样式与 BEM 命名(如cart-drawer__trigger) - 模板层强制:所有
<img>必须显式声明alt,CMS 导入图必须含描述字段,空图走alt="" - JS 动态插入表单控件时,必须同步生成唯一
id并配对<label for="xxx">;禁用仅靠aria-label替代 - 用 axe-core CLI 在 E2E 测试后扫描 DOM:
npx axe http://localhost:3000/product/123 --tags="wcag2a,wcag2aa",重点盯image-alt和label-title-only规则
data-module 是比 class 更可靠的 JS 查询锚点
电商页面常有多个“购物车浮层”“收藏按钮”“规格弹窗”重复出现,靠 class="cart-modal" 查询极易误匹配。一旦组件复用,id="cart-modal" 又必然重复,document.getElementById() 失效。
立即学习“前端免费学习笔记(深入)”;
alt="" 和 label for 必须覆盖所有动态生成节点
电商页大量内容由 JS 渲染(如搜索建议、商品对比表格、实时价格更新),这些节点若缺失 alt 或未绑定 label,对屏幕阅读器用户就是功能黑洞——不是体验差,是根本不可用。
真正难的不是写对一个页面的 HTML,而是让数百个模板、十几种 CMS 输出、几十个前端团队产出的 HTML,在语义、结构、可访问性上保持一致。这靠的是机器可校验的契约,而不是人肉 Review 或培训 PPT。



















