ID属性必须全局唯一,class可重复使用;ID选择器权重(100)远高于类选择器(单个10),且!important无法跨层级覆盖;现代开发中ID仅适用于label关联、锚点跳转、自动化测试及ARIA属性等有限场景,CSS中应避免使用ID选择器。

id属性必须全局唯一,class可以重复使用
HTML 规范强制要求 id 值在整个文档中只能出现一次。浏览器不校验重复,但后果明确:CSS 样式可能只作用于第一个匹配元素;document.getElementById() 永远只返回第一个;React/Vue 的 hydration 会直接失败。而 class 属性天生设计为可复用——多个元素共用同一个类名完全合法,一个元素也可以同时拥有多个类名(如 class="btn btn-primary js-submit")。
#header 和 .btn 的优先级不是“谁更强”,而是“不可覆盖”
ID 选择器权重固定为 100,类选择器单个是 10。这意味着哪怕你写 .submit-btn.submit-btn.submit-btn(权重 30),也压不过 #submit-btn(权重 100)。这不是“建议避免”,而是调试时真实卡点:你改了 CSS 却没生效,大概率是某个父容器或组件悄悄用了 ID 选择器。更麻烦的是,!important 在这种跨权重层级冲突里无效——它只在同级权重内起作用。
现代开发中,ID 几乎不该出现在 CSS 文件里
真正需要 ID 的场景非常有限:label[for="email"] 必须对应 input#email;页面内锚点跳转依赖 id="section-2";自动化测试用 data-testid 或稳定 ID 定位元素。除此之外,用 ID 写样式等于主动放弃组合性、主题切换能力和团队协作安全性。BEM、CSS Modules、Tailwind 等主流方案都默认绕开 ID——不是技术不能,而是语义和工程成本不允许。
JS 查 DOM 时,querySelector('.modal') 比 getElementById('modal') 更健壮
看起来 getElementById() 更快,但它依赖 ID 绝对存在且唯一。动态渲染、条件展示、服务端模板拼接都容易导致 ID 重复或缺失。而 document.querySelector('.js-modal') 或 document.querySelector('[data-component="modal"]') 虽然多一次遍历,却能天然兼容重复、条件、批量场景。如果真要给 JS 用专用标识,推荐带前缀的 class(如 class="js-dropdown-toggle")或 data- 属性,而不是把样式层的 ID 当作行为层的钩子。
立即学习“前端免费学习笔记(深入)”;
最常被忽略的其实是可访问性约束:aria-labelledby、aria-controls、aria-describedby 这些属性值必须指向真实存在的、唯一的 ID。这里 class 无法替代——不是语法问题,是标准强制要求。所以 ID 不是“过时”,而是用途窄、责任重,用错地方比不用还危险。


















