class必须排第一且加命名空间前缀,id仅用于锚点或ARIA关联,data-*须全小写短横线并仅传初始化参数,hidden和class是唯一可靠视图控制通道。

HTML 全局属性不是“随便加的配置项”,在组件库中乱用 id、class、data-* 会导致样式泄漏、状态不同步、SSR 失败、无障碍失效——标准不是为了整齐好看,而是堵住这些默认崩塌路径。
class 必须排第一,且带命名空间前缀
构建工具(如 PostCSS、Lit、Webpack)依赖 class 做样式作用域提取和组件映射;若它不在属性首位,某些 AST 解析器会跳过后续处理,导致 CSS 模块化失效。同时,没有前缀的 btn 或 header 在嵌入第三方项目时必然冲突。
-
class必须是第一个属性,哪怕只写class=""也要占位 - 所有类名强制加统一前缀,如
c-button、c-card__footer,禁用泛化名 - 子元素类名必须走 BEM + 设计令牌,如
c-button__icon、c-spacing-md,不许出现big-red这类描述性命名 - 按钮、表单控件等语义结构必须用原生标签,
<button>不可替换成<div class="c-button">
data-* 只能传初始化参数,不能当状态源
dataset 是只读快照,只映射 HTML 初始值;JS 后续调 el.setAttribute('data-id', '500'),React/Vue 组件不会重渲染,SSR 和 CSR 的值还可能不一致。常见错误是把 data-count="10" 直接参与计算,结果 "10" + 1 === "101"。
- 仅用于不可变初始化参数:
data-theme="dark"、data-testid="modal-close" - 结构化数据必须用
JSON.parse(el.getAttribute('data-config') || '{}'),且包try/catch - 命名严格小写+短横线:
data-user-role✅,data-userRole❌,data-1st-item读取需用dataset["1stItem"] - 表单提交时
data-完全不进FormData,额外参数必须 JS 显式提取
hidden 和 class 是唯一可靠的视图输出通道
浏览器原生支持 hidden 和 class 属性变更触发重绘,其他全局属性(如 title、lang)只影响辅助技术,不驱动 UI 更新。想控制 loading 状态?别写 data-loading="true",用 el.classList.toggle('c-state-loading')。
立即学习“前端免费学习笔记(深入)”;
-
hidden是布尔属性:存在即隐藏,删除即显示;旧版 Safari 需 fallback 到style.display = 'none' - 多状态 UI(loading/success/error)必须用 class 控制,配合命名空间化规则如
.c-button--loading .c-spinner - 避免操作
className字符串拼接,优先用el.classList.add()/.toggle() -
id仅用于锚点、ARIA 关联或 SSR hydration,禁止用于 JS 逻辑强耦合(如document.getElementById('modal-close'))
所有属性值必须双引号包裹,且 style 标签只能在 head 中
未加引号的 src=assets/icon (v2).svg 会被截断为 icon;<style> 放在 <body> 里根本不会被解析为有效样式,连 @media 查询都失效。这不是兼容性问题,是 HTML 规范层面的否定。
- 所有属性值强制双引号:
alt="用户头像"✅,alt='用户头像'❌ -
<style>必须在<head>内,动态插入也必须用document.head.appendChild(styleEl) - 资源路径用相对路径:
src="./img/logo.svg",避免硬编码 CDN - 基础重置要覆盖
*::before/*::after,不能只清bodymargin
最难的不是记住每条规则,而是在每次加 data-、写 id、塞 style 前,先问一句:这个值是否只服务于当前元素的初始渲染?它会不会被下游项目覆盖?它在 SSR 和 CSR 之间是否一致?



















