CSS3之色彩与渐变

CSS3之色彩

1. RGB模式

在物理学中有一个重要的光学特性:任何一种颜色都可以使用红色、绿色和蓝色三种颜色混合出来,这三个颜色也被称为光学三原色。

RGB颜色模式正是基于这个原理。它使用三个0~255之间的数字来表示在混合时红、绿、蓝三种原色的数量,0表示混入的数量为0, 255表示混入纯色。比如rgb(255, 255, 255)表示红、绿、蓝三种颜色都使用纯色,混合的结果就是白色;再比如,rgb(255, 255, 0)表示红、绿使用纯色,蓝色的数量为0,混合的结果是紫色。如果以任意的比例混合,比如rgb(252,105,203),表示混入红色的数量为252,绿色为105,蓝色为203,它会产生下面的颜色:
CSS3之色彩与渐变_第1张图片
每种原色的数量不同,所产生的颜色理论上都是不同的。而RGB模式下,每个原色的数量为0~255共计256个取值,那么三种原色总共可以混合出256 * 256 * 256 = 16777216种颜色,这超过1677万种颜色几乎覆盖了人眼所能识别的所有颜色。

不过这个0~255的数值并没有太大的实际意义,它只是一种用来衡量颜色数量的相对标准。RGB颜色标准中只是人为设定纯色的颜色数量是255。例如某个颜色中,红色的值为85,那就表示构成该颜色的红色的数量为纯红色的三分之一。

既然只是一个参考值,那为什么要把纯色的数量定为255呢?如果把这个值定的更大,那三种原色所能组合出的颜色数量不是更多?其实确实是这样的。例如把纯色的值设置为1000,那么RGB模式将能表示1000 * 1000 * 1000 = 10亿种颜色。那为什么设计RGB模式的专家们偏偏选择了255这个值呢?我么来看一张图片:
CSS3之色彩与渐变_第2张图片
假设这张图片从理论上来说是连续的(此时请忘记屏幕是由像素构成的),那么它总共包含了多少种颜色呢?除了几种纯色外,它还包含了无数的中间色,所以我们可以认为它包含了无数种颜色。但屏幕却是由一个个像素构成的,每个像素只能显示一种颜色,最终聚合在一起,才能显示这张图片。假设这张图片由十万个像素构成,那要显示这张图片,就必须明确指定每个像素的颜色。显然,此时该图片所包含的颜色数量不可能超过十万种。也就是说,颜色空间中可能无限多的颜色,为了显示在屏幕上,必须分割成有限多的颜色。

我们知道,颜色的变化是连续的。在没有任何颜色的情况下,物体显示为黑色,在三种原色都使用纯色的情况下,物体显示为白色。在白色和黑色之间存在着无数种连续的中间色。在这个连续的范围内,我们需要每隔一定的距离取一个颜色来代表与其相近范围的颜色(就如同坐标轴上0到100之间理论上有无数个点,但是当你每隔0.1取一个值时,你就只能得到约1000个点,5.11这个值此时只能就近用5.1来表示),那么每隔多远取一个值可以让人眼感知到所有的颜色呢?

这个问题需要一定的权衡。因为颜色值需要使用计算机的二进制表示,所以它要便于计算机运算。科学家们选择使用一个字节(即8个二进制的0或1,如1111 1111转换成十进制正好是255,而之所以选择8位为一个字节,也是因为8 = 2^3,在计算机中,2的乘方数都是便于计算的数字)来表示某种原色的数量。由于字节是计算机描述存储空间的基本单位(比如我们常说的1KB,指的就是1024个字节,它是以单个字节为基本单位的),所以它非常便于计算机存储和运算。另外,选择一个字节来表示一种原色的数量,RGB空间就将整个的颜色空间切割成16777216个独立的颜色,这个数量足以使人眼感知到颜色空间的所有颜色。

RGB模式表示颜色时通常有四种写法:

  1. 英文名称。如white,red等,这些颜色名内置于浏览器,数量有限。
  2. rgb(255, 255, 255)。用三个十进制数来表示三种原色的数量。
  3. #ffffff。用6个十六进制数表示,这里的字母也可以使用大写,即#FFFFFF。每个十六进制数可以转化为4个二进制数,因此 ff 转化为十进制就是255,所以这里每两个十六进制数表示一种原色的数量。
  4. #fff。上述格式的简写,如果六个十六进制数两两相等,就可以省略一个,如#dd8833可以简写为#d83。

2. RGBA模式

CSS3在RGB模式的基础上新增了另一种颜色模式:RGBA模式。该模式在之前三原色的基础上新增了透明度,用一个0~1的alpha值来表示(在PS中使用alpha通道来处理透明度,这里的alpha值与之类似,A就是alpha的首字母)。如果要使用RGBA模式,你可以这样写:

color: rgba(252,105,203, 0.4);

在使用RGBA模式之前,如果需要创建半透明的效果,你只能使用IE浏览器的滤镜。但随着RGBA模式逐渐得到广泛支持,我们可以抛弃这个仅在IE中可以使用的技巧。在仅使用RGB模式时,内层div将位于外层div上方,并遮住下方的区域,如下:
CSS3之色彩与渐变_第3张图片
但是如果给内部的div设置了一定的透明度,你就可以看到下方的背景色:
CSS3之色彩与渐变_第4张图片
粉色的区域已经具有了80%的透明度,因此你可以透过它看到底下的蓝色背景。如果你给字体颜色设置透明度,它同样可以出现半透明效果。

RGBA模式使用起来比较简单,它为设计师提供了更多设计网页的能力,这里不再详述。

3. HSL模式

与RGB模式的理念不同,HSL模式不基于红、绿、蓝三色的混合来表示一个颜色(从最底层的硬件实现来说依然是三原色的混合,但是该颜色模式的设计者希望你换个角度看待颜色的构成,如何转化成三种原色的数量由模式设计者来考虑),而是基于色相、饱和度和亮度三个参数。HSL模式下颜色的写法为:

hsl(0, 50%, 50%);

三个参数分别表示色相、饱和度和亮度。

三者将颜色空间表示为一个圆柱,如下图:
CSS3之色彩与渐变_第5张图片
1. 色相:
色相决定了一个颜色的基础颜色,它是一个360度的圆,各个角度对应的颜色如下:
CSS3之色彩与渐变_第6张图片
如果某个颜色的色相值是0度,那么它的基本色就是红色;如果是60度,那么就是黄色;而如果是介于两者之间的值,那么该颜色将介于红色和黄色之间。具体度数与颜色的对应关系参考上图。该色轮的产生与RGB模式基于同样的原理,但是它没有明暗色调的变化。

饱和度:
如果说色相决定了颜色的基本值,那么饱和度就是用来描述该色彩的纯度的。它是一个0~100%之间的值。假如色相度数为0度,饱和度为100%,那么它就是纯红色,而如果饱和度为50%,那么它就会表现为偏灰的红色。比如下面是饱和度100%、50%和10%的红色:
CSS3之色彩与渐变_第7张图片
简单来说,饱和度决定了颜色的鲜艳程度。

亮度:
最后亮度表示该颜色的明亮程度。亮度值越大,该颜色就会越发白,亮度值越小,该颜色就会越发黑。亮度也是一个介于0~100%之间的值,亮度为0时,该颜色将表现为黑色(就如同在一个完全黑暗的房间内,你看到的任何颜色的物体都是黑色的);亮度为100%时,该颜色将表现为白色(比如红色的物体在强烈的太阳光下,看起来会是一种发白的红色,到达极限时就呈现为白色)。下面是亮度100%、70%、50%、30%和0的红色:
CSS3之色彩与渐变_第8张图片
亮度表现的是不同亮度的光照射在物体上时,它所呈现出的颜色。

从总的颜色数量上来看,HSL模式所能表示的颜色少于RGB模式,但它却是不少设计师更加偏爱的一种颜色模式。这是因为hsl颜色模式更加符合人类对颜色的认知。虽然红、绿、蓝三色的组合是非常科学的物理学方法,但是你很难想象到rgb(100, 100, 50)表示什么颜色,它是下面的颜色:
CSS3之色彩与渐变_第9张图片
RGB模式在很多情况下最终展现的颜色都是不易想象的,而且要记忆如此多的颜色也不太可能,所以大多数情况下设计师都需要借助一个调色板进行网页设计。而hsl模式的使用就更加直接了,你只需要简单记忆几个主要的色相角度所对应的颜色(如0度、60度、120度…),饱和度和亮度都可以凭借经验推测出来(比如你想要暗一点的颜色,就降低亮度值,想要浅一点的颜色,就降低饱和度。在PS的使用中,这非常便捷。而如果使用RGB模式,你可能很难知道该怎么修改RGB三个参数)。

4. HSLA模式

很简单,只是在上述颜色模式下新增了透明度,它的值也是一个0~1之间的小数,使用方法类似于RGBA,你可以像下面这样书写一个HSLA模式的颜色:

hsla(0, 50%, 50%, 0.5);

它将是一个半透明的红色。这里不再详述。

实际上在其他领域还有一些颜色模式,比如HSV模式(与HSL模式类似,只是最后一个参数是明度,而不是亮度)、CYMK模式(一种常见的印刷体颜色模式)等,这里不再一一详述。

CSS3之渐变

CSS3的渐变分为两种:线性渐变和径向渐变。两种渐变最简单的效果如下图:
CSS3之色彩与渐变_第10张图片
线性渐变是沿着一条直线产生渐变,该直线可以沿任意方向。径向渐变产生的是放射性的渐变效果,渐变中心点可以放置在任意位置。下面我们来详细看一下两种渐变。

1. 线性渐变

线性渐变,顾名思义,就是沿着直线产生的渐变效果。比如上面第一个图就是沿着下面的直线产生的渐变:
CSS3之色彩与渐变_第11张图片
代码如下:

background-image: linear-gradient(to right, red , yellow);

该语句表示,该div的背景使用线性渐变(linear-gradient),方向是向右(to right),开始位置的颜色是红色(red),结束的颜色是黄色(yellow),这样浏览器就会按照图中的样式绘制出从左到右,从红色到黄色的线性渐变。

在线性渐变中,垂直于渐变方向的任意直线上的颜色都是相同的。以上面的例子来说,渐变方向为从左向右,那么在任意一条竖直方向的直线上,像素点的颜色必定是相同的,这是线性渐变的基本特征。

线性渐变并不局限于两种颜色的渐变。你可以使用更多的颜色来产生渐变,如:

background-image: linear-gradient(to bottom right, red, yellow, blue, purple);

CSS3之色彩与渐变_第12张图片
这里我们创建了一个从左上角到右下角的渐变(to bottom right,右下角),总共使用了四种颜色:红色、黄色、蓝色、紫色作为色标(在PS中称为color stop),于是产生了上面更加多彩的渐变色。

需要注意的是,线性渐变的方向为to bottom right并不意味着它是沿着div的对角线产生的渐变。它只代表该渐变的方向为右下角45度,与需要绘制该渐变的区域形状无关。所以你可以看到,色标的轴线并不垂直于div的对角线,而是沿右上角45度。线性渐变的角度可以是任意角度,但是只有left(左)、right(右)、top(上)、bottom(下)、left bottom(左下)、left top(左上)、right top(右上)、right bottom(右下)这八个方向可以使用关键字,其他的角度需要使用确切的角度来表示:
CSS3之色彩与渐变_第13张图片
比如渐变是从左向右的,那么也可以写成linear-gradient(90deg, red, yellow),它等价于写成to right。假如你希望上述div的渐变是沿着对角线的,那么你需要通过手动计算对角线的角度来实现,比如上述渐变把角度设置为约130度时是垂直于对角线的(未经过严格计算,仅供参考):

 background-image: linear-gradient(130deg, red , yellow, blue, purple);

CSS3之色彩与渐变_第14张图片
此外,各个色标的位置并不一定是等距的。在直接书写多个色标时,色标的距离默认是相同的,浏览器会自动计算各个色标的位置,但是你也可以不这样做。比如:

background-image: linear-gradient(to right, red 0%, yellow 40%, blue 60%, purple 100%);

CSS3之色彩与渐变_第15张图片
可以看到,黄色和蓝色的色标明显偏向了中间,这样你就可以灵活地产生各种更复杂的渐变效果。

此外,渐变还可以配合透明度,产生渐隐效果:
CSS3之色彩与渐变_第16张图片
而它只需要这样一行样式声明:

background-image: linear-gradient(to right, rgba(255,0,0,0), rgba(255,0,0,1));

此外,如果你希望产生重复渐变,那么色标两端的位置也不一定是0%和100%。比如下面的效果:
CSS3之色彩与渐变_第17张图片
它使用的是下面的样式声明:

background-image: repeating-linear-gradient(to right, red, yellow 12.5%, green 25%); 

注意,这里使用的不是linear-gradient,而是repeating-linear-gradient,表示要产生重复渐变。如果使用linear-gradient,这里渲染到25%的位置就会结束,后面的部分将使用最后一个色标的值来填充。如果开始位置不是0%,那么开始区域将使用第一个色标的颜色来填充。

2. 径向渐变

所谓的径向渐变,就是从一个中心点向外部产生的放射性的渐变。在默认情况下,径向渐变的中心点位于容器的中心位置,形状是椭圆形,渐变的大小是到容器的最远角落的位置,如图:
CSS3之色彩与渐变_第18张图片
它的样式声明为:

background-image: radial-gradient(red, yellow, green);

与线性渐变一样,径向渐变的色标也可以不均匀分布,如:
CSS3之色彩与渐变_第19张图片
书写样式声明时,只需要为每个色标指定位置即可:

background-image: radial-gradient(red 5%, yellow 25%, green 60%);

此外你可以指定渐变的形状。如果容器的形状不是标准的正方形,那么渐变的默认形状就是椭圆,但是你可以强制产生圆形的渐变,只需要把样式的第一个参数写成circle即可:

background-image: radial-gradient(circle, red, yellow, green);

CSS3之色彩与渐变_第20张图片
浏览器此时将以较长的方向为基准绘制圆形渐变,较窄的方向上直接裁切掉即可。

此外你还可以修改中心点的位置。假如我希望在左上角用渐变绘制出一个“太阳”,就可以将放射中心置于左上角:

background: -webkit-radial-gradient(30px 30px, closest-side, red, yellow, black);

CSS3之色彩与渐变_第21张图片
注意,在修改中心点位置时,经过实际测试,在谷歌浏览器中仍然需要-webkit-前缀才能生效。如果实际中存在这样的需求,一定要根据目标用户使用的浏览器添加对应的前缀,保证浏览器兼容。

我们看到上面的代码中除了第一个参数中心点位置外,还传了第二个参数,它表示渐变的辐射范围。它总共有四个标准值:

  1. closest-side。最近的边,比如上面的例子中,左侧和上侧是最近的边,浏览器参照该边的位置来绘制径向渐变,其余的区域全部用第三种颜色:黑色(也就是传入的最后一个参数:black)来填充了。
  2. farthest-side。最远的边。此时浏览器以最远的边为基准来绘制渐变,超出绘制区域的位置将直接裁掉。如图:
    CSS3之色彩与渐变_第22张图片
  3. closest-corner。最近的角。显然,这里左上角是最近的角,浏览器会以它为基准来绘制渐变,其余区域用黑色覆盖:
    CSS3之色彩与渐变_第23张图片
    与closest-side相比,这里黄色的区域更贴近两侧的边,因为它的放射半径的外围在左上角,而不是左侧边。
  4. farthest-corner。最远的角。此时是右下角。如图:
    CSS3之色彩与渐变_第24张图片
    同样的,它比farthest-side更偏向于两侧边。

除了这四种标准值,还有两种可选值:contain和cover。contain的效果相当于closest-side,而cover的效果相当于farthest-corner,这里不再详述。

可能大家对上面四种值的行为不是很好理解,我们再进一步解释一下。

参考线性渐变的特点:垂直于渐变方向的任意直线上的颜色都是相同的。在径向渐变中同样存在着类似的特性。假设渐变是圆形渐变,如图:
CSS3之色彩与渐变_第25张图片
那么从圆心向外,我们可以绘制出无数个同心圆,在径向渐变中,这每个同心圆上的点的颜色必定是相同的。

所以,请忘记你用于显示渐变的容器的形状,径向渐变绘制的只是这无数个同心圆。那么这些同心圆绘制到什么位置算结束呢?它应该由半径最大的那个同心圆决定。所以最大的那个同心圆的半径就决定了渐变的范围。如果你设置渐变范围为closest-side,就表示最大的同心圆的半径为圆心到最近的边的距离,浏览器会在这个范围内均匀地绘制同心圆,各个色标将在圆的半径上均匀分布。该区域绘制完毕后,浏览器会使用最后一个色标(如图所示的绿色)来填充剩余的区域,这样一个径向渐变就绘制完成了。比如上面的例子,实际上浏览器试图在绘制这样一个径向渐变:
CSS3之色彩与渐变_第26张图片
超出div的区域被浏览器直接裁掉了。如果设置的参数为closest-side,那么这个原只会绘制到与最近的边相切,其余区域使用最后一种颜色填充。

同理,farthest-side表示最大的同心圆的半径为圆心到最远的边的距离。在绘制所有同心圆的过程中遵循一个原则:超出绘制区域的裁掉,没有绘制的区域使用最后一个色标填充。closest-corner和farthest-cormer也是这个原理。

如果所绘制的不是圆,那么浏览器所绘制的就不是同心圆了,而是一个个“同心椭圆”(不确定是否有这个术语,但它与同心圆同理)。当最外部的那个椭圆与指定的边或角相交时,渐变绘制就结束了,其余的区域将用最后一个色标填充,超出绘制区域的将被裁掉。注意,绘制椭圆时,每个同心的椭圆都保持长轴与短轴的比例等于容器宽和高的比例,因此每个同心椭圆的形状都是一致的。此时浏览器相当于在绘制下面的椭圆,然后裁掉了超出div的区域。
CSS3之色彩与渐变_第27张图片

与线性渐变类似,径向渐变也可以绘制重复渐变:
CSS3之色彩与渐变_第28张图片
样式声明为:

background-image: repeating-radial-gradient(red, yellow 10%, green 15%);

此时使用repeating-radial-gradient来表示这是一个需要重复的径向渐变。

除了这些典型的用法,你可以还可以使用渐变创造一些特殊的效果:
CSS3之色彩与渐变_第29张图片
我们仿佛从左下角裁掉了四分之一的椭圆,产生了右上角的特殊形状,它只需要下面一行样式即可:

background-image: -webkit-radial-gradient(bottom left, #fff 0%, #fff 60%, green 60%, green 100%);

注意,这里我们为谷歌浏览器加了-webkit-前缀,如果需要在其他浏览器实现,需要额外写带其他前缀的样式。

这里还有使用渐变实现的更加不可思议的效果:
CSS3之色彩与渐变_第30张图片
这仅仅是一个普通的div,没有使用任何图片,只是使用渐变在两侧“裁切”出了邮票效果。它的代码如下:

<div id="grad2"></div>

<style>
#grad2 {
    height: 100px;
    width: 400px;
    margin-left: 100px;
    float: left;
    background-image: 
    radial-gradient(
      circle at 1px 8px, 
      transparent 6px, 
      #ff9e6d 6px, 
      #ff9e6d 0px), 
    radial-gradient(
      circle at 199px 8px, 
      transparent 6px, 
      #ff9e6d 6px, 
      #ff9e6d 0px);
    background-size: 200px 18px;
    background-position: 0 0, 200px 0;
    background-repeat-x: no-repeat;
}
</style>

这里在同一个div内使用了两个径向渐变,他们使用逗号隔开,然后分别从左右两侧,沿着边线绘制小的透明圆形(模拟被裁掉的效果)。然后借助background参数来控制这两个渐变的位置和大小,使两者分别作用于div的左半部分和右半部分。绘制出的透明圆形默认会重复,这时需要设置background-repeat-x: no-repeat来阻止水平方向上的重复,仅保留竖直方向上的重复,于是就产生了上面的锯齿效果。

使用渐变来实现上面的效果,可以节约一次http请求(少下载一张图片),并且浏览器绘制渐变的速度要快于显示一张图片。如果一个网页中可以借助渐变实现的效果全部使用渐变实现,那么网页性能的提升或将超出你的想象。

总结

CSS最令人着迷的地方就在于,你永远不知道它究竟可以实现多少不可思议的网页效果,只有放开自己的想象力,才能充分发挥CSS的强大威力。本文所展示的只是色彩和渐变的冰山一角,如果感兴趣,建议参考LEA VEROU著的CSS揭秘(原名CSS secret)一书,或许会对CSS有一个全新的认识。

你可能感兴趣的:(h5+css3)