id选择器必须唯一,用于可访问性锚点和ARIA关联;class选择器可复用,适用于样式和JS操作;现代开发中禁用id写样式,推荐data属性或js-前缀class供JS使用。

class 选择器能复用,id 选择器必须唯一
一个页面里可以有多个 .btn 元素,但只能有一个 #header。浏览器不强制校验 id 重复,但一旦出现,document.getElementById() 只返回第一个匹配元素,getElementById 在 JS 中失效风险高;CSS 层叠时,重复 id 的样式可能被意外覆盖或忽略。
- id 用于标记页面中逻辑上不可分割的单一实体,比如
#main-nav、#user-modal - class 用于标记具有相同视觉或行为特征的一组元素,比如
.card、.is-disabled、.theme-dark - 服务端渲染或 SSR 场景下,id 重复还会导致 hydration 失败(React/Vue 均有此问题)
id 选择器优先级高于 class,但不该靠它“赢”样式
CSS 优先级规则里,#sidebar 的权重是 100,而 .sidebar-item 是 10。这容易诱使开发者用 #form-submit-btn 替代 .btn-primary 来“确保样式生效”,结果是样式越来越难维护、无法组合、无法主题化。
- 优先级差异在调试时表现为:明明写了
.btn:hover { color: red; },但没生效——可能是某个父级用了#page-wrapper并设置了color: blue; - 现代 CSS 方法论(如 BEM、ITCSS)明确禁止用 id 写样式,只允许用在 JS Hook 或 ARIA 关联(如
aria-labelledby) - 若真需提高权重,改用更具体的 class 组合,比如
.form .btn-primary,而不是塞个 id
JS 操作时,id 快但脆弱,class 灵活但需遍历
document.getElementById('save-btn') 比 document.querySelector('.save-btn') 快,但前提是那个 id 真的存在且没被动态删掉。一旦组件重渲染、条件渲染或测试环境模拟 DOM,id 就容易丢失或冲突。
- 推荐写法:
document.querySelector('[data-testid="save-button"]')(测试专用)或document.querySelector('.js-save-btn')(带js-前缀的 class,专供 JS 使用,不参与样式) - 避免在 JS 中依赖 id 做事件委托,比如
document.getElementById('list').addEventListener(...)—— 改用document.querySelector('.item-list')更健壮 - 使用框架(React/Vue)时,直接用 ref 或 refKey,根本不需要手动查 id 或 class
可访问性与语义中,id 不是装饰,而是锚点和关联凭证
id 最不可替代的作用是支撑 ARIA 和原生 HTML 语义:label for="email"、aria-describedby="error-123"、id="tooltip-1" 都依赖 id 的唯一性和稳定性。这里不能用 class 替代。
立即学习“前端免费学习笔记(深入)”;
- 表单控件必须配
id,否则失效,屏幕阅读器无法正确关联 - 模态框的
aria-labelledby和aria-describedby属性值必须指向真实存在的 id - SPA 路由跳转后,用
location.hash = '#section2'滚动到对应,这个 id 不能是动态生成或重复的
请输入有效邮箱
复杂点在于:同一个 id 既要满足可访问性要求,又不能被 CSS 或 JS 错误地当成样式钩子或操作目标。开发中常被忽略的是——把 id 当 class 用,既写样式又绑 JS 还搞 ARIA,三者耦合后,一改全崩。










