是否有基于CSS自定义属性创建可主题化组件变体的最佳实践



我目前正在与一个团队合作开发一组web组件,这些组件应该是客户公司开发的当前和即将开发的web应用程序的基础。

我希望这些组件支持颜色主题化;这方面的第一个用例是支持暗模式

当前方法

  • 我在文件colorpalette.css中定义了客户的公司设计颜色(这些颜色只是一个例子):

    :root {
    --color-blue: #004994;
    --color-light-blue: #0095db;
    --color-light-green: #afca06;
    --color-light-grey: #9c9c9c;
    --color-green: #51ae31;
    --color-grey: #555555;
    --color-orange: #f39200;
    --color-red: #d40f14;
    --color-turquoise: #008c8e;
    --color-violet: #b80d78;
    --color-yellow: #ffcc00;
    --color-white: #ffffff;
    --color-black: #000000;
    }
    
  • 我正在确保所有其他使用或定义颜色的文件只使用此文件中的颜色。这导致了一个文件colors.css,我开始为每个主题定义不同的颜色:

    @import "./colorpalette.css";
    :root {
    --bg-color-button: var(--color-light-grey);
    --text-color-button: var(--color-black);
    --border-color-button: var(--color-grey);
    }
    :root[data-theme=dark] {
    --bg-color-button: var(--color-grey);
    --text-color-button: var(--color-white);
    --border-color-button: var(--color-light-grey);
    }
    

到目前为止,我对这种方法感到满意。

问题

现在我开始添加这些按钮的不同语义版本:.btn-danger.btn-success等,它们应该使用颜色作为传输这些语义的手段。

可能的解决方案-两种不同的替代方案

这是我不确定的地方,因为我看到了两个替代方案:

  1. 为这些语义创建新的变量,并在其名称中携带语义:

    :root {
    --bg-color-button-success: var(--color-light-green);
    --text-color-button-success: var(--color-black);
    --border-color-button-success: var(--color-green);
    }
    

    并在按钮样式定义中使用这些:

    .btn {
    background-color: var(--bg-color-button);
    color: var(--text-color-button);
    border-color: var(--border-color-button);
    }
    .btn.btn-success {
    background-color: var(--bg-color-button-success);
    color: var(--text-color-button-success);
    border-color: var(--border-color-button-sucess);
    }
    
    • 优点
      • 只需修改两个文件,就可以重新设置整个应用程序的主题
    • Cons
      • 这种方法显然会产生无数的变量,因为我们需要为每个需要应用不同颜色的地方定义一个单独的变量
      • 如果以后要引入其他按钮变体,则必须同时编辑colors.cssbutton.css
  2. 另一种方法可以是在指定上下文中重新定义现有变量:

    .btn {
    background-color: var(--bg-color-button);
    color: var(--text-color-button);
    border-color: var(--border-color-button);
    }
    .btn.btn-success {
    --bg-color-button: var(--color-light-green);
    --text-color-button: var(--color-black);
    --border-color-button: var(--color-green);
    }
    
    • 优点
      • alot更少的变量
      • 变量只有在实际使用的地方才会被重新定义
      • 定义新的按钮变体比其他方法更容易,因为您只需要编辑button.css
    • Cons
      • 要重新命名组件库,除了colorpalette.csscolors.css之外,您可能还需要触摸每个组件的css文件

我试着总结了两种方法的优缺点。

问题

比起另一种方式,更喜欢一种方式的其他原因是什么?

提示

在最终投票关闭之前,请考虑以下

我知道很多人可能会认为这个问题是离题的,因为它吸引了固执己见的答案,但我相信这个问题对许多开发人员来说有很大的实际意义,因为css自定义属性最近才成为事实上的标准,这通常会导致最佳实践慢慢出现。因此,固执己见的答案以及这些观点的原因正是我在这里有意问的。

这也绝不是最佳实践CSS主题的重复,因为这个问题来自2010年,当时CSS自定义属性并不存在。

在我看来,主题系统的优先级要求很容易改变外观。因此,您的第一个解决方案将适用于这种情况。让我们谈谈它的缺点。

这种方法显然会产生无数的变量,因为我们需要为每个需要应用不同的颜色

需要更多的变量。因为它们有不同的用途。当您重新设计主题时,它将帮助您快速更改外观,而无需进入所有组件文件。你只需要关心它,以防重新设计主题。所以我认为这不应该被视为缺点。

如果您以后想引入其他按钮变体,您可以必须编辑CCD_ 10和CCD_。

同样,我不认为这是缺点,因为您只需要在2个文件中添加一些额外的代码。这些代码不会影响以前存在的任何东西。

但是您忘了提到这种方法的最大缺点。你需要重写CSS规则。如果我们使用渐变背景会发生什么?代码是这样的:

.btn {
background: linear-gradient(to left, var(--text-color-button-1), var(--text-color-button-2) 50%, var(--text-color-button-3) 75%, var(--text-color-button-4) 75%);
color: var(--text-color-button);
border-color: var(--border-color-button);
}
.btn.btn-success {
background: linear-gradient(to left, var(--text-color-button-success-1), var(--text-color-button-success-2) 50%, var(--text-color-button-success-3) 75%, var(--text-color-button-success-4) 75%);
color: var(--text-color-button-success);
border-color: var(--border-color-button-sucess);
}

如果我们想把50%的数字改成另一个,那将是一场噩梦。因此,让我们将您的两种方法结合为一,以解决它们的缺点。

这是那些想要快速扫描的人的解决方案

color.css

--color-red-100: red;
--color-red-500: red;
--color-red-900: red;
--color-green-100: green;
--color-green-500: green;
--color-green-900: green;
--color-bg-button-1: var(--color-red-100);
--color-bg-button-2: var(--color-red-500);
--color-bg-button-3: var(--color-red-900);
--color-bg-button-4: var(--color-red-100);
--color-bg-button-success-1: var(--color-green-100);
--color-bg-button-success-2: var(--color-green-500);
--color-bg-button-success-3: var(--color-green-900);
--color-bg-button-success-4: var(--color-green-100);

button.css

.btn {
background: linear-gradient(to left, var(--text-color-button-1), var(--text-color-button-2) 50%, var(--text-color-button-3) 75%, var(--text-color-button-4) 75%);
}
.btn.btn-success {
--text-color-button-1: var(--color-bg-button-success-1);
--text-color-button-2: var(--color-bg-button-success-2);
--text-color-button-3: var(--color-bg-button-success-3);
--text-color-button-4: var(--color-bg-button-success-4);
}

在这种方法中

  • 通过使用基本颜色变量,如果你只想调整一些灰度,你只需要更改基本颜色变量、按钮和其他任何东西都会相应地更改
  • 通过使用作用域变量但链接到新变量,您不需要重写CSS规则,只需编辑一个文件中的变量值就可以轻松地重新设计主题
  • 当然,这种方法仍然有第一个解决方案的两个缺点,但我认为它可以用于更高优先级的要求

对我来说,最佳实践应该放在特定的上下文中,所以这个解决方案非常适合,以防你的首要任务是轻松地重新设计主题。如果你只想使用CSS变量来轻松重用,并且没有任何改变变量值的计划,那么应该选择OP的第二个解决方案来进行快速编程。

最新更新