11.3 CSS 渐变(gradients)

颜色渐变效果

当我们讨论CSS渐变时,准确讲是颜色的渐变

渐变色彩实际上不是颜色(color),而是图像(image)对象,通常用来作为元素背景。

这个特殊图像没有内在的尺寸和比例,它具体的大小将匹配其关联的HTML元素。

CSS中有两种类型的渐变:

  • 线性(linear):颜色在直线方向从一个点到另一个点的变化。
  • 径向(radials):颜色从圆心到圆周全方向的变化。

线性渐变(linear-gradient)

线性渐变的最新语法注1如下,看起来有点复杂:

linear-gradient( 
  [ <angle> | to <side-or-corner> ,]? <color-stop> [, <color-stop>]+ )
  \---------------------------------/ \----------------------------/
              渐变轴线的定义                 颜色停止点的定义  

<side-or-corner> = [left | right] || [top | bottom]
<color-stop> = <color> [ <percentage> | <length> ]?

要理解线性渐变的语法,首先要了解渐变轴线(gradient line)的概念。

线性渐变由渐变轴线来定义的,轴线方向上的每个点颜色都不同,而轴线垂直线上的每个点颜色都相同。而渐变轴线由关联元素的中心点以及一个角度来定义。渐变轴线的定义是可选的,默认情况是一条从上到下的垂直线。

渐变颜色由一系列点来定义,如起点、终点和可选的中间点,也就是颜色停止点(color-stop point)。

起始点是渐变线颜色开始的点。它被定义为在渐变轴线和一条经由同象限的元素盒子顶角垂直线之间的交点。

终点的定义可以被简单视为是起点对于元素盒子中心点的对称映射点。

理解了这些概念,我们再来解释下具体的 linear-gradient 语法:

  • <side-or-corner> 代表渐变轴线的起点位置,由两个关键词组成,第一个指示水平方向的边(左或右),第二个指示垂直方向的边(上或下),顺序其实无关紧要,而且都是可选的。
  • <angle> 代表渐变角度,从to top开始按顺时针方向旋转。
  • <color-stop> 代表渐变颜色停止点,由一个颜色值加上可选的停止位置组成,停止位置使用轴线方向上的百分比或像素长度来表示。

线性渐变特性从2008年苹果公司提议开始,到目前最新的版本(Level 3),经历过多次变化,目前网上能查到的中文技术博客内容都或多或少有些过时。 要了解详尽信息,读者可以参考阅读W3C规范线性渐变部分或者Mozilla CSS属性详解

这里需要提醒的是:关于deg语法,有过一些争议。尽管最新的规范定义了deg遵循时钟方向,0度代表to top。但目前浏览器对于带前缀的gradient定义, 还是遵循之前苹果提出的标准建议,使用了极地坐标系:to east,也就是屏幕上从左向右的方向。你可以用这个CSS3渐变生成器工具自己测试下。

不过除却这些分歧外,渐变特性的基本理念不外是要定义:

  • What:需要什么颜色。
  • Where:这些颜色出现在渐变轴线的哪个位置(起点、中间、终点等)。
  • Which:渐变将发生在哪个方向。

我们看下具体的实例:

div{ background-image: linear-gradient(red, blue);}
<div>一个简单的文本背景色垂直渐变</div>
一个简单的文本背景色垂直渐变

上述是最简单的例子,渐变轴线以及起点、终点都是使用的默认值:

  • 渐变方向垂直的,从上(top)下(bottom)
  • 起点为元素盒子矩形上边沿的中间点,也就是第一个颜色点应用的位置
  • 终点为元素盒子矩形下边沿的中间点,也就是第二个颜色点应用的位置

改变渐变方向

如果默认渐变方向不合适,你可以通过下面方法中的任意一种来改变:

  • 使用关键词 to left top 来定义渐变目的地
  • 定义一个具体的角度(angle) ,如 45 deg

方向的设置必须在颜色之前:

div{ background-image: linear-gradient(to bottom right, yellow, purple); width: 200px;}
<div>从左上角到右下角的对角线渐变</div>
从左上角到右下角的对角线渐变

如果我们要设置更为具体的渐变角度,我们可以使用deg来定义:

  • 0deg 等同于to top,从下到上。
  • 20deg 20度倾斜,表示从to top开始沿顺时针方向旋转20度。
  • 90deg 等同于to right,下午3点的位置,从左到右。
  • 180deg 默认值,等同于to bottom,从上到下。
div{ background-image: linear-gradient(20deg, green, blue); width: 150px;}
<div>带20度倾斜的对角线渐变</div>
带20度倾斜的对角线渐变

我们用一张图片来解释上面的代码,一目了然:

添加更多的颜色

你可以添加任意多的颜色,它们将被均匀分配在渐变轴线上:

  • 2 个颜色: 0% 和 100%
  • 3 个颜色: 0%, 50% 和 100%
  • 4 个颜色: 0%, 33%, 67% 和 100%
<div>A rainbow made from a gradient</div>
div {
  background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
}
颜色沿渐变轴线平均分配的彩虹渐变线

设置具体的颜色停止点

如果我们不想上述颜色定义按渐变轴线平均分配,我们可以在颜色停止点中添加具体的颜色停止位置,这样的一个颜色停止点就由两部分组成:颜色+位置。位置的单位可以使用百分比 % 或者像素 px

径向渐变(radial-gradient)

线性渐变是单条轴线方向上的颜色渐变,而径向渐变则在所有方向上延伸出去。语法和线性渐变类似,都有颜色停止点。不过径向渐变不需要指定方向,而是要指定:

  • 一个形状(shape):圆形或椭圆形
  • 一个起点:圆形或椭圆形的中心点
  • 一个终点:圆形或椭圆形的边界

标准语法如下:

radial-gradient(   [ circle || <length> ] [ at <position> ]? ,
                 | [ ellipse || [<length> | <percentage> ]{2}] [ at <position> ]? ,
                 | [ [ circle | ellipse ] || <extent-keyword> ] [ at <position> ]? ,
                 | at <position> ,
                 <color-stop> [ , <color-stop> ]+ )
<extent-keyword> = closest-corner | closest-side | farthest-corner | farthest-side
<color-stop> = <color> [ <percentage> | <length> ]?
div{ background-image: radial-gradient(red, yellow); padding: 1rem; width: 300px;}
<div>This looks like the sun, doesn't it?</div>
This looks like the sun, doesn't it?

缺省情况下:

  • 渐变形状是椭圆(ellipse)
  • 第一个颜色点在圆心
  • 最后一个颜色点在最远的那个角(farthest corner)

起点

起点的用法和背景位置类似。位置前面多了一个 at 关键词。

div{ background-image: radial-gradient(at top right, black, lightgrey); padding: 1rem; width: 300px;}
<div>A gloomy day.</div>
A gloomy day.

终点

默认情况下,渐变形状将在最远角(farthest corner)结束。我们也可以选择下面这些值:

  • closest-side:最近的那条边
  • closest-corner:最近的那个角
  • farthest-side:最远的那条边
  • farthest-corner:最远的那个角

上面的角或边都是指的关联元素盒子矩形的边角。选择side还是corner,视觉差别不大。选择终点的远近,对于长椭圆形状,会有较大的差别。

div{ background-image: radial-gradient(closest-corner at 20px 20px, green, blue); padding: 1rem; width: 300px;}
div:hover{ background-image: radial-gradient(farthest-side at 20px 20px, green, blue)}
<div>远近角终点渐变效果比较,悬停变远角。</div>
远近角终点渐变效果比较,悬停变远角。

上例中起点为(20px,20px)坐标位置,最近角为左上角(0,0)位置,最远边为右边。使用角时,会产生类似对角线渐变效果,而使用边时没有。

固定尺寸(fixed size)

我们也可以使用像素来定义具体的渐变尺寸:

div{ background-image: radial-gradient(20px 10px at 75% 50%, darkviolet, pink); padding: 1rem; width: 300px;}
<div>使用像素来定义具体的渐变尺寸</div>
使用像素来定义具体的渐变尺寸

上面演示了CSS颜色渐变特性的基本使用方法,通过线性渐变和径向渐变我们可以构造出很漂亮的背景图案,这些图案可以用来装饰按钮、区域乃至整个页面。

下面我们给出2个实用的案例,1个是条纹图案,1个是渐变色按钮:

例子1:拟物风格的渐变色按钮

例子2:渐变背景纹理图案

  1. 这里的语法描述遵循W3所制定的CSS属性值定义语法