现代 CSS

图解CSS: CSS渐变

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

CSS的渐变主要分布在 CSS Images Module Level 3CSS Image Values and Replaced Content Module Level 4 两个规范模块中,其中Level 4 和 Level 3相比,新增了conic-gradient()repeating-conic-gradient()两个属性。在CSS中,CSS的渐变相当于图像,我们可以使用线性渐变(linear-gradient()repeating-linear-gradient())、径向渐变(radial-gradient()repeating-radial-gradient())和锥形渐变(conic-gradient()repeat-conic-gradient())。事实上这三种渐变就相当于背景图像,而且渐变通常是一种颜色渐变到另一种颜色,但是CSS允许你控制渐变发生的每一个方面,从方向、形状到颜色,以及它们如何从一个渐变到另一个渐变。在这篇文章中,主要和大家一起探讨有关于CSS渐变相关的话题。

CSS 渐变简介

渐变一般指的是从一种颜色平滑地过渡到另一种颜色,而且用户代理(比如浏览器)将其渲染为图像,这个图像可以是背景图像(background-image)、边框图像(border-image)和遮罩图像(mask-image)等,即CSS中可以接受图像的任何属性。开发者可以使用一些指定的 CSS渐变函数来指定这些图像,这样用户代理就要以在渲染页面时自动生成图像。其主要语法:

<gradient> = [
    <linear-gradient()> | <repeating-linear-gradient()> |
    <radial-gradient()> | <repeating-radial-gradient()> |
    <conic-gradient()>  | <repeating-conic-gradient()> 
]

比如我们将渐变运用到background-image属性上:

background-image: linear-gradient(#ff8a00, #e52e71);
background-image: repeating-linear-gradient(to right,#ff8a00 10%,#e52e71 20%);}
background-image: radial-gradient(#ff8a00, #e52e71);
background-image: repeating-radial-gradient(circle, #ff8a00 10%, #e52e71 20%);
background-image: conic-gradient(#ff8a00, #e52e71);
background-image: repeating-conic-gradient(#ff8a00 10%, #e52e71 20%);

效果如下:

渐变中的色标

不管使用哪一个渐变函数绘制的渐变图像都由一组指定的颜色构成,并且每个颜色都有对应的位置,在渐变中将其称为<color-stop>,它主要由两部分组成,<color>颜色和渐变线。即渐变函数中指定的 每一个点的颜色。我们通常把这个颜色和相应的位置称为渐变中的色标:

颜色停止(<color-stop>)和过渡提示是在一个颜色停止列表(<color-stop-list>)中指定的,这个颜色停止列表是一个包含两个更多颜色停止和可选过渡提示的列表:

<color-stop-list> = <linear-color-stop> , [ <linear-color-hint>? , <linear-color-stop> ]#
<linear-color-stop> = <color> && <length-percentage>?
<linear-color-hint> = <length-percentage>

比如下面这个示例:

background-image: linear-gradient(to right, rgb(56, 0, 253) 0%, rgb(255, 0, 146) 20%, rgb(255, 111, 177) 40%, rgb(255, 71, 64) 80%, rgb(30,90,88) 100%);

在这个示例中,渐变的梯度线(也称为“渐变线”)是矩形的左侧边缘至右侧边缘,在这个渐变梯度线上有一个五个颜色组成的颜色停止列表,每个颜色的停止位置分别是0%20%40%80%100%。颜色的停止位置可以是百分比也可以其他的长度值(<length>),比如px。如果颜色停止位置是百分比,它的计算是根据起始点和结束点之间梯度线的长度来确定,起始点为0%,结束点是100%。梯度线长度从元素的起始点沿终点方向沿梯度线测量。

CSS中的百分比计算是个复杂的体系,假设我们把上面的线性渐变运用于一个宽度为835px的容器中,它的渐变梯度线长度是835px,那么上对应的百分比转换成px的话是用颜色停止位置的百分比值乘以元素的宽度(width):

注意,上面这个示例算是一个特殊的示例,渐变的角度是0(即to rightto left),但渐变的梯度线长度和渐变角度是有关的,比如,我们把to right换成45deg

background-image: linear-gradient(45deg, rgb(56, 0, 253) 0%, rgb(255, 0, 146) 20%, rgb(255, 111, 177) 40%, rgb(255, 71, 64) 80%, rgb(30,90,88) 100%);

梯度线长度就变了:

这个时候渐变梯度线长度的计算就复杂了。具体如何计算,我们后面会花一定的篇幅来专门介绍。

在渐变中,颜色停止和过渡提示的位置通常位于元素盒子的起始点和结束点之间,但这不是必需的。比如,我们在线上渐变使用多个渐变颜色,但并没有显式指定颜色停止的位置:

background-image: linear-gradient(to right, rgb(56, 0, 253) , rgb(255, 0, 146) , rgb(255, 111, 177) , rgb(255, 71, 64), rgb(30,90,88) );

这个时候会自动被分配一个位置。颜色停止列表中的第一个或最后一个颜色停止分别被指定为渐变梯度线的0%位置(渐变梯度线起始位置)和渐变梯度线的100%位置(渐变梯度线终点位置)。就该示例来说,由五个颜色组成的颜色停止列表,构建四个颜色区间,那么每个区间将会平均分配渐变梯度线的长度,也就是说示例中的第二个颜色的停止位置位于渐变梯度线的25%位置,第三个颜色的停止位置位于渐变梯度线的50%位置,第四个颜色的停止位置位于渐变梯度线的75%位置:

你可能已经发现了,在上面这个示例中,并没有显式的给每个停止颜色指定停止位置,但用户代理在渲染该图像时对每个停止颜色做了一个修正处理。这个过程是一个自动过程,并且这个过程也称为颜色停止修正。用户代理在解析每个色块(停止颜色)的使用位置时,会按下面的步骤来处理:

  • ① 如果第一个停止颜色没有显式设置停止位置,将其停止位置设置为0%;如果最后一个停止颜色没有显式设置停止位置,将其停止位置设置为100%
  • ② 如果一个停止颜色或过渡提示的位置小于停止颜色列表中它前面的任何停止颜色或过渡提示的指定位置,则将其停止位置设置为等于它前面的任何停止颜色或过渡提示的指定位置的最大位置
  • ③ 如果任何停止颜色没有停止位置,那么它们的停止位置会均分有停止位置的前后停止颜色之间的间隔

应用这些规则,所有停止颜色和过渡提示都将有明确的停止位置和停止颜色,并按升序排列。下面这几对渐变,每一对中的后者是前者的手工“修正”版本,通过应用上述规则获得。对于每一对,两个渐变渲染的结果都是相同的。每个箭头中的数字指定在转换中调用了哪些修正步骤。

background-image: linear-gradient(to right, rgb(56, 0, 253) , rgb(255, 0, 146) 20%, rgb(255, 71, 64));
// = ① >> 
background-image: linear-gradient(to right, rgb(56, 0, 253) 0% , rgb(255, 0, 146) 20%, rgb(255, 71, 64) 100%);

根据“规则①”对第一个停止颜色和最后一个停止颜色做修正,第一个停止颜色的停止位置位于渐变线的0%,最后一个停止颜色的停止位置位于渐变线的100%

background-image: linear-gradient(to right, rgb(56, 0, 253) 40% , rgb(255, 0, 146), rgb(255, 71, 64), rgb(188,188,90));

// = ①, ③>> 
background-image: linear-gradient(to right, rgb(56, 0, 253) 40% , rgb(255, 0, 146) 60%, rgb(255, 71, 64) 80%, rgb(188,188,90) 100%);

根据“规则①”将最后一个停止颜色(rgb(188, 188, 90))的停止位置修正为渐变线的100%位置,然后根据“规则③”对第二个停止颜色(rgb(255, 0, 146))和第三个停止颜色(rgb(255, 71, 64))的停止位置进行修正。因为这两个停止颜色都没有显式设置停止位置,因此它会均分第一个停止颜色和最后一个停止颜色之间的间距(即渐变线的100% - 40% = 60%),根据计算可以得到第二个停止颜色的停止位置位于渐变线的60%,第三个停止颜色的停止位置位于渐变线的80%

background-image: linear-gradient(to right, rgb(56, 0, 253) -10% , rgb(255, 0, 146), rgb(255, 71, 64));

// = ①, ③ >> 
background-image: linear-gradient(to right, rgb(56, 0, 253) -10% , rgb(255, 0, 146) 45%, rgb(255, 71, 64) 100%);

这个示例也是根据“规则①, ③”来进行修正的,最后一个停止颜色的停止位置会位于渐变线的100%,第二个停止颜色(rgb(255, 0, 146))没有显式设置停止位置,将会均分第一个和最后一个停止颜色位于渐变线上的间距(即100% - (-10%) ÷ 2 = 55%),也就是容器宽度的45%

background-image: linear-gradient(to right, rgb(56, 0, 253) -50px , rgb(255, 0, 146), rgb(255, 71, 64));

// = ①, ③ >> 
background-image: linear-gradient(to right, rgb(56, 0, 253) -50px , rgb(255, 0, 146) calc(50% - 25px), rgb(255, 71, 64) 100%);

这个示例和上面的示例是相似的,不同之处停止颜色的停止位置有两种不同的单位(px%),但修正规则是相同的,第二个停止颜色rgb(255, 0, 146)没有显式设置停止位置,它会是均分与其相邻两停止颜色位置之间的间距(即100% - (-50px) ÷ 2),最终的值是100% - (-50px) ÷ 2 - 50px = 50% - 25px在CSS中不同单位之间的混合计算需要使用calc()函数来表达,即calc(50% - 25px)

注意:如果在渐变中停止颜色的停止位置使用混合单位值(比如pxemvw%)时要多加小心,因为这可能会导正停止颜色在之前的停止颜色之前无意地移动。比如background-image: linear-gradient(yellow 100px, blue 50%),当容器高度不小于200px时不会触发任何颜色停止位置的修正,然而,当容器高度是150px时,那么blue的停止位置就相当于75px,位于yellow之前,根据前面“规则②”,blue停止颜色的停止位置会得到修正,会修正为和yellow相同的停止位置,即100px

background-image: linear-gradient(to right, rgb(56, 0, 253) 20%, rgb(255, 0, 146) 0%, rgb(255, 71, 64) 40%);

// = ② >> 
background-image: linear-gradient(to right, rgb(56, 0, 253) 20%, rgb(255, 0, 146) 20%, rgb(255, 71, 64) 40%);

在这个示例中,虽然三个停止颜色都显式指定了停止位置,但第二个停止颜色的停止位置设置了0%,它比前面的停止颜色的停止位置要小,这个时候会根据“规则②”进行调整,会将其停止位置设置为前面最大的位置,即20%

再来看一个示例:

background-image: linear-gradient(to right, rgb(56, 0, 253),  rgb(255, 0, 146) -20%, rgb(32,123,225) 50%,rgb(255, 111, 177) 120%, rgb(55, 71, 164));

// = ①, ② >> 
background-image: linear-gradient(to right, rgb(56, 0, 253) 0%,  rgb(255, 0, 146) 0%, rgb(32,123,225) 50%,rgb(255, 111, 177) 120%, rgb(55, 71, 164) 120%);

上面我们都是以线性渐变为例向大家阐述了渐变中色标相关的细节,但在径向渐变和锥形渐变中色标的计算有所差异,我们先来看径向渐变为例:

background-image: radial-gradient(50% 100%, #FFFFFF 0%, #972929 34%, #3571DF 67%, #C014CF 100%);

径向渐变和线性渐变的梯度线(渐变线)略有不同,径向渐变的渐变线长度是以其半径,那么对应的百分比也是相对于其半径为基础计算:

如果径向渐变是一个椭圆形渐变:

background-image: radial-gradient(50% 100%, #FFFFFF 50%, #972929 67%, #3571DF 83%, #C014CF 100%);

其停止颜色的百分比也是相对于其半径做计算:

在锥形渐变中,颜色停止就更独特一点,其渐变线是其周长,如果停止颜色的位置是百分比,那么它是相对于360deg来计算的:

background-image: conic-gradient(at 50% 50%, #FFFFFF 0%, #972929 25%, #3571DF 50%, #B60A46 75%, #3DD69F 100%);

第一个停止颜色(#ffffff)位置对应的是0deg,第二个停止颜色(#972929)位置对应的是90deg、第三个颜色(#3571df)对应的是180deg,第四个颜色(#b60a46)对应的是270deg,第四个颜色(#3dd69f)对应的是360deg

不管是哪种类型的CSS渐变,每个停止颜色都有相应的停止位置,即使未显式设置。当然每种渐变的停止颜色的停止位置计算方式都有所差异。

线性渐变

在Web设计中最为常见的渐变类型是 linear-gradient(),它也常称为“线性渐变”,因为该类型的渐变颜色是从左到右、从上到下、或者在一个方向上行何角度上的渐变。

线性渐变的语法规则如下:

linear-gradient() = linear-gradient([ <angle> | to <side-or-corner> ]? ,<color-stop-list>)
<side-or-corner> = [left | right] || [top | bottom]

linear-gradient()函数的第一个参数<angle>to <side-or-corner>是用来指定渐变线方向,并决定停止颜色在渐变线上的停止位置。如果省略该参数,那么它的值是to bottom,即从顶部到底部。该参数接受两种方式指定的值:

  • <angle> :通过角度来指定渐变线的方向,它的单位可以是degturngradsrad;而且值可以是正负值,其中正值代表顺时针旋转,负值代表逆时针旋转
  • 使用关键字:这里关键字指的是<side-or-corner>,可以是to topto rightto bottomto leftto top rightto bottom rightto bottom leftto top left等。如果参数是to topto rightto bottomto left,则渐变线的角度分别是0deg90deg180deg270deg。如果参数指定了方向是某个方框的角度(比如to top left),则渐变线必须具有一定的角度,使其与指定的角相交于同一象限,并且垂直于渐变框的两个相邻角相交的直线。

我们来看一些简单的示例,以双色线性渐变在不同角度和关键词下的效果:

<!-- HTML -->
<div style="--linear-direction: to top"></div>
<div style="--linear-direction: to right"></div>
<div style="--linear-direction: to bottom"></div>
<div style="--linear-direction: to left"></div>
<div style="--linear-direction: 0deg"></div>
<div style="--linear-direction: 45deg"></div>
<div style="--linear-direction: 90deg"></div>
<div style="--linear-direction: 135deg"></div>
<div style="--linear-direction: 180deg"></div>
<div style="--linear-direction: 225deg"></div>
<div style="--linear-direction: 270deg"></div>
<div style="--linear-direction: 315deg"></div>
<div style="--linear-direction: 360deg"></div>
<div style="--linear-direction: to top right"></div>
<div style="--linear-direction: to bottom right"></div>
<div style="--linear-direction: to top left"></div>
<div style="--linear-direction: to bottom left"></div>
<div style="--linear-direction: 15deg"></div>
<div style="--linear-direction: -225deg"></div>

/* CSS */
:root {
    --color-start: #09f;
    --color-stop: #e52e71;
    --linear-direction: to top;
}

div {
    width: 100%;
    height: 30vh;
    border-radius: 5px;
    position: relative;
    background-image: linear-gradient(
        var(--linear-direction),
        var(--color-start),
        var(--color-stop)
    );
}

效果如下:

在渐变中,我们不局限于只有两种颜色!事实上,我们可以有任意多的逗号分隔的渐变色(即<color-stop-list>),比如下面这个示例,就用了四个渐变颜色:

body {
    background-image: linear-gradient(to right, red, #f06d06, rgb(255, 255, 0), green);
}

linear-gradient()的语法规则中我们可以获知,我们可以通过指定一个<angle>来指定渐变线的方向。在介绍渐变中色标的时候也提到过,渐变中的角度对于渐变线的影响是复杂的。这里我们以线性渐变为例来向大家介绍<angle>对渐变线方向带来的影响。

先来看一个简单的示例:

:root {
    --color-start: #09f;
    --color-stop: #e52e71;
    --linear-direction: to top right;
}

div {
    background-image: linear-gradient(var(--linear-direction),var(--color-start),var(--color-stop));
}

这个示例渐变是从元素的左下角到右上角。此时渐变的角度会由元素的大小决定。对于一个正方形,它的角度正好是45deg。如果元素的宽高比发生变化,则渐变的角度调整为对角线的角度,例如宽高比为2:1的角度约为26.5deg

这是一个反正切,它和正切之间的关系如下图所示:

这里涉及到了一些数据知识,你可以阅读维基百科中有关于三角函数反三角函数相关的文档。

我们把示例调整一下:

div {
    background-image: linear-gradient(36deg, #f09, #3023AE, #0ff);
}

我试着一步一步解释这个渐变角度意味着什么?

首先在元素上绘制一个垂直轴,并将它旋转36deg。这条轴我们称为梯度轴:

接下来,我们绘制最接近渐变轴的矩形的对角线。在我们的例子中,这是从左下到右上的对角线。在这个对角线上,我们指定了颜色点:#f090%#3023AE50%#0ff100%

现在还缺三条线,这两条线贯穿给定的颜色点,并且与梯度轴正交。我们把它们称为颜色停止轴。

最后,可以绘制渐变。我们可以看到它精确地以指定的角度运行,但是在外部边缘可以看到定义为0100的颜色的一小部分:

从上图中可以轻易的发现,对角线,渐变轴和颜色停止轴构成了一个直角三角形。应用 泰勒斯定理,我们可以在这个三角形周围画一个圆。如果我们在剩下的三个角重复整个过程,就能得到一个有点像花的图形。当梯度旋转时,它的端点沿这个花形状的外线运行。

@Nils Binder在Codepen通过一个Demo,完美的实现上述提到的每个过程

尝试在上面示例中改变他的角度值,你会看到下图这样的效果:

其实在规范中也对渐变线做出了很详细的解释。如果W是渐变容器的宽度,H是渐变容器的高度,A是渐变角度,那么渐变线的长度可以通过下面的公式计算:

abs(W * sin(A)) + abs(H * cos(A))

径向渐变

径向渐变与线性渐变最大的不同之处在于它从一个点开始向外发散。渐变经常被用来模拟光源,我们知道光源并不总是直的。这使得径向渐变中颜色之间的过渡看起来更加自然。

在径向渐变中,颜色不像线性渐变那样从渐变框的一边平滑地褪色到另一边,而是从单个点出现,并以圆形或椭圆形平滑地向外扩散。

径向渐变是通过渐变线的中心和结束形状的大小和形状(它可能是圆形或椭圆形)来指定的。颜色停止以列表的形式给出,就像线性渐变一样。从渐变中心开始,向(可能超出)结束形状前进,绘制均匀缩放的同心圆(或椭圆),并根据指定的停止颜色着色。

径向渐变的语法规则如下:

radial-gradient() = radial-gradient([ <ending-shape> || <size> ]? [ at <position> ]? ,<color-stop-list>)

radial-gradient()由其中心点、边缘形状轮廓及位置、色值结束点定义而成。径向渐变的中心点至边缘形状以及其延伸的部分,由连续缩放的若干同心轮廓组成,这个轮廓由设定的边缘形状决定。色值结束点用于设定虚拟渐变射线(Virtual Gradient Ray)的变化方式,由中收点水平变化至右侧:

radial-gradient()函数中的各个参数的定义如下:

  • <ending-shape> :决定径向渐变从一种颜色过渡到另一种颜色时所遵循的形状,主要有circle(圆)或ellipse(椭圆)。在我们讨论径向渐变时,<ending-shape>本质上被限制为圆形。radial-gradient()可以省略这个值(即,不显式设置该值),该值被省略的话,则<size>为单个<length>,则结束形状默认为圆形,否则为椭圆。
  • <size> : 决定渐变结束形状的大小。如果省略,其默认值为farthest-side<size>的值可以是关键字(比如closest-sidefarthest-sideclosest-cornerfarthest-corner),也可以是由<length><length-percentage>指定的半径。为了实现关键词定义的目的,将渐变框边缘看作是在两个方向上无限扩展的,而不是有限的线段。如果<ending-shape>ellipse,它的轴与水平轴和垂直轴对齐。相对而言,<size>取值为关键词时较难理解,在后面我们单独把这部分拿出来和大家一起探讨。
  • at <position> :指定渐变图形<ending-shape>的中心在渐变元素中的位置。它和background-position的工作方式非常相似。这意味着toprightbottomleft这样的关键词都可以用,也可以将关键词组合起来使用,比如top lefttop centertop right等。除此之外,还可以使用数字值(包括百分比)来指定确切的位置,所有这些数字值都是相对于元素的边框的。如果该值省略的话,其默认值是center(即50% 50%)。
  • <color-stop-list>:渐变停止颜色列表。包含一个<color>值加上可选的位置值(相对虚拟渐变射线的<percentage>或者<length>长度值)。 百分比值0%,或者长度值0,表示渐变中心点;百分比值100%表示渐变射线与边缘形状相交的点。 其间的百分比值线性对应渐变射线上的点。

扩展上述定义,radial-gradient()的语法也可以像下面这样来描述:

radial-gradient() = 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

我们来看一些简单的示例:

:root {
    --color-start: #ebf;
    --color-center: #09f;
    --color-end: #f36;
    --ending-shape: ;
    --size: farthest-corner;
    --position: center;
}

.radial__gradient {
    background-image: radial-gradient(
        var(--ending-shape) var(--size) at var(--position),
        var(--color-start),
        var(--color-center),
        var(--color-end)
    );
}

效果如下:

尝试着在上面的Demo中调整radial-gradient()函数的各个参数值,你将看到不同的效果。

<size>

在介绍radial-gradient()函数中的<size>参数时,它可以使用一些关键词<extent-keyword>,即closest-sidefarthest-sideclosest-cornerfarthest-corner。为了能让大家更好的理解这几个关键词如何控制径向渐变大小(<size>),先向大家写一个Demo:

:root {
    --color-start: #09f;
    --color-end: rgba(255, 255, 255, 1);
    --position: 50% 75%;
}

div {
    background-image: radial-gradient(
        var(--ending-shape) var(--size) at var(--position),
        var(--color-start),
        var(--color-end)
    );
}

效果如下:

closest-side

当使用closest-side来设置一个圆形径向渐变大小,主要是通过径向边缘与离元素最近边缘的切点到圆心之间的直线距离大决定;当使用closest-side来设置椭圆形径向渐变大小,主要通过径向渐变水平与垂直边缘与离最近边缘切点到圆心的直线距离大小决定:

farthest-side

当使用farthest-side来设置圆形径向渐变大小,主要通过径向渐变边缘与元素最远边的切点到圆心的直线距离大小决定;当使用farthest-side来设置椭圆形径向渐变大小,主要通过径向渐变与元素最远边切点到圆心的直线距离大小决定:

closest-corner

当使用closest-corner来设置圆形径向渐变大小,主要通过渐变边缘与到元素最近顶角交接点到圆心直线距离决定;当使用closest-corner来设置椭圆形径向渐变大小,主要通过径向渐变边缘与到元素最近顶角交接点到圆心的直线距离大小决定:

farthest-corner

当使用farthest-corner来设置圆形径渐变的大小,主要通过径向渐变边缘与元素最远顶角交点到圆心的直线距离决定;当使用farthest-corner来设置椭圆形径向渐变,主要通过渐变边缘与元素最远顶点的交接点到圆心的直线距离决定:

radial-gradient()函数的<size>参数中,除了<extent-keyword>值之外,还可以是<length><length-percentage>值,其中<length>只能用于circle(圆形渐变),<length-percentage>只能用于ellipse(椭圆形渐变),并且需要是两个值:

/* 正确的用法 */
background-image: radial-gradient(#09f, #f36);
background-image: radial-gradient(10px, #09f, #f36);
background-image: radial-gradient(10px 20px, #09f, #f36);
background-image: radial-gradient(50% 50%, #09f, #f36);
background-image: radial-gradient(circle 20px, #09f, #f36);
background-image: radial-gradient(ellipse 20% 50%, #09f, #f36);
background-image: radial-gradient(ellipse 100px 200px, #09f, #f36);
background-image: radial-gradient(ellipse 10px 10%, #09f, #f36);

/* 不正确的用法 */
background-image: radial-gradient(50%, #09f, #f36);
background-image: radial-gradient(circle 10%, #09f, #f36);
background-image: radial-gradient(circle 50% 50%, #09f, #f36);
background-image: radial-gradient(ellipse 50%, #09f, #f36);
background-image: radial-gradient(ellipse 100px, #09f, #f36);
background-image: radial-gradient(circle 10px 10%, #09f, #f36);

前面提到过,在使用radial-gradient()函数时,<ending-shape>是可以省略不写的,则<size>为单个<length>,则结束形状默认为圆形,否则为椭圆。但是,<ending-shape><size>同时都省略的时候,则会根据容器自己来匹配渐变形形状。如果容器是正方形,则会是一个圆形渐变,否则则是一个椭圆形渐变。

使用radial-gradient()时还有一个小技巧,可以用两个radial-gradient()来模拟一个linear-gradient()的效果。不过这个小技巧中有一个小小的限制,那就是两个radial-gradient()是相对角,这个模拟出来的效果要比linear-gradient()效果更柔和:

background-image: 
    radial-gradient(
        circle at top right, 
        hsl(var(--cyanHSL)), hsl(var(--cyanHSL) / 0%)
    ),
    radial-gradient(
        circle at bottom left, 
        hsl(var(--pinkHSL)), hsl(var(--pinkHSL) / 0%)
    )
; 

我们来看一个对比效果:

div {
    background-image: linear-gradient(
        to top right,
        var(--cyanHSL),
        var(--pinkHSL)
    );
}

div {
    background-image: 
        radial-gradient(circle at left bottom,var(--cyanHSL),var(--pinkHSL)),
        radial-gradient(circle at top right, var(--cyanHSL), var(--pinkHSL));
}

效果如下:

在CSS中使用radial-gradient()函数也有令人感到恶心或不解的地方。从前面的内容中可以知道的是:radial-gradient()函数的使用中,其<position><size><ending-shape>几个参数可以相互组合,但这些参数的相互组合可能会产生半径为0circleellipse。比如,渐变的中心在渐变框的边缘上,并且指定了closest-sideclosest-corner,或者明确指定了<size><ending-shape>值,且半径的任意一个为0,就会发生这种情况。

针对于这些情况,其渲染规则是:

  • 如果<ending-shape>是半径为0的圆形,会将<ending-shape>渲染为一个圆,其半径是任意一个非常小的比零大的值。这会使得渐变仍然看起来像一个圆
  • 如果<ending-shape>的宽度为0(无论高度如何),会将<ending-shape>渲染为一个椭圆,其高度是任意一个非常大的值,其宽度是任意一个非常小的比0大的值。这会使得渐变看起来类似于水平方向的渐变,并且关于椭圆中心对称。这也决味着,所有用百分比定义的颜色位置的百分百是相对于0px
  • 如果<ending-shape>的高度为0,会将<ending-shape>渲染为一个椭圆,其宽度是任意一个非常大的值,其高度是任意一个非常小的比零大的值。这会使用渐变看起来像一个纯色的图片,其颜色为最后一个位置的颜色,或者如果它是重复的话,其颜色为渐变的平均色

圆锥渐变

conic-gradient(圆锥渐变)和径向渐变(radial-gradient)相似。两者都是圆形的渐变,默认情况下将元素的中心作为停止颜色源点。然而,在径向渐变的的停止颜色是在以圆的中心到渐变边缘的射线上,而圆锥渐变的停止颜色是在圆的周长上。

conic-gradient被称为“圆锥渐变”是因为它看起来像一个从上面看的圆锥体。

conic-gradient是通过指定渐变中心、旋转角度和一个停止颜色列表来指定。它和linear-gradient()radial-gradient()不同的是,圆锥渐变的停止颜色位置是通过<angle>指定的。然后画出从中心发出并指向各个方向的射线,每条射线的颜色会等于它们相交的斜线的颜色。

我们可以像这样来理解圆锥渐变(conic-gradient()):

圆锥渐变(conic-gradient())它位于“某一点”(渐变中心位置),以一种颜色的媒体角度开始,以另一个颜色的某个角度线束

其实上面的描述也将圆锥渐变的语法陈述了:

conic-gradient() = conic-gradient([ from <angle> ]? [ at <position> ]?, <angular-color-stop-list>)

参数的定义如下:

<angle> :用来指定整渐变的旋转角度,如果该值省略,其值为0deg

background-image: conic-gradient(from 30deg, #09f, #f36);

调整上面示例中的角度值,你可以看到整个圆锥渐变在根据相应的角度值进行旋转:

<position> : 用来定义圆锥渐变中心点的位置,它和radial-gradient()渐变中的<position>一样,其用法和CSS的background-position类似,如果该值省略的话,其默认的值为center

background-image: conic-gradient(from 30deg at top left, #09f, #f36);

效果如下:

<angular-color-stop-list><color-stop-list>类似,都是用来指定渐变停止颜色(<color-stop>)和停止位置(<color-hint>),不同的是linear-gradient()radial-gradient()<color-stop-list>的颜色停止位置是相对于渐变线计算的;而<angular-color-stop-list>围绕着圆心绘制的圆形上。比如说,从conic-gradient()的圆心开始,每个角度都有一条射线,该射线会和相应的圆相交,该交点就是颜色停止位置。比如说0%100%的位置是在0deg的射线与圆相交的点,45deg对应的百分比就是45 / 360 = 12.5%

比如下面这个示例:

div {
    background-image: conic-gradient(
        red,
        yellow,
        lime,
        aqua,
        blue,
        magenta,
        red
    );
}

它等同于:

div {
    background-image: conic-gradient(red 0%, yellow 16.66%, lime 33.33%, aqua 50%, blue 66.66%, magenta 83.33%, red 100%);
}

就该例而言,相当于将360deg均分了六份,每份是16.66%,即60deg

也可以显式的在停止颜色中指定其停止位置,比如:

background-image: conic-gradient(red 0%, yellow 16.66%, lime 33.33%, aqua 50%, blue 66.66%, magenta 83.33%, red 100%);
background-image: conic-gradient(red 0%, yellow 16.66%, lime, aqua, blue 50%, magenta 85%, red);
background-image: conic-gradient(red, yellow 20%, lime 10%, aqua, blue 50%, magenta 85%, red);

使用conic-gradient()函数时,在颜色停止位置处可以添加硬停止来构建饼图效果:

background-image: conic-gradient(
    #09f 5%,
    #f36 0 10%,
    #09f 0 15%,
    #f36 0 20%,
    #09f 0 25%,
    #f36 0 30%,
    #09f 0 35%,
    #f36 0 40%,
    #09f 0 45%,
    #f36 0 50%,
    #09f 0 55%,
    #f36 0 60%,
    #09f 0 65%,
    #f36 0 70%,
    #09f 0 75%,
    #f36 0 80%,
    #09f 0 85%,
    #f36 0 90%,
    #09f 0 95%,
    #f36 0
);

除此之外,conic-gradient()函数中颜色停止位置除了使用%单位之外,还可以使用turngradsrad相关的度数单位,而且也可以使用负值:

重复渐变

在CSS中除了linear-gradient()(线性渐变)、radial-gradient()(径向渐变)和conic-gradient()(圆锥渐变)之外还有相应的重复渐变,即 repeating-linear-gradient()repeating-radial-gradient()repeating-conic-gradient()。这三种类型的重复渐变的语法和相对应的渐变类型相同,例如,repeating-linear-gradient()linear-gradient()语法相同。

重复渐变采用了一种技巧,可以在linear-gradient()radiial-gradient()conic-gradient()的基础上创造性的使用停止颜色,并为我们所用。我们可以使用他们创造出图案,并允许它们无限地重复。当渲染时,停止颜色点在两个方向无限重复,它们的位置以最后一个指定的颜色停止位置与第一个指定的颜色停止位置之差的倍数移动。例如,repeating-linear-gradient(red 10px, blue 50px)等同于linear-gradient(..., red -30px, blue 10px, red 10px, blue 50px, red 50px, blue 90px, ...)。请注意,最后一个颜色停止位置和第一个颜色停止位置总是在每一组的边界上重合,如果渐变的开始和结束颜色不相同,就会产生尖锐的过渡。比如:

background-image: repeating-linear-gradient(
    to right,
    red,
    red 20px,
    gold 20px,
    gold 40px
);

background-image: repeating-radial-gradient(
    red,
    red 20px,
    gold 20px,
    gold 40px
);

background-image: repeating-conic-gradient(red, gold 20deg);

效果如下:

接下来,我们来具体看这三种类型的重复渐变。

repeating-linear-gradient()

repeating-linear-gradient()创建一个由重复线性渐变组成的<image>,它会在所有方向上重复渐变以覆盖其整个容器。这个函数的结果是一个<gradient>数据类型的对象,是一个特殊的<image>类型。

为了更好的帮助大家理解重复线性渐变,我们先从一个简单的linear-gradient()开始,比如:

div {
    background-image: linear-gradient(90deg, red, gold);
}

我们在该基础上添加一个background-size: 40px,同时在xrepeat

div {
    background-image: linear-gradient(90deg, red, gold);
    background-size: 40px;
    background-repeat: repeat-x;
}

你将看到像下图这样的效果:

最终的效果经历了三个过程:

  • 使用linear-gradient(90deg, red, gold)绘制了一张渐变图像,该图像默认尺寸是容器的宽高
  • 接着使用background-size: 40pxlinear-gradient(90deg, red, gold)创建的图像尺寸设置为宽度是40px,高度是容器的高度
  • 使用background-repeat: repeat-x,将linear-gradient(90deg, red, gold)创建的图像沿着容器的x轴方向水平平铺,将会铺满整个容器

将上面的示例稍作调整:

div {
    background-image: linear-gradient(
        90deg,
        red,
        red 50%,
        gold 50%,
        gold 100%
    );
    background-size: 40px;
    background-repeat: repeat-x;
}

整个效果会更清晰:

这两个示例演示的效果,其实就是一种背景图像重排的效果。也就是说,就这两个效果,我们可以repeating-linear-gradient() 函数来实现:

div {
    background-image: repeating-linear-gradient(
        90deg,
        red,
        red 0,
        gold 40px,
        gold 40px
    );
}

div {
    background-image: repeating-linear-gradient(
        90deg,
        red,
        red 20px,
        gold 20px,
        gold 40px
    );
}

效果如下:

如果我们把渐变容器宽度设置为40px时,这两个重复线性渐变效果如下:

repeating-linear-gradient()函数中,上面的效果也被称为 基准渐变长度,它看上去像是background-size指定的长度。也就是说重复线性渐变中停止颜色(色标位置)的偏移量都是基准渐变长度(最后一个色标和第一个色标的距离),这也是每次重复时的长度。那么repeating-linear-gradient()函数会以这个基准渐变长度重复排列(有点类似于background-repeat)。当容器宽度超过这个基准渐变长度时,那么repeating-linear-gradient()色标位置的偏移量就是这个基准渐变长度的倍数:

因此,最后色标的色值应该与第一个色标的色值保值一致;如果不一致的话,会导致非常突兀的渐变效果。

与其他渐变一样,repeating-linear-gradient()也没有提供固定的尺寸;即,它没有原始尺寸或首选尺寸,也没有首选的比例。它将自适应于对应的元素的尺寸。

就上面的示例而言,使用linear-gradient()background-size相结合能实现类似于repeating-linear-gradient()类似的效果,那么为什么还需要repeating-linear-gradient()呢?

先来看一个示例:

手动调整示例中角度值,可以明显的看到它们之间的差异:

我们来看一个45deg的示例,先把渐变容器尺寸宽度都调整为40px,刚好是repeating-linear-gradient()的一个基准渐变长度:

从上图中我们可以获知,如果用linear-gradient()background-size实现repeating-linear-gradient()的效果,将需要使linear-gradient()绘制图下图的效果:

这将会需要一定的数学知识:

正如上图所示,需要计算出渐变线AD的长度,以及ABAB')、ACAC')的长度,这样就可以知道BB')点和CC')点的位置。这样就可以使用linear-gradient()绘制出与repeating-linear-gradient()类似的斜纹效果。

其实,@Lea Verou在她的著作《CSS Secrets》中还提供了更为简单的计算方式。这里简单的介绍一下。

我们所要的条纹效果,其实有点类似于使用了下图这样的一张位置在容器中平铺得来:

它包含了四条纹理,而不是这里的两条,所以看起来像是无缝连接的。我们可以使用linear-gradient()描述类似上图的位图:

div {
    background-image: linear-gradient(45deg, red 25%, gold 25%, gold 50%, red 50%, red 75%, gold 0);
    background-size: 40px 40px;
}

虽然这样能实现类似于repeating-linear-gradient()创建的斜文效果,但时每条条纹看起来要小得多:

为了解释这个问题,我们需要使用学校里学到的勾股定理来计算直角三角形的各边变长。勾股定理指出,最长边等于其他两边的平方和。在直接三角形中,两条短边相等所以么最长边就等于:

在创建这个斜纹中,background-size指定的就是三角形最长边的边长,因此纹理的宽度就是直角边的长度。在大小为40pxbackground-size将会产生宽度为40 × √2(即40 * Math.sqrt(2)),大约等于56.5685px。修正之后的:

div {
    background-image: linear-gradient(
        45deg,
        red 25%,
        gold 25%,
        gold 50%,
        red 50%,
        red 75%,
        gold 0
    );
    background-size: 56.5685px 56.5685px;
}

效果如下:

现在虽然在视觉效果上看上去相似了,但决不能说linear-gradient()background-size结合就可以替代repeating-linear-gradient()。比如,我们角度换成一个30deg

是不是惨不忍睹!

repeating-radial-gradient()

CSS函数repeating-radial-gradient()创建一个从原点辐射的重复渐变组成的<image>。它类似于radial-gradient()并且采用相同的参数,但是它会在所有方向上重复颜色,以覆盖其整个容器。

div {
    background-image: radial-gradient(
        circle at center,
        red 25%,
        gold 25%,
        gold 50%,
        red 50%,
        red 75%,
        gold 0
    );
}

div {
    background-image: repeating-radial-gradient(
        circle at center,
        red,
        red 20px,
        gold 20px,
        gold 40px
    );
}

虽然repeating-radial-gradient()radial-gradient()有着相同的语法规则,但他们最终产生的效果是相差万里的。

repeating-radial-gradient()的重复计算和repeating-linear-gradient()是相似的。

你是否会问,在CSS中使用radial-gradient()background-size结合是不是也可以模拟出repeating-radial-gradient()的效果,我只能说难,非常的难。我们在上面的示例基础上稍做调整:

background-image: radial-gradient(
    circle at center,
    red 25%,
    gold 25%,
    gold 50%,
    red 50%,
    red 75%,
    gold 0
);
background-size: 20% 20%;

效果如下:

当然,在某些场景下,仅使用radial-gradient()也可以模拟出repeating-radial-gradient()相似的视觉效果,但相对来说要更麻烦:

div {
    background-image: radial-gradient(
        circle at center,
        red,
        red 20px,
        gold 20px,
        gold 40px,
        red 40px,
        red 60px,
        gold 60px,
        gold 80px,
        red 80px,
        red 100px,
        gold 100px,
        gold 120px,
        red 120px,
        red 140px,
        gold 140px,
        gold 160px,
        red 160px,
        red 180px,
        gold 180px,
        gold 200px,
        red 200px,
        red 220px,
        gold 220px,
        gold 240px,
        red 240px,
        red 260px,
        gold 260px,
        gold 280px,
        red 280px,
        red 300px,
        gold 300px,
        gold 320px,
        red 320px,
        red 340px,
        gold 340px,
        gold 360px,
        red 360px,
        red 380px,
        gold 380px,
        gold 400px,
        red 400px,
        red 420px,
        gold 420px,
        gold 440px,
        red 440px,
        red 460px,
        gold 460px,
        gold 480px,
        red 480px,
        red 500px,
        gold 500px,
        gold 520px,
        red 520px,
        red 540px,
        gold 540px,
        gold 560px,
        red 560px,
        red 580px,
        gold 600px,
        gold 620px
    );
}

div {
    background-image: repeating-radial-gradient(
        circle at center,
        red,
        red 20px,
        gold 20px,
        gold 40px
    );
}

效果非常的相似,但代码但代码也是成几何倍增加。

另外,一旦参数稍作调整,radial-gradient()repeating-radial-gradient()的效果就有差异了,比如说,把上面示例circle at center 调整为circle 100px at left top时,radial-gradient()相应的缺陷就出来了:

虽然在原有基础上继续添加repeating-radial-gradient()的基准渐变量可以达到相似视觉效果,但这样对于开发者来说总是痛苦的。

repeating-conic-gradient()

repeating-conic-gradient()像另外两个重复渐变(repeating-linear-gradient()repeating-radial-gradient())一样,都是用来创建重复渐变图像。它的语法规则和conic-gradient()类似,颜色停止位置被放置在渐变的圆弧上

div{
    background-image: conic-gradient(red 0 33%, gold 33% 66%, #09f 66%);
}

div {
    background-image: repeating-conic-gradient(
        red 0 8.33%,
        gold 8.33% 16.66%,
        #09f 16.66% 24.999%
    );
}

reapeating-conic-gradient()repeating-radial-gradient()语法也有点相似

像非重复的锥形渐变一样,重复部分的大小是从最后一个颜色停止的角度减去的第一个颜色停止

div {
    background-image: repeating-radial-gradient(
        red 0 8%,
        gold 8% 16%,
        #09f 16% 24%
    );
}


div {
    background-image: repeating-conic-gradient(
        red 0 8.33%,
        gold 8.33% 16.66%,
        #09f 16.66% 24.999%
    );
}

但是它们之间也是有一定的差异:

在CSS中repeating-conic-gradient()是很有作用的,在后面介绍用例的时候,将会向大家展示其强大的魅力。

缓动渐变

缓动渐变并不是W3C规范中的。但是缓动函数能给我们的渐变带来质的变化,就拿线性渐变来举例,线性渐变在开始和、或结束的地方通常会硬边。我们可以通过缓动函数来控制颜色组合来避免这种现象。

在CSS中,缓动函数主要被运用于transitionanimation中的transition-timing-functionanimation-timing-function中。除了常见的lineareaseease-inease-outease-in-outsteps()等还有cubic-bezier。在将来或现在借助于PostCSS插件的能力,我们也可以在渐变中使用缓动函数

对应的代码:

.ease-gradient {
    linear-gradient(
        to top left,
        hsla(294, 100%, 45%, 0.48),
        cubic-bezier(0.7, 0.04, 0, 0.89),
        hsla(160, 98%, 43%, 1)
    );
};

编译出来的代码:

.ease-gradient {
    linear-gradient(
        to top left,
        hsla(294, 100%, 45.1%, 0.48) 0%,
        hsla(293.3, 80.68%, 49.61%, 0.49) 12.2%,
        hsla(292.45, 75.26%, 53.52%, 0.509) 21.3%,
        hsla(291.37, 69.66%, 56.71%, 0.537) 27.7%,
        hsla(289.8, 62.6%, 59.38%, 0.571) 32%,
        hsla(287.27, 54.11%, 61.65%, 0.611) 34.8%,
        hsla(282.77, 44.32%, 63.59%, 0.656) 36.6%,
        hsla(273.82, 33.39%, 65.24%, 0.702) 38%,
        hsla(252.05, 21.6%, 66.63%, 0.75) 39.6%,
        hsla(206.45, 18.85%, 64%, 0.798) 41.8%,
        hsla(173.58, 23.29%, 60.54%, 0.844) 45.2%,
        hsla(161.14, 36.33%, 59.4%, 0.887) 50.4%,
        hsla(156.93, 48.21%, 57.48%, 0.926) 57.9%,
        hsla(155.95, 58.42%, 54.65%, 0.959) 68.3%,
        hsla(156.83, 66.73%, 50.56%, 0.984) 82.2%,
        hsl(159.91, 98.17%, 42.94%) 100%
    );
};

除了使用上面的在线编辑工具之外,还可以使用PostCSS的插件 postcss-easing-gradients。我们可以像下面这样引入该插件:

linear-gradient([ <direction>,]?<color>,<animation-timing-function>,<color>)

我们就可以像下面这样使用:

.cubic-bezier {
    background: linear-gradient(to bottom, black, cubic-bezier(0.48, 0.3, 0.64, 1), transparent);
}

/* 编译出来的结果 */
.cubic-bezier{
    background: linear-gradient(
        to bottom,
        hsl(0, 0%, 0%),
        hsla(0, 0%, 0%, 0.94505) 7.9%,
        hsla(0, 0%, 0%, 0.88294) 15.3%,
        hsla(0, 0%, 0%, 0.81522) 22.2%,
        hsla(0, 0%, 0%, 0.7426) 28.7%,
        hsla(0, 0%, 0%, 0.66692) 34.8%,
        hsla(0, 0%, 0%, 0.58891) 40.6%,
        hsla(0, 0%, 0%, 0.50925) 46.2%,
        hsla(0, 0%, 0%, 0.42866) 51.7%,
        hsla(0, 0%, 0%, 0.34817) 57.2%,
        hsla(0, 0%, 0%, 0.2693) 62.8%,
        hsla(0, 0%, 0%, 0.19309) 68.7%,
        hsla(0, 0%, 0%, 0.12126) 75.2%,
        hsla(0, 0%, 0%, 0.05882) 82.6%,
        hsla(0, 0%, 0%, 0.01457) 91.2%,
        hsla(0, 0%, 0%, 0)
    );
}

除了PostCSS插件之外还可以使用Sketch插件 sketch-easing-gradient

在Sketch中的操作我录了一个屏:

导出来的CSS代码如下:

/*
* Future CSS (use it today with postCSS-easing-gradients - note your settings colorMode: 'lrgb' and colorStops: 15)
*/
.future {
    background-image: linear-gradient(
        /* Gradient direction goes here */
        hsl(0,88.93%,50.39%),
        cubic-bezier(0.81, 0.07, 0.17, 0.7),
        hsl(229.27,76.82%,45.69%)
    );
}

/*
* Fallback CSS
*/
.forNow {
    background-image: linear-gradient(
        /* Gradient direction goes here */
        hsl(0,88.93%,50.39%) 0%,
        hsl(355.37,86.76%,50.28%) 15.24%,
        hsl(350.92,83.26%,49.98%) 26.69%,
        hsl(346.33,80.21%,49.42%) 34.97%,
        hsl(341.39,76.81%,48.57%) 40.73%,
        hsl(335.86,73.1%,47.42%) 44.6%,
        hsl(329.4,69.05%,45.95%) 47.23%,
        hsl(321.56,64.59%,44.16%) 49.25%,
        hsl(311.55,59.59%,42.04%) 51.3%,
        hsl(297.99,54.69%,40.29%) 54.02%,
        hsl(283.67,54.94%,43.14%) 58.05%,
        hsl(270.56,55.13%,45.75%) 64.02%,
        hsl(257.97,55.27%,48.1%) 72.58%,
        hsl(244.82,55.77%,50.17%) 84.36%,
        hsl(229.27,76.82%,45.69%) 100%
    );
}

最终效果如下:

虽然说,现在缓动渐变还不是规范中的一部分,但只要该效果是大家所需要的,我想在将来某一天他将会成为W3C规范中的一部分。就好比CSS的自定义属性(变量),也是由CSS预处理器的一部分,然后慢慢变成W3C规范中的一部分。

渐变的运和场景

上文提到的CSS渐变属性在现代Web开发中的使用是非常的频繁,因为他们除了可以帮助开发者快速还原UI之外,还可以为Web性能提供一定的优势。前面也说过了,CSS渐变主要被运用于CSS中能使用<image>的属性中,比如background-imageborder-imagelist-style-image以及mask-image等。接下来为大家介绍几个CSS渐变最常用的几个场景。

CSS渐变绘制图形

在《CSS的视觉效果》一文中和大家聊一些CSS中绘制图形和还原视觉效果的各种方案,其中CSS的渐变最是最为浓重的一笔。在项目中有很多效果(视觉效果)是可以纯CSS代码来实现的,比如像下图这些效果:

你或许已经发现了,其中很多UI上都能看到渐变的身影,那么这些渐变绝大多数都是可以用CSS渐变来实现。我们来看一个具体的实例:

仔细分析一下,我们可以采用多背景来实现:

完成这个示例的效果,就用到了linear-gradient()radial-gradient(),当然也还借助了background-sizecalc()等其他的CSS特性:

.card { 
    border-radius: 12px 72px 12px 12px; 
    border: 1px solid transparent; 
    border-color: rgba(184, 112, 0, 0.28); 
    box-shadow: 0 8px 12px 0 rgba(234, 165, 55, 0.3), inset 0 1px 3px 0 rgba(255, 255, 255, 0.5); 

    background-size: 28px 28px, 49px 49px, 103px 103px, cover; 
    background-position: calc(100% - 20px) calc(100% - 20px), calc(100% + 10px) calc(100% + 10px), -34px -28px, 0 0; 
    background-image: 
        radial-gradient(circle, rgba(255,255, 255, .2), rgba(255,255, 255, .2) 70%, rgba(255,255, 255,0) 70%), 
        radial-gradient(circle, rgba(255,255, 255, .2), rgba(255,255, 255, .2) 70%, rgba(255,255, 255,0) 70%), 
        radial-gradient(circle, rgba(255,255, 255, .3), rgba(255,255, 255, .3) 70%, rgba(255,255, 255,0) 70%), 
        linear-gradient(180deg, #ffe3ae 0%, #ffd34f 100%); 
    background-repeat: no-repeat; 
}

最终效果如下:

另外,使用CSS渐变还能不依赖任何图片,实现一些UI视觉丰富的Web组件:

渐变文本

在CSS中,我们是无法直接将渐变运用于color这样的属性上,但在实际开发中总是会碰到需要给文本添加渐变的的效果。那么我们就可以使用CSS的渐变结合CSS的background-cliptext-fill-colortext-stroke来实现文本的渐变填充和渐变描边等效果:

<h1 class="fill" style="--gradient:  linear-gradient(to right, red, gold)">Text Gradient</h1>
<h1 class="stroke" style="--gradient:  linear-gradient(to right, red, gold)">Text Gradient</h1>

.fill {
    text-fill-color: transparent;
    color: transparent;
    background-clip: text;
    background-image: var(--gradient);
}

.stroke {
    -webkit-text-stroke: 10px transparent;
    background-clip: text;
    background-image: var(--gradient);
    color: #fff;
}

效果如下:

按上面的方式还可以给整个段落的文本添加渐变色:

渐变边框

我平时在业务开发中,渐变边框的效果也是常见的一种。前面我们提到过,CSS渐变生成的就是<image>数据类型,它们除了可以被运用于background-image之外,还可以用于border-image。这里将大家演示几种实现渐变边框的技术方案。

先来看border-image和CSS渐变的组合:

<div style="--gradient: linear-gradient(red, gold)"></div>

div {
    border: 10px solid;
    border-image: var(--gradient) 1;
}

效果如下:

不过这种方式给带有圆角的边框添加渐变色,就无法实现了:

但是我们可以结合clip-path来实现:

div {
    border: 10px solid;
    border-image: var(--gradient) 1;
    clip-path: inset(0 round 10px);
}

效果如下:

如果你对CSS的clip-path感兴趣的话,可以移步阅读《探索CSS Masking模块:Clipping》一文。

实现渐变边框还可以结合background-clipbackground-origin和多个渐变来实现。这种方式也常称为是嵌套渐变。例如:

div {
    border: 10px solid transparent;
    background-image: linear-gradient(#222, #222), var(--gradient);
    background-origin: border-box;
    background-clip: padding-box, border-box; 
    border-radius: 10px;
}

效果如下:

在这个基础上配合background-size还可以使用CSS渐变实现带有纹理的边框效果:

去年改版的CSS Tricks网站中渐变边框就是一大特色,其中有一个半圆形的渐变边框效果就很有意思:

网站使用的是SVG来实现的:

其实我们也可以使用CSS的渐变来实现这个效果。@Sharps在Codepen就写了这个效果

我们还可以使用CSS的animation来构建带有动效的的渐变边框效果。基于上面的示例,稍作修改就可以使用渐边边框动起来:

@keyframes animatedgradient {
    0% {
        background-position: 0% 50%;
    }
    50% {
        background-position: 100% 150%;
    }
    100% {
        background-position: 0% 50%;
    }
}

div {
    border: 10px solid transparent;
    background-image: linear-gradient(#222, #222), var(--gradient);
    background-origin: border-box;
    background-clip: padding-box, border-box;
    border-radius: 10px;
    padding: 0 10px;
    animation: animatedgradient 30s linear alternate infinite;
    background-size: 500% 500%; /* 这个很重要 */
}

除了上面的方法之外,我们还可以使用CSS最新的特性 @property,来构建带有动效的渐变边框或渐变背景。

CSS渐变创建纹理

在上面的示例中,我们其实已经看到了使用CSS渐变创建带有纹理效果的边框。也就是说,使用CSS渐变可以创建很多有意思的背景纹理效果,只不过仅仅使用CSS的渐变是不够的,制作这些纹理效果还需要使用多背景,background-size等特性。

上图是截取MagicPattern网站的,除了这个,还有@Lea Verou写的一个纹理库

我们来看一个最简单的示例,就是黑白相隔的纹理效果:

body {
    background-color: #eee;
    background-image:
    linear-gradient(45deg, black 25%, transparent 25%, 
        transparent 75%, black 75%, black),
    linear-gradient(45deg, black 25%, transparent 25%, 
        transparent 75%, black 75%, black);
    background-size: 60px 60px;
    background-position: 0 0, 30px 30px;
}

效果如下:

前面在介绍repeating-conic-gradient()时就说过,我们可以使用圆锥渐变来构建纹理效果。就上面的效果,它是类似下图这样的图平铺出来的效果:

这个就是上面示例中background-size对应的一个盒子。如果我们使用repeating-conic-gradient()可以很容易实现上图的效果:

body {
    background-color: #eee;
    background: repeating-conic-gradient(#000 0% 25%, #eee 0% 50%) 50% / 60px 60px;
}

有关于这方面更详细的介绍,还可以阅读 @Ana Tudor 的《Background Patterns, Simplified by Conic Gradients》一文。@Ana Tudor在文章中提供了一个示例,使用repeating-conic-gradient()除了实现水平黑白间隔的纹理效果,还可以实现带有旋转的效果:

渐变在蒙层上的运用

CSS的渐变除了可以用于上面提到的border-imagebackground-image之外,还可以用于mask-image上。比如我们可以使用渐变将一张图片实现缕空效果:

div {
    width: 100vw;
    height: 100vh;
    background: url(https://assets.codepen.io/489403/grand_canyon.jpeg) no-repeat
        center;
    background-size: cover;

    mask-image: linear-gradient(
        to right,
        #000,
        #000 50%,
        transparent 50%,
        transparent 100%
    );
    mask-size: 10vw 100%;
    mask-repeat: repeat;
}

有关于CSS的mask这里就不详细介绍了,感兴趣的话可以阅读《探索CSS Masking模块:Masking》一文。

小结

这篇文章主要介绍了CSS的渐变属性,linear-gradient()radial-gradient()conic-gradient()以及其对应的重复渐变,比如repeating-linear-gradient()repeating-radial-gradient()repeating-conic-gradient()。通过文章的内容我们可以了解CSS渐变的属性的基本语法规则以及如何使用,但这些属性在使用的时候都有一些边界,文章中并没有深入的和大家探讨这方面的边界效果。

这篇文章可以称得上是CSS渐变的使用指南,希望它能帮助大家更好的了解CSS的渐变。如果你在这方面有更多的经验欢迎在下面的评论中与我们共享。

返回顶部