一种所有浏览器都支持的新方法,用于将颜色存储在 CSS 变量中并使用 SASS 函数对其进行修改。
我们都知道这一点。HSL 颜色值是最好的。同意!SASS颜色功能很棒。是的,没什么新鲜事。但是如何结合这些东西并在今天使用它们呢?有办法!
我们为我们的框架开发了一种新的方法,该方法将本机变量(存储HSL颜色值)的灵活性与SASS函数的实用性相结合。
👋 您第一次听说CodyHouse框架吗?
* 开始使用
* 浏览组件
* 全球编辑
在我们的框架中,我们使用CSS变量。我们集成了 postcss-css-variables 插件的修改版本,为不支持它们的浏览器生成回退。我们更喜欢 CSS 变量而不是 SASS 变量,因为您可以在特定断点(或使用类)覆盖它们的值。事实证明,此功能对于开发我们的响应式间距和排版系统以及颜色主题特别有用。
也就是说,以下是我们在启动框架(v 1.0.0)时定义颜色变量的方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| :root, [data-theme="default"] {
// main
--color-primary-darker: hsl(220, 90%, 36%);
--color-primary-dark: hsl(220, 90%, 46%);
--color-primary: hsl(220, 90%, 56%);
--color-primary-light: hsl(220, 90%, 66%);
--color-primary-lighter: hsl(220, 90%, 76%);
--color-primary-a20: hsla(220, 90%, 56%, 0.2);
--color-accent-darker: hsl(355, 90%, 41%);
--color-accent-dark: hsl(355, 90%, 51%);
--color-accent: hsl(355, 90%, 61%);
--color-accent-light: hsl(355, 90%, 71%);
--color-accent-lighter: hsl(355, 90%, 81%);
// color contrast
--color-bg: hsl(0, 0%, 100%);
--color-bg-a00: hsla(0, 0%, 100%, 0);
--color-contrast-lower: hsl(0, 0%, 95%);
--color-contrast-low: hsl(240, 1%, 83%);
--color-contrast-medium: hsl(240, 1%, 48%);
--color-contrast-high: hsl(240, 4%, 20%);
--color-contrast-higher: hsl(240, 8%, 12%);
--color-contrast-higher-a90: hsla(240, 8%, 12%, 0.9);
// semantic
--color-border: var(--color-contrast-low);
// ...
}
|
HSL 颜色值很棒,因为它们使创建颜色变化变得直观。只需编辑色调、饱和度和亮度值。这些数字很容易阅读。
但是,当我们开始处理组件时,我们意识到没有简单的方法来设置颜色的 alpha 值:
1
2
3
| .component {
background-color: hsla(var(--color-primary), 0.2); // not working 😥
}
|
您可以将 CSS 变量包含在 SASS mixins 和函数中,但上面的代码会返回一个无效的值(–var(color) 被 hsl(x,x%,x%) 替换)。
如何解决这个问题?
首先,我们尝试使用 CSS原生颜色函数。
1
2
3
| .component {
background-color: color-mod(var(--color-primary) alpha(20%));
}
|
它们很整洁,但远未得到主要浏览器的支持。我们尝试集成一些PostCSS插件来生成回退,但没有运气。我们在最终输出中不断出现错误,因此我们认为这种方法太不可靠了。
因为我们的问题无法为颜色设置不透明度值,所以第二个方法是为 alpha 值创建 CSS 变量:
1
2
3
4
| :root, [data-theme="default"] {
--color-primary: hsl(220, 90%, 56%);
--color-primary-a20: hsla(220, 90%, 56%, 0.2);
}
|
在组件级别,您可以通过应用 alpha 变量来设置 alpha 值:
1
2
3
| .component {
background-color: var(--color-primary-a20);
}
|
请记住,目标是将所有颜色值存储到单个文件中,以便整个系统易于维护。我们不能只在组件级别使用 hsla。_colors.scss
虽然我们不是100%相信这个解决方案,但我们决定在框架的第一个版本中采用它。
事实证明,为 alpha 值创建变量是一个糟糕的解决方案,主要有两个原因:
- 如果您在组件级别工作,则每当想要对颜色使用不同的 Alpha 值时,都必须切换到该文件。_colors.scss
- 因为我们的系统基于颜色主题(颜色是可互换的),所以如果你为一种颜色创建一个 alpha 变量,你必须对所有其他颜色做同样的事情。
我们又回到了原点。
以下是最终得到我们认为是一个很好的解决方案的过程:首先,我们尝试使用 mixin 来指定 alpha 值。此混合需要 3 个变量:、 和 。$property$color-variable$opacity
我们会像这样使用mixin:
1
2
3
| .component {
@include alpha(background-color, --color-primary, 0.2);
}
|
虽然这是mixin的代码:
1
2
3
4
5
6
| @mixin alpha($property, $color-variable, $opacity) {
$color-variable-h: var(#{$color-variable+'-h'});
$color-variable-s: var(#{$color-variable+'-s'});
$color-variable-l: var(#{$color-variable+'-l'});
#{$property}: hsla($color-variable-h, $color-variable-s, $color-variable-l, $opacity);
}
|
为此,我们需要为每种颜色设置 3 个变量:
:root, [data-theme="default"] {
--color-primary: hsl(220, 90%, 56%);
--color-primary-h: 220;
--color-primary-s: 90%;
--color-primary-l: 56%;
}
其中是色调值,是饱和度百分比,是亮度百分比(不,我们不想放弃HSL颜色值☝️)。--color-name-h--color-name-s--color-name-l
仍然太复杂了,但我们正在到达某个地方。
在这一点上,我们想出了创建我们自己的alpha SASS函数来替换mixin的想法。这将允许我们以更友好的方式编写 CSS 声明:
1
2
3
| .component {
background-color: alpha(var(--color-primary), 0.2);
}
|
下面是函数的代码:
// return css color variable with different opacity value
@function alpha($color, $opacity){
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsla($color-h, $color-s, $color-l, $opacity);
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
越来越近!困扰我们的最后一件事是必须为每种颜色(色调、饱和度、亮度)手动创建 3 个附加变量。这很烦人,因为您必须在修改颜色时更新这些变量的值。
啊哈时刻意识到我们可以使用 SASS mixin 来定义每种颜色,以便我们可以在 CSS 中自动生成色调、饱和度和亮度值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| @mixin defineColorHSL($color, $hue, $saturation, $lightness){
#{$color}: unquote("hsl(#{$hue}, #{$saturation}, #{$lightness})");#{$color}-h: #{$hue};#{$color}-s: #{$saturation};#{$color}-l: #{$lightness};
}
:root, [data-theme="default"] {
@include defineColorHSL(--color-primary, 220, 89%, 56%);
@include defineColorHSL(--color-accent, 355, 90%, 61%);
@include defineColorHSL(--color-black, 240, 8%, 12%);
@include defineColorHSL(--color-white, 0, 0%, 100%);
// color contrasts
@include defineColorHSL(--color-bg, 0, 0%, 100%);
@include defineColorHSL(--color-contrast-lower, 0, 0%, 95%);
@include defineColorHSL(--color-contrast-low, 240, 1%, 83%);
@include defineColorHSL(--color-contrast-medium, 240, 1%, 48%);
@include defineColorHSL(--color-contrast-high, 240, 4%, 20%);
@include defineColorHSL(--color-contrast-higher, 240, 8%, 12%);
}
|
这种方法的好处是,您仍然以易于理解的语法声明颜色,并允许您创建修改 HSL 值的颜色变体:
1
2
3
4
5
6
7
| :root, [data-theme="default"] {
@include defineColorHSL(--color-primary-darker, 220, 90%, 36%);
@include defineColorHSL(--color-primary-dark, 220, 90%, 46%);
@include defineColorHSL(--color-primary, 220, 90%, 56%);
@include defineColorHSL(--color-primary-light, 220, 90%, 66%);
@include defineColorHSL(--color-primary-lighter, 220, 90%, 76%);
}
|
在 SCSS 中,您可以使用 alpha 函数设置不透明度值:
1
2
3
| .component {
background-color: alpha(var(--color-primary), 0.2); // it works 🎉
}
|
它有效🙌!我们刚刚推送了一个框架更新(v 1.1.0),其中包括新的mixins和一个更新的文件。_colors.scss
由于此方法允许您访问和修改色调、饱和度、亮度和 alpha 值,因此您可以为每个值创建一个函数!
编辑亮度:
1
2
3
4
5
6
7
8
9
10
11
12
| @function lightness($color, $lightnessMultiplier){
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsl($color-h, $color-s, calc(#{$color-l} * #{$lightnessMultiplier}));
}
.component {
background-color: lightness(var(--color-primary), 1.2);
}
|
编辑饱和度:
1
2
3
4
5
6
7
8
9
10
11
12
| @function saturation($color, $saturationMultiplier){
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsl($color-h, calc(#{$color-s} * #{$saturationMultiplier}), $color-l);
}
.component {
background-color: saturation(var(--color-primary), 1.2);
}
|
我们框架的主要目标是简化启动 Web 项目的过程。我们觉得我们正在朝着这个目标前进。如果您对我们可以改进的地方有任何建议,请与我们联系!欢迎任何反馈。