Skip to content
This page has been auto-translated and may contain errors.View in English

颜色和背景

docs.scrimba.com

你想让按钮显示特定的蓝色。你从设计文件中找到颜色,粘贴 #1b2130 到样式表中,它生效了,但你完全不知道这些字符是什么意思,也不知道如何调整这个色调让它稍微浅一点。CSS 中的颜色看起来像一堆神秘代码,直到你学会了底层的几个系统。一旦你能读懂颜色并将其绘制到背景上,页面的大部分视觉特征就掌握在你手中了。

命名颜色

CSS 让你用几种不同的方式写同一个颜色。最简单的是**关键词**:浏览器已经认识的普通英文名称。

css
.tag {
  color: rebeccapurple;      /* 一个命名颜色,无需代码 */
}

大约有 140 个这样的名称,用于快速工作很方便,但对于真正的设计来说远远不够。其他方式让你能描述任何颜色。十六进制代码# 后跟六个字符,rgb() 用数量混合红、绿和蓝。它们都指向精确的颜色;关键词只是常见颜色的快捷方式。

css
.tag {
  color: #1b2130;            /* 同样的深海军蓝,用十六进制代码写法 */
}

CSS 中有四种方式写颜色,它们通过不同的系统描述相同的颜色。**关键词**如 rebeccapurple 是固定的名称。十六进制代码#1b2130 将红、绿、蓝压缩成六个字符。rgb() 函数将这三个通道设置为 0 到 255 的数字。而 hsl() 则通过色调、饱和度和亮度来描述颜色。

css
.badge {
  color: #1b2130;                 /* 十六进制:红、绿、蓝各两个字符 */
  color: rgb(27, 33, 48);         /* 同样的颜色,用红、绿、蓝数量表示 */
  color: hsl(219, 28%, 15%);      /* 同样的颜色,用色调、饱和度、亮度表示 */
}

这三行都绘制了相同的深海军蓝。当你手动选择颜色时,应该选择**hsl()**。它读起来像一个人能够理解的描述,而十六进制和 rgb 是你主要是复制粘贴的数字。

CSS 接受颜色作为关键词、十六进制代码、rgb()hsl(),前三种都寻址相同的sRGB色彩空间(屏幕几十年来一直使用的标准色彩空间),只是记号不同。十六进制是十六进制:#1b2130 是红色 1b、绿色 21、蓝色 30,每一对的值从 00ff(十进制的 0 到 255)。rgb() 用普通十进制写这三个通道。这两种都不是为了让人类推理而构建的,因为把颜色"调亮一点"意味着同时调整三个数字,没有明确的方向。

css
.badge {
  color: #1b2130;               /* 十六进制:1b 红,21 绿,30 蓝 */
  color: rgb(27 33 48);         /* 同样的通道,十进制,现代空格分隔语法 */
  color: hsl(219 28% 15%);      /* 色调 219deg,28% 饱和度,15% 亮度 */
}

优先选择 hsl():它的三个轴每个都对应一个你可以单独调整的东西。色调是色轮上从 0 到 360 的位置,饱和度是颜色的鲜艳程度,亮度是颜色的明亮程度。想要一个悬停状态稍微暗一点?降低亮度百分比,保持其他两个不变。这种单一可读的轴正是 hsl()自定义属性组合得很好的原因,你用自定义属性来构建调色板,可能保持一个色调,在一组色调中只改变亮度。

Juno命名颜色 同一个颜色可以写成关键词如 rebeccapurple、十六进制代码如 #1b2130rgb()。关键词速度快但只有大约 140 个,所以大多数真正的工作使用代码。现在不要尝试用眼睛读十六进制代码;在这个阶段复制精确值完全正常。
Juno命名颜色 关键词、十六进制、rgb()hsl() 都通过不同的系统命名相同的颜色。当你自己挑选颜色时,使用 hsl(),因为色调、饱和度和亮度是你实际能够推理的东西。十六进制和 rgb() 是用于你从设计中复制的值,而不是用手调整的。
Juno命名颜色 关键词、十六进制和 rgb() 都通过不同的记号寻址 sRGB;hsl() 将同一个颜色重新框架化为三个轴,你可以一次移动一个。这就是优先选择它的全部原因:更暗的悬停是一个数字,亮度,而不是三个协调的。当你从自定义属性构建调色板并在一个比例中改变亮度时,它就会得到回报。

透明度

有时你想要一种颜色可以部分透视,所以无论在其后面的是什么都会显示一点。这是**透明度**,你用称为 alpha 的第四个值添加它:0 是完全透视,1 是完全不透明。

css
.overlay {
  background-color: rgb(27 33 48 / 0.5);   /* 海军蓝,但半透明 */
}

末尾的 / 0.5 意味着"半透明度"。还有一个叫 opacity 的属性,它一次性淡化整个元素,包括文本:

css
.faded {
  opacity: 0.5;              /* 淡化整个元素,不只是一个颜色 */
}

区别很重要:alpha 只影响那一个颜色,而 opacity 淡化元素的一切。

通过添加**alpha**值,你可以让颜色透视,其中 0 是不可见,1 是不透明。rgb()hsl() 都在斜杠后面接受它,十六进制代码可以在末尾添加两个额外的字符。

css
.overlay {
  background-color: rgb(27 33 48 / 0.5);    /* 半透明海军蓝 */
  background-color: hsl(219 28% 15% / 0.5); /* 通过 hsl 实现同样的效果 */
  background-color: #1b213080;              /* 同样的效果:80 大约是 50% alpha */
}

alpha 和 opacity 属性之间有重要的区别。Alpha 使一个颜色部分透明,仅此而已。opacity 淡化整个元素,包括其文本、其边框和任何子元素,作为单个单位。用 alpha 淡化一个颜色;用 opacity 淡化整个元素。如果你的文本在你只是想要柔和背景时变得微弱,你到了 opacity,而你想要的是 alpha。

Alpha 是颜色上的第四个通道,从 0(完全透明)到 1(完全不透明),它属于那一个颜色值。现代 rgb()hsl() 在斜杠后接受它,十六进制接受它作为第四字节,所以 #1b213080 是海军蓝在 80/ff,大约 50%。因为 alpha 在颜色上,你可以让背景半透明,同时文本、边框和其他一切保持完全不透明。

css
.overlay {
  background-color: hsl(219 28% 15% / 0.5);  /* 只有这个填充是半透明的 */
  color: white;                              /* 文本保持完全不透明 */
}

opacity 是一个不同的工具,只是碰巧看起来相似。它设置元素作为整体的透明度,它通过将元素及其所有后代作为一个组合成页面来实现。两个结果随之而来,alpha 没有。首先,opacity 低于 1 建立一个新的堆叠上下文(重叠元素如何排序的自包含层),这可以改变什么在什么之上。其次,你不能在淡化的父级内恢复不透明的子级,因为淡化适用于完成的组。当你只想要一个填充或一个边框透视时,在那个颜色上使用 alpha,不要碰 opacity

Juno透明度 添加第四个值到颜色使其透视:0 是不可见,1 是不透明,/ 0.5 这样的东西是一半。那个 alpha 只接触一个颜色。单独的 opacity 属性淡化整个元素,包括文本,所以当你只想要更柔和的背景时选择 alpha。
Juno透明度 Alpha 是单一颜色上的透明度,在 rgb()hsl() 中写在斜杠后,或作为两个额外的十六进制字符。opacity 属性是更粗暴的版本:它一次性淡化整个元素及其子级。当你的文本意外变得微弱时,你使用了 opacity,而 alpha 是正确的选择。
Juno透明度 Alpha 在颜色上,所以半透明的填充保持不透明的文本和边框不受影响。opacity 将整个元素及其后代作为一个组合成,这就是为什么子级不能在淡化的父级内保持不透明,以及为什么它悄悄地启动了一个新的堆叠上下文。除非你确实想要整个元素一起淡化,否则选择 alpha。

背景颜色和图像

background-color 属性填充元素后面的区域,到其边框。你可以使用任何你能命名的颜色。

css
.hero {
  background-color: hsl(219 28% 15%);   /* 内容后面的纯海军蓝 */
}

你也可以用 background-image 在元素后面放一个图像,用 url(...) 指向文件:

css
.hero {
  background-image: url("mountains.jpg");
  background-size: cover;               /* 缩放图像以填充整个区域 */
}

background-size: cover 缩放图片使其完全填充盒子,裁剪任何溢出。它是你大多数时候想要的设置,这样就没有空隙。

background-color 绘制内容后面的区域,填充内补区到边框边缘。在该颜色之上,你可以用 background-imageurl(...) 叠加图像。因为它叠加在上面,背景颜色在图像下方显示任何透明部分,以及图像仍在加载时显示。

css
.hero {
  background-color: hsl(219 28% 15%);   /* 显示和首先加载 */
  background-image: url("mountains.jpg");
  background-size: cover;               /* 填充盒子,裁剪溢出 */
  background-position: center;          /* 图像中心保持在视图中 */
  background-repeat: no-repeat;         /* 一个副本,不平铺 */
}

三个属性控制图像如何放置。background-size 通常是 cover(填充盒子,裁剪溢出)或 contain(将整个图像放在内部,可能会留下间隙)。background-position 决定当图像被裁剪时视图中保留哪一部分,center 是安全的默认值。background-repeat: no-repeat 阻止小图像在盒子中平铺。

background-color 填充元素的背景区域,默认是内补区,所以颜色到达内补的外边缘并在边框处停止。background-image 在该颜色之上绘制,值得在任何照片图像下保持纯色 background-color:它是图像加载或请求失败时显示的回退,并显示透明区域,所以选择一个接近图像色调的颜色避免闪现裸露的页面。

css
.hero {
  background-color: hsl(219 28% 15%);   /* 回退和加载时填充 */
  background-image: url("mountains.jpg");
  background-size: cover;               /* cover:填充盒子,裁剪溢出 */
  background-position: center;          /* 在中心锚定裁剪 */
  background-repeat: no-repeat;
}

大小选择是真正的权衡。cover 在两个轴上缩放图像以填充盒子,并裁剪溢出的任何部分,所以没有空白但图像的一部分丢失;contain 缩放直到整个图像适配,所以没有裁剪但盒子可以显示未覆盖的条纹(background-color 填充这些)。background-positioncover 下最重要,因为它决定哪个区域在裁剪中存活:center 是安全的,但肖像可能想要 top 以在框中保留脸部。对于清晰的非照片填充,注意渐变也算 background-image,下一节会用到。

Juno背景颜色和图像background-color 填充元素后的空间,background-image: url(...) 把图片放在那里。将图像与 background-size: cover 配对,使其填充整个盒子而不留下间隙。这个组合涵盖了你早期大多数会用到的东西。
Juno背景颜色和图像 背景图像叠加在背景颜色之上,所以在图像加载期间保持颜色在下面。cover 填充盒子并裁剪溢出,contain 适配整个图像可能留下间隙,background-position 决定裁剪时哪一部分保持可见。添加 no-repeat 除非你确实想要图像平铺。
Juno背景颜色和图像 在任何照片下保持 background-color:它是加载期间的回退并显示透明区域。covercontain 是填充-裁剪对适配-可能-间隙,background-position 只在 cover 下赚得存在,它选择裁剪中幸存的东西。默认在 center 上锚定,只有当图像的特定部分必须保持在框中时才移动它。

渐变

**渐变**是从一个颜色平滑混合到另一个的过程。CSS 将其视为一种图像,所以它放在 background-image 中而不是 background-color

css
.banner {
  background-image: linear-gradient(hsl(219 28% 15%), hsl(219 40% 35%));
}

那从顶部的第一个颜色混合到底部的第二个。你可以列出超过两个颜色,也可以改变方向:

css
.banner {
  background-image: linear-gradient(to right, hsl(340 80% 55%), hsl(30 90% 60%));
  /* 从左到右混合而不是从上到下 */
}

无需图像文件;浏览器为你绘制混合。

**渐变**是一个生成的图像,这就是为什么 linear-gradient()background-image 中而不是 background-color。它的第一个参数是方向,然后是一个要混合的颜色列表。省略方向,它从上到下运行。

css
.banner {
  background-image: linear-gradient(
    to right,                    /* 方向:左边缘到右边缘 */
    hsl(340 80% 55%),            /* 起始颜色 */
    hsl(30 90% 60%)              /* 结束颜色 */
  );
}

radial-gradient() 以相同的方式工作,但从中心点向外环形混合,而不是沿直线。它是用于柔和发光或聚光灯效果的工具。

css
.spotlight {
  background-image: radial-gradient(hsl(0 0% 100%), hsl(219 28% 15%));
  /* 明亮的中心淡化到暗边 */
}

因为渐变是背景图像,它与实际图像和其他渐变在同一 background-image 属性下叠加,用逗号分隔。

渐变是生成的图像,所以它在 background-image 中并遵循与 url(...) 相同的大小和叠加规则。linear-gradient() 首先采用可选的方向(to right,或像 135deg 的角度),然后是它混合的颜色停止列表。给停止显式位置,你完全控制颜色着陆的位置,当两个停止在同一点相遇时,这将渐变变成硬条纹。

css
.banner {
  background-image: linear-gradient(
    135deg,                      /* 角度:0deg 向上,90deg 向右 */
    hsl(340 80% 55%) 0%,
    hsl(30 90% 60%) 100%
  );
}

radial-gradient() 从中心向外混合,在其停止之前采用可选的形状和大小。两者都是每种意义上的图像,所以它们在一个逗号分隔的 background-image 下叠加,较早的渐变在较晚的渐变上绘制,这就是半透明渐变如何在照片上变成色调的方式:

css
.hero {
  background-image:
    linear-gradient(hsl(219 28% 15% / 0.6), hsl(219 28% 15% / 0.6)),  /* 顶部暗色调 */
    url("mountains.jpg");                                             /* 下面的照片 */
  background-size: cover;
}

因为 hsl() 直接公开亮度,两个停止之间在相同色调但两个亮度值之间的渐变给出干净、可控的淡化,这是另一个选择 hsl 而不是十六进制有回报的地方。

Juno渐变 渐变是颜色之间的平滑混合,CSS 将其视为图像,所以它在 background-image 中。linear-gradient() 沿直线混合,默认从上到下,或添加 to right 改变方向。无需文件,浏览器自己绘制混合。
Juno渐变linear-gradient()radial-gradient() 都是生成的图像,所以它们属于 background-image。线性沿你用方向瞄准的线混合;径向从中心向外环形混合,适合发光。因为它们是图像,你可以在一个逗号分隔的 background-image 下堆叠多个。
Juno渐变 渐变是图像,所以它们采用位置,在一个 background-image 下叠加,并遵守 background-size。给颜色停止显式位置以精确淡化或硬条纹,并在 url(...) 上堆叠半透明渐变以色调调照片而不需要第二个元素。两个停止 hsl() 在相同色调但两个亮度值之间的淡化是最干净的可控类型。

适应和保持可读的颜色

一个有用的关键词是 currentColor。它代表元素的文本颜色,所以边框或图标可以自动匹配文本:

css
.chip {
  color: hsl(219 28% 15%);
  border: 2px solid currentColor;   /* 边框匹配文本颜色 */
}

稍后改变文本颜色,边框自己跟随,无需第二次编辑。

还有一件事要记住:确保文本从背景中脱颖而出。深色文本在深色背景上难以阅读,淡灰色在白色上会让眼睛疲劳。目标是两者之间亮度的明确差异。

currentColor 是一个关键词,解析为元素自己的 color 值,所以边框、轮廓和 SVG 图标可以跟踪文本颜色而不重复它。设置一次文本,与 currentColor 关联的所有东西都随之更新。

css
.chip {
  color: hsl(219 28% 15%);
  border: 2px solid currentColor;   /* 跟随 color,没有重复值 */
}

与此并行要注意的属性是**对比度**:文本及其背景之间亮度的差异。低对比度难以阅读,易用性指南为正文设置最小比率。这就是 hsl() 再次赢得地位的地方:因为亮度是它自己的轴,你可以保持色调并将文本和背景亮度推得足够远以保持可读性,而不是同时盲目猜测三个通道。

currentColor 解析为元素的计算 color,这使它成为一种轻量级方式来将边框、轮廓、方框阴影和 SVG fill 关联到文本颜色。它像任何值一样继承,所以在容器上设置 color 级联一个颜色源到每个引用 currentColor 的后代,这是从一个声明主题化组件的干净模式。

更难的约束是**对比度,前景和背景之间相对亮度差异的测量。易用性标准WCAG**(Web 内容易用性指南)为普通正文设置 4.5 比 1 的最小比率,为大型文本设置 3 比 1,低于那个的文本对许多人来说难以阅读,不仅是那些视力较弱的人。hsl() 帮助你达到它:亮度是一个单独的轴,所以你可以保持色调和饱和度,只移动两个亮度值直到对通过,而不是盲目推动六个通道。它是帮助推理,不是保证,因为相等亮度颜色仍然可能未通过真实亮度计算,所以用检查器验证最终比率。

这个级别还有两件事值得了解。background 速记一次设置许多背景属性,它的一个规则是 background-sizebackground-position 后,用斜杠分隔:background: url("bg.jpg") center / cover no-repeat。CSS 现在有超过 hsl() 的颜色函数,如 oklch(),到达在支持更宽色域(屏幕能显示的颜色范围)的显示上 sRGB 外的颜色。你现在还不需要它们,但了解更新函数存在意味着当设计系统要求比 sRGB 能表达的更鲜艳的颜色时,你会认出它们。将其与可读的排版配对,文本向每个读者传达其意义。

Juno适应和保持可读的颜色currentColor 是复制元素文本颜色的关键词,所以边框可以匹配文本,如果你稍后改变它就跟随它。除此之外,保持文本可读:确保它明显比其后的亮或暗。低对比度是页面难以阅读的最常见原因。
Juno适应和保持可读的颜色currentColor 将边框、轮廓和图标关联到文本颜色,所以你在一个地方设置它。注意对比度,文本和背景之间的亮度间隙,因为易用性规则为正文设置最小值。在 hsl() 中拉开亮度值是保持那个间隙足够宽的可靠方法。
Juno适应和保持可读的颜色currentColor 继承,所以容器上的一个 color 主题化每个引用它的后代。WCAG 想要正文 4.5 比 1,hsl() 让你只移动亮度以达到它,尽管相等亮度仍可能未通过真实亮度检查,所以用工具验证。记住 background 速记将大小放在位置后,用斜杠,以及像 oklch() 这样的更新函数存在,当设计需要它们时用于更宽色域。