应避免使用标签选择器(如img、button)以防全局样式污染,而应采用带业务语义的类名(如.product-card__image)或属性选择器(如[data-ui="highlight"] code)实现样式隔离。

直接用 div、p、img 这类标签选择器,几乎必然污染全局样式——它不看你在哪个组件里写,只认页面里所有匹配的元素。
为什么 img 一设就全站变样?
浏览器对 img 这种标签选择器没有“文件作用域”概念。你在一个组件的 CSS 文件里写 img { border-radius: 4px; },构建后它会被注入全局 <style> 标签,立刻生效于所有 <img> 元素,包括第三方库里的图片、服务端渲染的静态图、甚至 dangerouslySetInnerHTML 插入的内容。
常见错误现象:
- 给轮播图加了
img { max-width: 100%; },结果头像、图标、SVG 内嵌图全被拉伸变形 - 想微调某张插图的
vertical-align,却导致表格内所有图片基线错乱 - 用
button重置默认样式,顺手把 Ant Design 的<Button>按钮边框也干掉了
class 是最简单有效的隔离手段
不用改架构、不依赖构建工具,只要把标签选择器换成带语义的类名,就能切断全局影响链。关键不是“要不要加 class”,而是 class 名是否具备归属感。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 禁止裸写
img、button、h2等标签选择器;必须搭配明确上下文,比如.article-content img或.user-avatar - 类名要带业务锚点:
.product-card__image比.card-img更可靠,后者仍可能和.blog-card__image冲突 - 第三方组件无法改源码时,用属性选择器兜底:
[data-ui="highlight"] code比code安全得多 - 重置样式(如
*, *::before, *::after)只放在入口 CSS 最顶部,且仅限box-sizing、margin等基础项
CSS Modules 不是万能解药
启用 Button.module.css 后,.btn 会变成 Button_btn__abc123,但前提是:你没在任何地方写过 img 这种全局规则。CSS Modules 只处理 class 和 id,对标签选择器完全放行。
容易踩的坑:
- 以为开了 CSS Modules 就高枕无忧,继续在
.module.css里写img { opacity: 0.8; }→ 依然全局生效 - 混用普通
.css和.module.css:前者导入即全局注入,后者局部作用域,冲突源头反而更隐蔽 - Vite 项目中,
.css文件永远不模块化,哪怕内容只供一个组件用
@scope 还不能当主力用
@scope (.card) { img { border-radius: 8px; } } 理论上能锁死作用域,但截至 2026 年 8 月,Chrome 127+ 支持,Firefox 和 Safari 仍无稳定实现。生产环境强行使用,等于主动放弃兼容性。
当前务实做法:
- 把
@scope当作未来储备知识,别在上线代码里依赖它 - 真要强隔离,优先走 BEM + 属性选择器组合:
.card[data-scope="product"] img - 动态插入的 DOM(如富文本解析结果),用
data-属性统一打标,再配精准选择器,比指望@scope实际得多
最常被忽略的一点:样式污染往往不是来自“写了什么”,而是来自“没删什么”。旧项目里残留的 ul, ol { margin: 0; } 这类规则,比新写的任何模块化 CSS 都更容易悄悄毁掉整个布局。


















