局部样式被全局覆盖是css层叠规则正常工作所致,因模块化不改变选择器权重,.btn_abc123(0,1,0)敌不过.btn.btn-primary(0,2,0),需通过提权(如双重类名、根元素限定)而非依赖导入顺序或!important来解决。

全局样式覆盖局部样式,根本不是“模块化失效”,而是 CSS 层叠规则在正常工作——局部类名(如 .btn_abc123)权重仍只是 0,1,0,而框架或全局文件里一个 .btn.btn-primary 就是 0,2,0,天然赢。
为什么 import './global.css' 会盖过 import styles from './Button.module.css'
因为 Vite 的 CSS 模块编译只改类名(加哈希),不改选择器权重。全局样式若在入口文件中先导入,又用了高权重选择器,就会在层叠顺序和特异性上双重压制局部样式。
- 全局样式导入位置无关先后:只要它生成的 CSS 规则特异性 ≥ 局部规则,就生效
-
.card { max-width: 400px; }和.card_456xyz { max-width: 300px; }对比,前者胜出(权重相同,但全局 CSS 通常更早注入) - Vue 的
<style scoped></style>或 React 的 CSS Modules 都不改变这个底层逻辑,只是加了属性选择器或哈希类名
怎么让局部样式真正“赢”?别用 !important,改选择器结构
提升局部选择器权重,是最可控、可维护的方式。CSS Modules 支持嵌套语法(如 Sass/PostCSS),直接在模块文件里提权:
.btn {
padding: 8px 16px;
}
/* 双重类名:权重从 0,1,0 → 0,2,0 */
.btn.btn {
background: #1890ff;
}
/* 或用组件根元素限定 */
.Button-root .btn {
border-radius: 4px;
}
- 避免写
div .btn这种低效提权(增加无意义标签,影响性能) - 不要依赖导入顺序“赌先后”,浏览器解析 CSS 是异步且不可靠的
- 如果组件有唯一根 class(如
<div class="Button">),用 <code>.Button .btn最稳妥如何防止第三方全局样式穿透进你的模块?
像 Bootstrap、Ant Design 这类库的 CSS 是纯全局的,它们的
.ant-btn会匹配你组件里任何带该 class 的元素——哪怕你在Button.module.css里写了同名规则,也大概率被压。- 不用
composes复用第三方 class:它会把外部 class 名拼进你的模块作用域,等于主动引入冲突 - 用 wrapper 容器切断影响:
<div class="my-button-wrapper"><button class="ant-btn"></button></div>,再写.my-button-wrapper .ant-btn { ... } - 对重置类(如
* { box-sizing: border-box })保持警惕:它会继承到你模块内所有元素,BEM 组件可能因此错乱;改用:where(*) { box-sizing: border-box }降权
检查时最容易忽略的一点:DevTools 里被划掉的规则未必是“被覆盖”
比如你看到
.card { max-width: 400px; }被划掉,点开“Computed”面板发现实际生效的是html .card { max-width: auto; }——这不是优先级问题,而是继承链上某处写了max-width: inherit或父元素限制了宽度。真正要盯的是“Styles”侧边栏里每条规则末尾显示的 specificity 值(如
0,2,0),以及来源文件路径是否指向你没意识到的全局 reset 或框架 CSS。一旦发现是bootstrap.min.css在起作用,就别修你的模块文件,去 wrapper 或提权。 - 不用











