You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
8.3 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# CSS渲染CSS是如何绘制颜色的
你好我是winter今天我们来学习一下CSS的渲染相关的属性。
我们在布局篇讲到CSS的一些属性决定了盒的位置那么今天我讲到的属性就决定了盒如何被渲染。
按照惯例,还是先从简单得讲起,首先我们来讲讲颜色。
## 颜色的原理
首先我们来讲讲颜色,最常见的颜色相关的属性就是 `color``background-color`
这两个属性没什么好讲的,它们分别表示文字颜色和背景颜色,我们这里重点讲讲颜色值。
### RGB颜色
我们在计算机中最常见的颜色表示法是RGB颜色**它符合光谱三原色理论:红、绿、蓝三种颜色的光可以构成所有的颜色。**
![](https://static001.geekbang.org/resource/image/7f/a1/7f5bf39cbe44e36758683a674f9fcfa1.png)
为什么是这三种颜色呢?这跟人类的视神经系统相关,人类的视觉神经分别有对红、绿、蓝三种颜色敏感的类型。
顺便提一下人类对红色的感觉最为敏感所以危险信号提示一般会选择红色而红绿色盲的人就是红和绿两种神经缺失一种。其它的动物视觉跟人可能不太一样比如皮皮虾拥有16种视锥细胞所以我猜它们看到的世界一定特别精彩。
现代计算机中多用 0 - 255 的数字表示每一种颜色,这正好占据了一个字节,每一个颜色就占据三个字节。
这个数字远远超过了人体的分辨能力因此上世纪90年代刚推出这样的颜色系统的时候它被称作真彩色。早年间还有更节约空间但是精度更低的16色、256色、8位色和16位色表示法。
红绿蓝三种颜色的光混合起来就是白光没有光就是黑暗所以在RGB表示法中三色数值最大表示白色三色数值为0表示黑色。
### CMYK颜色
如果你上过小学美术课,应该听过“红黄蓝”三原色的说法,这好像跟我们说的不太一样。实际上是这样的,颜料显示颜色的原理是它吸收了所有别的颜色的光,只反射一种颜色,所以颜料三原色其实是红、绿、蓝的补色,也就是:品红、黄、青。因为它们跟红、黄、蓝相近,所以有了这样的说法。
![](https://static001.geekbang.org/resource/image/15/1b/15fefe9f80ec8e1f7bd9ecd223feb61b.png)
在印刷行业使用的就是这样的三原色品红、黄、青来调配油墨这种颜色的表示法叫做CMYK它用一个四元组来表示颜色。
你一定会好奇,为什么它比三原色多了一种,其实答案并不复杂,在印刷行业中,黑色颜料价格最低,而品红、黄、青颜料价格较贵,如果要用三原色调配黑色,经济上是不划算的,所以印刷时会单独指定黑色。
对CMYK颜色表示法来说同一种颜色会有多种表示方案但是我们参考印刷行业的习惯会尽量优先使用黑色。
### HSL颜色
好了讲了这么多其实还没有涉及今天的主角HSL颜色。接下来我们就讲一讲。
我们刚才讲的颜色是从人类的视觉原理建模,应该说是十分科学了。但是,人类对颜色的认识却并非来自自己的神经系统,当我们把阳光散射,可以得到七色光:红橙黄绿蓝靛紫,实际上,阳光接近白光,它包含了各种颜色的光,它散射之后,应该是个基本连续的。这说明对人的感知来说,颜色远远大于红、绿、蓝。
因此HSL这样的颜色模型被设计出来了它用一个值来表示人类认知中的颜色我们用专业的术语叫做色相H。加上颜色的纯度S和明度L就构成了一种颜色的表示。
![](https://static001.geekbang.org/resource/image/a3/ce/a3016a6ff178870d6dba23f807b0dfce.png)
在这里我需要特别推荐HSL颜色因为它是一种语义化的颜色。当我们对一张图片改变色相时人们感知到的是“图片的颜色变了”。这里先容我卖个关子具体的例子待我们讲完了渐变再看。
### 其它颜色
接下来我们讲一讲RGBARGBA是代表Red红色、Green绿色、Blue蓝色和Alpha的色彩空间。RGBA颜色被用来表示带透明度的颜色实际上Alpha通道类似一种颜色值的保留字。在CSS中Alpha通道被用于透明度所以我们的颜色表示被称作 RGBA而不是RGBOOpacity
为了方便使用CSS还规定了名称型的颜色它内置了大量140种的颜色名称。不过这里我要挑出两个颜色来讲一讲gold和银silver
如果你使用过这两个颜色你会发现gold和银silver的视觉表现跟我们想象中的金色和银色相差甚远。与其被叫做金色和银色它们看起来更像是难看的暗黄色和浅灰色。
为什么会这样呢?在人类天然的色彩认知中,实际上混杂了很多其它因素,金色和银色不仅仅是一种颜色,它还意味着一定的镜面反光程度,在同样的光照条件下,金属会呈现出更亮的色彩,这并非是用一个色值可以描述的,这就引出了我们接下来要讲的渐变。
## 渐变
在CSS中`background-image`这样的属性可以设为渐变。CSS中支持两种渐变一种是线性渐变一种是放射性渐变我们先了解一下它们的基本用法
线性渐变的写法是:
```
linear-gradient(direction, color-stop1, color-stop2, ...);
```
这里的direction可以是方向也可以是具体的角度。例如
* to bottom
* to top
* to left
* to right
* to bottom left
* to bottom right
* to top left
* to top right
* 120deg
* 3.14rad
以上这些都是合理的方向取值。
color-stop是一个颜色和一个区段例如
* rgba(255,0,0,0)
* orange
* yellow 10%
* green 20%
* lime 28px
我们组合一下,产生一个“真正的金色”的背景:
```HTML
<style>
#grad1 {
height: 200px;
background: linear-gradient(45deg, gold 10%, yellow 50%, gold 90%);
}
</style>
<div id="grad1"></div>
```
放射性渐变需要一个中心点和若干个颜色:
```
radial-gradient(shape size at position, start-color, ..., last-color);
```
当我们应用的每一种颜色都是HSL颜色时就产生了一些非常有趣的效果比如我们可以通过变量来调整一个按钮的风格
```HTML
<style>
.button {
display: inline-block;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: 14px/100% Arial, Helvetica, sans-serif;
padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0,0,0,.3);
border-radius: .5em;
box-shadow: 0 1px 2px rgba(0,0,0,.2);
color: white;
border: solid 1px ;
}
</style>
<div class="button orange">123</div>
```
```JavaScript
var btn = document.querySelector(".button");
var h = 25;
setInterval(function(){
h ++;
h = h % 360;
btn.style.borderColor=`hsl(${h}, 95%, 45%)`
btn.style.background=`linear-gradient(to bottom, hsl(${h},95%,54.1%), hsl(${h},95%,84.1%))`
},100);
```
## 形状
CSS中的很多属性还会产生形状比如我们常见的属性
* border
* box-shadow
* border-radius
这些产生形状的属性非常有趣我们也能看到很多利用它们来产生的CSS黑魔法。然而这里我有一个相反的建议我们仅仅把它们用于基本的用途把border用于边框、把阴影用于阴影把圆角用于圆角所有其它的场景都有一个更好的替代品datauri+svg。
## 总结
今天我们介绍了CSS中渲染相关的属性颜色和形状。
我们重点介绍了CSS的颜色系统从颜色基本原理讲解了RGB颜色、CMYK颜色和HSV颜色我们还讲解了Alpha通道。
接下来我们又讲了颜色的一个重要应用:渐变,我们可以把渐变看作是一个更复杂的颜色,它非常实用,能够用渐变绘制很多的图像。
最后我们讲解了形状相关的属性以及SVG应用的一个小技巧。
### 思考题
![](https://static001.geekbang.org/resource/image/0f/ac/0f6f4cc6d564df9986e0108cb8a427ac.jpg)
折衷鹦鹉是一种可爱的鸟类但是雄性折衷鹦鹉居然是跟雌性颜色不一样你能用JavaScript和canvas把这只雄性折衷鹦鹉变成跟雌性一样可爱的红色吗