问题描述
项目在引入@carbon/react(下称carbon) 之后, 一些原有样式被覆盖, 而且无法通过! important的声明方式提高优先级
比如自定义组件的border全部消失了
项目主要配置如下
{
"dependencies": {
"@carbon/react": "^1.61.0",
"next": "^14.2.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.77.7",
},
}
分析
Q: 样式是否正确声明?
A: 查看开发者工具-元素审查器中的目标元素样式发现样式声明有效
Q: 样式是否被覆盖?
A: 查看开发者工具-元素审查器中的样式列表中搜索border发现了一处样式覆盖
Q: 被覆盖的是border-width为什么笃定此处border声明是幕后黑手
A: CSS中border: 0是一个简写属性, 它的语法是
border =
<line-width> ||
<line-style> ||
<color>
所以border: 0 等同于 border-width: 0; border-style: none; border-color: initial这个结论在元素审查器中得以证实(border-width, border-style, border-color也分别是简写属性)
解决
既然找到了幕后黑手那么我们就要消除它的影响, 通过在代码中查找这部分属性, 我们定位到了carbon 内的一个文件, 样式被声明在一个reset对象中
这也解释了为什么样式覆盖问题是在引入carbon之后出现, 并且reset是在carbon被引入时的默认配置
至于carbon为什么要这样做, 我们在github上找到了这样一条相关issue: Change to _css--reset.scss is invasive / overreaching#195 老哥使用了effectively broken/argue/pollute 等激烈的措辞表达自己项目内样式被污染的不满, 而项目维护者表示项目是为了majority of people out of the box functionality使用的, 爱用不用. 天下苦carbon久矣, 但是谁叫它好看呢, 忍了. 而另外一个issue: Allow non-carbon projects to use ALL the carbon-component's required styles, without interfering with their own styles #6783中, 妹子提出了类似的问题, 但是她似乎不想通过使用css--reset: false(记住, 下面要考)关闭所有的override.
跑题了, 收.
前面说到了border: 0覆盖了border-width: 0; border-style: none; border-color: initial所以我们为了让border样式生效需要同时声明这三个属性
我们丢失的样式又回来了!
问题真的解决了么?
为什么在没有引入carbon之前不需要额外声明border-style就可以显示边框, 难道除了幕后黑手在捣乱之外, 还有好心人在默默帮助我们?
通过继续在元素样式列表中搜索border-style, 发现了这位好心人
是他在为我们保驾护航, 确保每一个border在被书写的时候就被分配了一只叫solid的伴生灵兽.
那么问题来了, 好心人他来自何方呢?
通过搜索我们找到了他的家庭住址
/* ! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com */
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0; /* 2 */
border-style: solid; /* 2 */
border-color: #e5e7eb; /* 2 */
}
至此我们铲除了坏人, 又让好人好事得以宣传, 心满意足.
还没完!?
上面提到通过css--reset: false可以关闭carbon的默认配置, 我们来验证一下, 通过在引入carbon的地方添加配置项:
@use '@carbon/react' with (
$css--reset: false,
$css--default-type: false
);
我们的border又回来了, 可喜可贺
后记
在搜索carbon的样式覆盖问题的时候, 发现了官方的FAQ What packages should I be installing?中, 提出除了整体引入之外
@use '@carbon/react';
也可以使用按需引入的方式
@use '@carbon/react/scss/components/[componentname]';
这样也间接避免了reset的引入, 从而让全局样式不被污染
同时按需引入的方式也可以大大提高项目hot reload的速度, 下面是整体引入和按需引入的速度对比
整体引入
按需引入
当然这种方法依然有引入非必要样式的风险, 所以应该结合按需引入和完整样式声明.