html属性应按class→id→data-→src/href→title/alt→role/aria-→tabindex顺序书写,data-*须带业务前缀,自闭合标签依工具链统一,属性值用双引号且无空格,需prettier+husky自动化执行。

HTML属性顺序不统一,是团队协作中最隐蔽的冲突源头——它不会报错,但每次CR都变成风格辩论。
为什么class必须排在id前面
这不是审美偏好,而是CSS层叠和选择器权重的实际映射。浏览器解析时,class比id更常复用、更易被JS操作,前置后能一眼识别组件身份;而id语义强、全局唯一,放在后面作为“锚点补充”更符合阅读直觉。
- 错误写法:
<div id="header" class="site-header"> —— 容易让人误以为<code>id才是主标识 - 正确顺序(按W3C推荐+eslint-plugin-html默认):
class→id→data-*→src/href→title/alt→role/aria-*→tabindex - 不强制但强烈建议:布尔属性省略值,如
<input disabled>而非<input disabled>,减少噪声 - 危险示例:
<div data-id="123"> —— 三个月后连自己都记不清这是用户ID还是商品SKU <li>安全写法:<code><div data-user-id="123" data-user-status="active">,或更明确:<code><div data-api-source="user/profile" data-user-id="123"> <li>配合<code>stylelint做校验:配置selector-attribute-pattern规则,拒绝不含业务前缀的data-* - 统一策略:团队所有项目启用Prettier,并配置
"htmlWhitespaceSensitivity": "css",它会自动对齐空格和闭合行为 - 注意例外:
<textarea></textarea>和<script></script>永远不能自闭合,否则内容丢失 - 真实坑点:在
.vue文件中写<img src="x">,Volar可能报warning;但写<img src="x">,Prettier又会格式化掉换行——必须靠prettier.config.js里htmlWhitespaceSensitivity: "ignore"兜底 - 反模式:
<div class="btn primary"> 或 <code><div class=" btn primary "> <li>正解:<code><div class="btn primary">,且所有属性值都走双引号 <li>自动化卡点:在<code>.prettierrc中设"singleQuote": false,再配合husky + lint-staged,在git commit前自动修正
data-*命名必须带业务上下文,不能只写data-id
裸名data-id在多人协作中等于没写——没人知道这个ID来自哪个接口、是否可为空、是否需要防重。它本质是前端与后端/业务逻辑的契约接口。
自闭合标签要不要加/,取决于你用什么工具链
HTML5规范允许<img>、<input>等标签省略/,但Prettier默认不加,而Vue SFC或某些SSR框架会要求显式闭合。混用会导致Git diff爆炸式增长。
属性值引号必须用双引号,且禁止空格环绕
单引号在JS模板字符串里容易嵌套冲突,而class=" a b "这种带首尾空格的写法,会让el.classList.contains("a")返回false——人眼难查,但运行时出bug。
最常被忽略的不是规则本身,而是「谁来执行」——没有Prettier + husky的组合,属性规范就是贴在Wiki上的装饰画。真正起效的那一刻,是新人第一次保存文件,光标还没离开编辑器,class已经跳到了最前面。











