颜色是数学:它们如何匹配——以及如何构建颜色选择器

2025-05-25

颜色是数学:它们如何匹配——以及如何构建颜色选择器

为什么有些颜色组合比其他颜色组合看起来更好?剧透:这和数学有关。

前几天,我在我的新网站上写了有关颜色主题工具的文章。

此工具以及我将在本文中介绍的一些其他颜色工具均基于HSL颜色格式。

HSL 代表色调饱和度和亮度

色相是主要颜色,以度数表示。
如果你观察色轮,你会发现它是一系列以 30° 为间隔的颜色:

色轮

在 CSS 中,它是:

.wheel {
  background: conic-gradient(
    hsl(0, 100%, 50%), 
    hsl(30, 100%, 50%), 
    hsl(60, 100%, 50%), 
    hsl(90, 100%, 50%), 
    hsl(120, 100%, 50%), 
    hsl(150, 100%, 50%), 
    hsl(180, 100%, 50%), 
    hsl(210, 100%, 50%), 
    hsl(240, 100%, 50%), 
    hsl(270, 100%, 50%), 
    hsl(300, 100%, 50%), 
    hsl(330, 100%, 50%),
    hsl(360, 100%, 50%)
  );
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

要将其变成水平或垂直滑块,请将渐变类型更改为linear-gradient

线性渐变


匹配颜色

当颜色搭配在一起时看起来很棒,这完全取决于它们在色环中之间的关系。

当您选择一种颜色(我们称之为原色)时,与该颜色正对面的颜色(180° 度)称为色 - 这两种颜色搭配在一起总是很好看。

我们将 HSL 拆分为 3 个 CSS 自定义属性:

--h--s--l

– 看看我们如何使用简单的数学来calc匹配我们的原色

.primary {
  hsl(var(--h), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

加180°为--h

.complimentary {
  hsl(calc(var(--h) + 180), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

分裂互补色与原色之间的夹角为 150° 和 210°

.splitcom1 {
  hsl(calc(var(--h) + 150), var(--s), var(--l));
}
.splitcom1 {
  hsl(calc(var(--h) + 210), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

类似色是所选颜色旁边的颜色(两侧)——在本例中是我们的原色

.analogous1 {
  hsl(calc(var(--h) + 30), var(--s), var(--l));
}
.analogous2 {
  hsl(calc(var(--h) - 30), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

色在色轮上均匀分布,因此从我们的原色来看,它的 120° 和 240°(或:负 120°):

.triad1 {
  hsl(calc(var(--h) + 120), var(--s), var(--l));
}
.triad2 {
  hsl(calc(var(--h) - 120), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

方形颜色我们的原色以及 90°、180°(补色)和 270° 的颜色组成:

.square1 {
  hsl(calc(var(--h) + 90), var(--s), var(--l));
}
.square2 {
  hsl(calc(var(--h) + 270), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

四色矩形正方形类似,由 60°、180°(互补色)和 240° 的颜色组成:

.tetra1 {
  hsl(calc(var(--h) + 60), var(--s), var(--l));
}
.tetra2 {
  hsl(calc(var(--h) + 240), var(--s), var(--l));
}
Enter fullscreen mode Exit fullscreen mode

色调

色彩为亮度增添光彩--l

.tint10 {
  hsl(var(--h), var(--s), calc(var(--l) + ((100% - var(--l)) / 10) * 1));}
.tint20 {
  hsl(var(--h), var(--s), calc(var(--l) + ((100% - var(--l)) / 10) * 2));
}
/* etc. */
Enter fullscreen mode Exit fullscreen mode

色调

阴影会消除--l亮度中的光:

.shade10 {
  hsl(var(--h), var(--s), calc(var(--l) - ((100% - var(--l)) / 10) * 1));
}
.shade20 {
  --c-sh2: hsl(var(--h), var(--s), calc(var(--l) - ((100% - var(--l)) / 10) * 2));
}
/* etc. */
Enter fullscreen mode Exit fullscreen mode

所有这些 CSS calculated -colors 都是我在CSS 颜色主题工具中使用的,基于--h--s--l属性:

颜色主题

现在,让我们看看如何构建颜色选择器。


HSL 颜色选择器

创建一个简单的、基于 HSL 的颜色选择器只需要三个<input type="range">控件,每个 CSS 自定义属性一个:--h--s--l

<form id="hsl">
  <input type="range" name="--h" min="0" max="360" value="0" />
  <input type="range" name="--s" min="0" max="100" value="100" data-suffix="%" />
  <input type="range" name="--l" min="0" max="100" value="50" data-suffix="%" />
  <div class="hsl"></div>
</form>
Enter fullscreen mode Exit fullscreen mode

在 CSS 中,根据需要设置滑块的样式,并将计算出的 HSL 颜色分配给颜色预览<div class="hsl">

.hsl {
  aspect-ratio: 1/1;
  background-color: hsl(var(--h,0), var(--s,100%), var(--l, 50%));
  width: 20rem;
}
Enter fullscreen mode Exit fullscreen mode

最后,在 JavaScript 中,在表单上添加一个 eventListener ,它将更新 CSS 自定义属性:

hsl.addEventListener('input', (event) => {
  const input = event.target;
document.documentElement.style.setProperty(input.name, `${input.valueAsNumber}${input.dataset.suffix||''}`)
})
Enter fullscreen mode Exit fullscreen mode

就这样!我用这个方法(以及一些 JavaScript)创建了这些小型颜色选择器

稍微复杂一点的是,这个颜色工具还使用基于 HSL 的滑块和 JavaScript 在各种格式(rgb、cmyk、hex)之间进行转换:

色彩编辑器

它还具有渐变编辑器,适用于所有类型的 CSS 渐变:圆锥渐变、线性渐变和径向渐变:

坡度

您可以在 Codepen 上找到该工具:


奖励:HSB 颜色选择器

Photoshop

Photoshop 颜色选择器的主要区域由三层组成,如果您查看HSB格式,则更容易理解

B代表亮度,使用与HSL 的亮度略有不同算法。

如果将 HSB 区域视为坐标系,则饱和度x 轴(从左到右,0 到 100),亮度y 轴(从下到上,0 到 100)。

因此,右上角的位置是100, 100,左下角的位置是0, 0

要在 HTML 和 CSS 中重新创建此内容,请使用三个层:

<div class="hue">
  <div class="brightness"></div>
  <div class="saturation"></div>
</div>
Enter fullscreen mode Exit fullscreen mode
.hue {
  --h: 0;
  background-color: hsl(var(--h), 100%, 50%);
}

.saturation {
  background-image: linear-gradient(to bottom, transparent, hsl(var(--h), 0%, 0%));
}

.brightness {
  background-image: linear-gradient(to right, hsl(var(--h), 100%, 100%), transparent);
}
Enter fullscreen mode Exit fullscreen mode

层需要相对于层进行定位.saturation.brightnessabsolutehue

CSS 并不反映实际的饱和度和亮度,但像这样分层,幻觉就完成了:

饱和度亮度

尝试改变的值--h

如果您想在 JavaScript 中构建类似 Photoshop 的颜色选择器,请检测指针设备的xygetBoundingClientRect()位置,使用来获取“选择器区域”的尺寸,然后进行转换,这样您总是会得到0,0和之间的坐标100,100

再次:x等于饱和度y等于亮度

您还必须将 HSB 转换为 HSL(使用 JavaScript),因为浏览器不理解 HSB 格式。

所以...我认为基于 HSL 的颜色选择器更易于编码和使用!

感谢阅读!

文章来源:https://dev.to/madsstoumann/colors-are-math-how-they-match-and-how-to-build-a-color-picker-4ei8
PREV
创建一个有趣、快速、安全且可持续的网站
NEXT
构建最小的 AutoSuggest