Skip to content
当前页大纲

linear-gradient的语法

css
linear-gradient([<angle> | to <side-or-corner>]? , <color-stop-list>)

这个函数接受的第一个参数是渐变的角度,他可以接受一个表示角度的值(可用的单位degradgradturn)或者是表示方向的关键词(toprightbottomleftleft toptop rightbottom right或者left bottom)。第二个参数是接受一系列颜色节点(终止点的颜色)

渐变容器

一个渐变图像和传统的背景图像不一样,它是没有维度(尺寸限制),它是无限的。那么决定渐变图像可见区域是由渐变容器大小来决定的

通常,如果给一个 DOM 元素的background-image使用linear-gradient,那么其(渐变)显示区域就是元素的border-box区域(如果不了解元素的border-box区域,建议先阅读box-sizing相关的文档)。其实也是background-color或者说通过url引入背景图像的显示区域

然而,如果你通过 CSS 的background-size设置一个尺寸,比如说background-size: 200px 200px,这个时候渐变容器(渐变尺寸)的大小就是200px * 200px。在没有使用background-position设置为其他值时,它默认是显示在 DOM 元素的左上角(也就是background-position: left top

渐变线

在渐变容器中,穿过容器中心点颜色停止点连接在一起的线称为渐变线。下面的渐变角度将会讲解更多细节

渐变角度

很明显,使用linear-gradient是通过渐变的角度来控制渐变的方向

渐变角度

C点渐变容器中心点∠A是通过C点垂直线(图中的虚线)与通过C点渐变线(图中的实线)的夹角,这个角称为渐变角度

可以通过下面的两种方式来定义这个角度

  • 使用关键词:to topto bottomto leftto rightto top rightto top leftto bottom rightto bottom left
  • 使用带单位的数字定义角度,比如45deg1turn

如果省略角度值,那默认就是to bottom(对应180deg0.5turn)

线性渐变默认角度

当使用顶角关键词时,需要注意的一点是,它依赖于渐变容器的尺寸。例如to top right

如果你想要一个redblue的渐变,方向是至元素的top top right。逻辑上,blue应该在元素的右上角,以及中间的紫色渐变周围应该形成一条直线,从左上角至右下角穿过。如下图所示:

线性渐变右上角

所以to top right并不意味着渐变线穿过右上角,也就是说渐变角度并不意味着是45deg

下面是一个渐变线移动变化的示意图:

渐变线移动示意图

渐变线长度

渐变线长度

如果所示,我们想要一个redblue的渐变,渐变的角度是45deg,因为渐变容器的比例,渐变线不能通过右上角。但浏览器想要做什么(规范告诉它做什么),能使右上角是blue

如果我们让渐变线的开始和结束都在渐变容器的边缘,那么blue将会覆盖渐变容器更大的区域,渐变不会有更多的扩散。

因此,为了做到这一点,渐变线有时不得不延长到渐变容器之外。其实很容器知道它的开始和结束位置。通过最近的角落画一条垂直于渐变线的线,与渐变线交叉的地方,就是渐变的开始和结束位置(规范中做出了很好的解释

事实上,如果 W 是渐变容器的宽度,H 是渐变容器的高度,A 是渐变角度,那么渐变线的长度可以通过下面的公式计算:abs(W * sin(A)) + abs(H * cos(A))

渐变色节点

每一个渐变色节点可以这样定义: <color> [<percentage> | <length>]?

可以看到,渐变线的位置并不是必须的,例如:

渐变色节点

如果没有显式指定颜色在渐变线上的位置,这将交给浏览器来确定颜色在渐变线上的位置。最简单的情况下只有两个颜色颜色 1将被放置在渐变线0%位置(渐变线开始位置),颜色 2将被放置在100%位置处(渐变线的结束点)。如果有三个颜色,那么颜色 1在渐变线的0%颜色 2在渐变线的50%颜色 3在渐变线的100%

在上面的这个示例中,有五个颜色,那么它们的位置分别在0%25%50%75%100%。它们将沿着渐变线平均分布渐变颜色

当然,也可以在渐变线上显式自定义渐变颜色在渐变线的位置。每个位置可以用百分比表示(相对于渐变线计算),也可以是任何一个 CSS 长度单位。比如下面这个示例:

自定义渐变色结束点

注意

渐变色结束点是一个增量值,排在后面的渐变色结束点必须大于之前的,否则浏览器会自动纠正

渐变结束点纠正

如上图:最后一个颜色blue是不正确的位置,因此浏览器将会纠正它的位置与之前的位置相同,在这种情况之下并不是与其相邻的颜色yellow,也不会是orange,它会追溯到第一个颜色red位置处。因此,redblue都分布在渐变线的30%处,因此其中yelloworange两颜色都将不可见

一个线性渐变的可视化工具

参考自《你真的理解 CSS 的 linear-gradient?

实战:条纹进度条

思路:

  1. 把渐变背景分成若干份正方形的切片
  2. 接着将每一份切片的背景均匀的分为四份,使用两种颜色互相隔开,因此需要四组渐变色节点
  3. 最后把每一份切片拼接成完整的斜向条纹
查看关键部分
css
background-color: var(--main-color);
background-size: 5rem 5rem;
background-image: linear-gradient(
  -45deg,
  transparent 0,
  transparent 25%,
  var(--light-color) 25%,
  var(--light-color) 50%,
  transparent 50%,
  transparent 75%,
  var(--light-color) 75%,
  var(--light-color) 100%
);
/* 或者也可以这样写 */
background-image: repeating-linear-gradient(-45deg, transparent 0 25%, var(--light-color) 25% 50%);
/* 因为上面把切片大小定为5rem,所以动画的位移也要是5rem */
@keyframes stripe-animation {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 5rem 0;
  }
}

全部代码如下

html
<div class="container">
  <div class="stripe"></div>
</div>
css
:root {
  --bg-color: #f1f1f1;
  --main-color: #fff;
  --light-color: #ff0000;
  --shadow-color: rgba(255, 0, 0, 0.15);
}
* {
  margin: 0;
  padding: 0;
  user-select: none;
  list-style-type: none;
}
html,
body {
  background-repeat: no-repeat;
  background-position: center;
  width: 100vw;
  height: 100vh;
  background-color: var(--bg-color);
}
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}
.stripe {
  width: 50%;
  height: 10vh;
  position: relative;
  background-color: var(--main-color);
  border: 1px solid var(--main-color);
  box-shadow: 1vw 3vh 10vh var(--shadow-color);
  border-radius: 10px;
  background-size: 5rem 5rem;
  background-image: repeating-linear-gradient(
    -45deg,
    transparent 0 25%,
    var(--light-color) 25% 50%
  );
  animation: stripe-animation 1s infinite linear;
  -o-animation: stripe-animation 1s infinite linear;
  -webkit-animation: stripe-animation 1s infinite linear;
  -moz-animation: stripe-animation 1s infinite linear;
}
.stripe::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  height: 100%;
  border-radius: 10px;
  background-image: linear-gradient(
    var(--main-color) 0,
    transparent 30%,
    transparent 70%,
    var(--main-color) 100%
  );
}

@keyframes stripe-animation {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 5rem 0;
  }
}
@-o-keyframes stripe-animation {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 5rem 0;
  }
}
@-webkit-keyframes stripe-animation {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 5rem 0;
  }
}
@-moz-keyframes stripe-animation {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 5rem 0;
  }
}

MIT License.