必须用id仅当元素绝对唯一且需精准引用,如锚点跳转、label绑定、js单例控制;滥用id会导致获取失效、hydration错乱、css权重失衡;class应语义化命名、用bem修饰符、工具类前缀隔离,避免样式耦合;id与class共存时dom定位行为不同,aria和表单绑定依赖id唯一性;命名须用kebab-case,禁用驼峰和下划线。

什么时候必须用 id,而不是 class
只有当元素在整页中**绝对唯一且需被精准引用**时才该用 id。比如:id="main-content" 供锚点跳转、id="form-contact" 绑定 <label for="form-contact"></label>、id="modal-confirmation" 供 JS 直接控制单个弹窗容器。
常见错误是把 id="submit-btn" 硬写在多个按钮上——document.getElementById('submit-btn') 永远只返回第一个,其余失效;服务端渲染时动态生成 id="item-{{id}}" 却没校验值唯一性,会导致 React/Vue hydration 错乱。
别为样式而用 id:CSS 中 #header 权重(100)远高于 .header(10),一旦滥用,后续靠 !important 或深层嵌套覆盖,会快速拖垮维护性。
class 的命名和组合怎么避免失控
一个元素可以有多个 class,这是它的核心优势,但前提是命名不耦合样式。写 class="red-btn" 或 class="float-right" 看似方便,换主题或改布局时就得全局搜替换,JS 里判断 el.classList.contains('float-right') 更会逻辑错位。
推荐做法:
- 基础语义名优先:
class="search-input"、class="user-avatar"、class="error-message" - 状态/变体用 BEM 修饰符:
class="card--loading"、class="button--disabled" - 工具类统一前缀隔离:
class="u-hidden u-text-center",不参与业务逻辑 - 多 class 组合代替单一大 class:
class="btn btn--primary btn--large"比class="btn-primary-large"更易复用和解耦
id 和 class 共存时的 DOM 定位风险
当一个元素同时有 id="header" 和 class="header",JS 里用 document.querySelector('.header') 和 document.getElementById('header') 表面都“能取到”,但行为完全不同:getElementById 总是唯一、确定;querySelector 取第一个匹配,若页面存在多个 class="header" 就不可靠。
更隐蔽的问题是 ARIA 和表单绑定:aria-labelledby="header" 或 for="header" 必须严格对应 id 值,class 完全无效。重复 id 不报错,但这些功能会静默失效,无障碍检测工具也常漏掉。
调试建议:在控制台运行 document.querySelectorAll('[id="header"]'),如果返回长度大于 1,说明已违反唯一性约束,必须修复。
kebab-case 是唯一安全的分隔方式
所有 id 和 class 名都必须用短横线(-)分隔,禁用驼峰(userAvatar)和下划线(user_avatar)。前者易与 JS 变量混淆,后者在旧版 IE 和部分 SSR 工具链中有解析异常;id 还不能以数字开头(id="1st-section" 非法),也不能含点号或冒号——JS 中调用 getElementById("user.email") 必须写成 getElementById("user\.email"),否则会被当 CSS 选择器解析。
BEM 中的双下划线(card__title)和双短横(card--hover)是约定,不是分隔符,它们本身属于名称一部分,仍需整体遵循 kebab-case 规则,比如 card__header--highlighted 合法,card__header_highlighted 就破坏了规范。
真正容易被忽略的不是规则本身,而是团队协作中对“语义优先”的坚持——一旦在某个组件里混用 class="nav-main" 和 class="NavMainItem",后续就很难再统一。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











