CSS Modules 通过以模块化的方式编写 CSS 代码,在 JavaScript 文件中导入和使用,自动生成唯一的类名,隔离样式,避免类名冲突。
style.module.scss
.more {
&List {
&Btn {
&:hover {
background: #fff;
}
}
}
}
index.tsx
import styles from './style.module.scss'
<Button className={styles.moreListBtn}></Button>
开发时生成的类名就长这样:
.__src_views_xxx_module__moreListBtn-a7f49f:hover {
background: #fff;
}
一般都是生成一个类名。
一个类名可能就会遇到优先级低无法覆盖样式的问题,比如Button就有这样一个外部样式:
@media (hover: hover) {
button.Btn:hover:not(.Btn--primary):not(.Btn--outline):not(:disabled) {
background: rgba(0, 0, 0, .04);
}
}
显然上面 CSS Modules 生成的样式优先级低于外部样式,自定义样式就不会生效。
!important 是不推荐的,MDN 也说了:使用 !important 是一个坏习惯,应该尽量避免,因为这破坏了样式表中的固有的级联规则 使得调试找 bug 变得更加困难了。
先复习下 CSS 优先级:
下面列表中,选择器类型的优先级是递增的:
类型选择器:(例如,h1)和伪元素(例如,::before)类选择器:(例如,.example),属性选择器(例如,[type="radio"])和伪类(例如,:hover)ID 选择器:(例如,#example)。
通配选择器(*)、关系选择器(+、>、~、" "、||)和 否定伪类(:not())对优先级没有影响。(但是,在 :not() 内部声明的选择器会影响优先级)。
ID 选择器 在 CSS Modules 中通常不建议使用。那么可以通过添加类选择器提升优先级。
@media (hover: hover) {
button.Btn:hover:not(.Btn--primary):not(.Btn--outline):not(:disabled) {
background: rgba(0, 0, 0, .04);
}
}
上面这段 CSS 的优先级是 051,即 0个ID 选择器、5个类选择器、1个类型选择器。
.__src_views_xxx_module__moreListBtn-a7f49f:hover {
background: #fff;
}
对于 <Button className={styles.moreListBtn}></Button>,生成的类名只有2个类选择器,需要添加4个类选择器使优先级达到 061 就可以覆盖外部样式。
那么如何添加类选择器又不会影响 CSS Modules 的使用呢,这时就可以通过否定伪类(:not())添加凑数类名,既可以增加类选择器提升优先级,又不会影响 CSS Modules 的使用。
.more {
&List {
&Btn:not(.priority1):not(.priority2):not(.priority3):not(.priority4) {
&:hover {
background: #fff;
}
}
}
}
生成的类名如下:
.__src_views_xxx_module__moreListBtn-a7f49f:not(
.__src_views_xxx_module__priority1-a7f49f
):not(
.__src_views_xxx_module__priority2-a7f49f
):not(
.__src_views_xxx_module__priority3-a7f49f
):not(
.__src_views_xxx_module__priority4-a7f49f
):hover {
background: #fff;
}
这样就有6个类选择器了。