Carbon Design 样式覆盖

205 阅读3分钟

问题描述

项目在引入@carbon/react(下称carbon) 之后, 一些原有样式被覆盖, 而且无法通过! important的声明方式提高优先级

比如自定义组件的border全部消失了

Screenshot 2024-07-11 at 14.53.26.png

Screenshot 2024-07-11 at 14.51.08.png

项目主要配置如下

{
    "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: 查看开发者工具-元素审查器中的目标元素样式发现样式声明有效

Screenshot 2024-07-11 at 14.59.46.png

Q: 样式是否被覆盖?

A: 查看开发者工具-元素审查器中的样式列表中搜索border发现了一处样式覆盖

Screenshot 2024-07-11 at 15.14.55.png

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也分别是简写属性)

Screenshot 2024-07-11 at 15.29.24.png

解决

既然找到了幕后黑手那么我们就要消除它的影响, 通过在代码中查找这部分属性, 我们定位到了carbon 内的一个文件, 样式被声明在一个reset对象中

Screenshot 2024-07-11 at 15.35.07.png

这也解释了为什么样式覆盖问题是在引入carbon之后出现, 并且reset是在carbon被引入时的默认配置

Screenshot 2024-07-11 at 16.04.32.png

至于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样式生效需要同时声明这三个属性

Screenshot 2024-07-11 at 15.48.57.png

我们丢失的样式又回来了!

Screenshot 2024-07-11 at 15.50.01.png

问题真的解决了么?

为什么在没有引入carbon之前不需要额外声明border-style就可以显示边框, 难道除了幕后黑手在捣乱之外, 还有好心人在默默帮助我们?

通过继续在元素样式列表中搜索border-style, 发现了这位好心人

Screenshot 2024-07-11 at 15.55.08.png

是他在为我们保驾护航, 确保每一个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又回来了, 可喜可贺

Screenshot 2024-07-11 at 15.50.01.png

后记

在搜索carbon的样式覆盖问题的时候, 发现了官方的FAQ What packages should I be installing?中, 提出除了整体引入之外

@use '@carbon/react';

也可以使用按需引入的方式

@use '@carbon/react/scss/components/[componentname]';

这样也间接避免了reset的引入, 从而让全局样式不被污染

同时按需引入的方式也可以大大提高项目hot reload的速度, 下面是整体引入和按需引入的速度对比

整体引入

Screenshot 2024-07-11 at 14.31.44.png

按需引入

Screenshot 2024-07-11 at 14.31.23.png

当然这种方法依然有引入非必要样式的风险, 所以应该结合按需引入完整样式声明.