Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入理解 CSS linear-gradient #35

Open
anjia opened this issue Dec 5, 2018 · 4 comments
Open

深入理解 CSS linear-gradient #35

anjia opened this issue Dec 5, 2018 · 4 comments
Labels
CSS cascading style sheets 文章

Comments

@anjia
Copy link
Owner

anjia commented Dec 5, 2018

渐变

渐变(Gradient)是 CSS3 引入的特性,其定义详见 CSS Images Module Level 3。它本质上是一个 2D 图像,可以对 background-image、list-style-image 和 border 等进行细微着色。

语法是:

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

渐变会绘制到一个叫渐变框(gradient box)的矩形框里。渐变框有具体的大小,而渐变本身是没有固有尺寸的。

固有尺寸(intrinsic dimensions)是固有宽度、固有高度、固有宽高比的集合。对于特定的对象,这三个尺寸都有可能存在或者不存在。比如:光栅图像(image)同时拥有这三个,SVG image 只有一个固有宽高比,CSS 渐变就没有任何固有尺寸。

举个例子,理解下。

在下面的代码中,渐变框就是.demo容器的 padding box,宽 220px 高 120px。

<style>
.demo {
    width: 200px; 
    height: 100px;
    padding: 10px;

    background-color: #eaeaea;
    background-image: linear-gradient(red, green);  /* 线性渐变 */
    background-repeat: no-repeat;
    background-position: center;
}
</style>

<div class="demo"></div>

如果你给 .demo 再增加一行下面的 CSS,那么,渐变框就变成了宽 50px 高 50px。

.demo {
    background-size: 50px 50px;
}

如果你是增加的下面这行 CSS,那么,渐变框就变成了宽 440px 高 240px。

.demo {
    background-size: 200% 200%;
}

同一个渐变,在渐变框大小不同时呈现的不同效果:

220px * 120px 50px * 50px 440px * 240px

理解 1. 渐变本身是没有固有尺寸的,虽然渐变框有具体大小

要想指定一个渐变效果,只需定义这三个元素,即可:

  • 渐变线(gradient line)
  • 渐变线上的起始点(starting point)和结束点(ending point)
  • 在起始点和结束点上的颜色值

这样,颜色就会平滑地填充渐变线上的其余部分。

不同的渐变类型,会定义如何使用渐变线上的颜色们来生成实际的渐变。

渐变类型,在几何上,可以是:

  • 线段(line):对应 CSS 的线性渐变(linear gradient)
  • 射线(ray):对应 CSS 的径向渐变(radial gradient)
  • 螺旋(spiral):对应 CSS 的圆锥渐变(conic gradient)

理解 2. 渐变三元素:渐变线、起始点和结束点、颜色序列

@anjia
Copy link
Owner Author

anjia commented Dec 5, 2018

本篇文章,先只聊最直观的线性渐变。

线性渐变

线性渐变就是指定一条直直的渐变线,然后再在这条线上放置几种颜色。在这种渐变类型下,创建 2D 图像的过程是:创建一个“无限”画布,用垂直于渐变线的线条来填充它,线条的颜色就取它和渐变线交点的那个颜色。

这里的“无限”是指渐变是可以无限大的,因为它本身是没有固有尺寸的。
之所以加引号“”,是因为在实际绘制中,渐变必然是被限制在一个有具体大小的渐变框里。

用一个例子来理解线性渐变创建 2D 图像的过程。

.demo {
    width: 200px; height: 100px; padding: 10px;

    /* 线性渐变,颜色依次是:深粉色、黄色、柠檬绿*/
    background-image: linear-gradient(0deg, deeppink, yellow, lime);
}

以上代码绘制出来的效果,如下。图中,蓝色标出的就是渐变线,它通过渐变框的中心。

三条横线是参考线,可忽略

整个渐变图像是画了无数条垂直于渐变线的线条而成的。在脑补这个绘制过程时,我又冒出了两个问题:

  • 渐变线上的颜色,生成规则是什么样子的?
  • 渐变线本身,是怎么确定的?

这,就需要从线性渐变的定义说起。

语法

线性渐变的语法是:

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

<side-or-corner> = [left | right] || [top | bottom]

linear-gradient()函数有两个参数:

  1. 第一个参数定义了渐变线。它给出了渐变线的方向,缺省是to bottom
  2. 第二个参数定义了渐变线上的颜色序列。

渐变线的方向

渐变线的方向,可以用两种方式来指定:

  • <angle>:0deg 即向上,正数表示顺时针方向旋转,所以 90deg 即向右。
  • 用关键字
    • to top, to right, to bottom, to left,对应到<angle>分别是 0deg, 90deg, 180deg, 270deg
    • to left top 则是指渐变框的左上角

在渐变框的中心点处,建立平面极坐标系:中心点是极点,向上的射线是极轴。

当渐变线的方向分别是 0deg、60deg、300deg 时,效果依次是:

颜色序列均是:深粉色、黄色、柠檬绿

0deg 60deg 300deg

起始点和结束点,都在渐变线上。

结束点位置的确定,是依据渐变方向,选择和它在同一个象限的渐变框的顶点,从它作一条垂直于渐变线的线,交点即结束点。同理,在相反方向上可确定起始点的位置。

理解 3. 结束点和起始点的位置确定规则

值得一提的是,当渐变线的方向是指向渐变框的某个角(corner)时,情况会稍稍复杂一些。比如,当渐变方向是to left top时,如下图:

第一反应,有没有觉得很奇怪?明明指定的渐变方向是to left top,为什么渐变线的方向却不是指向left top的呢?其实,这是有意为之的,是为了保证让渐变颜色的 50% 处恰好通过left bottomright top这两点。

所以,当渐变方向是指向特定角(eg. to left top)时,渐变线的方向是:在渐变框的中心点处,做一条垂直于相邻角(left bottomright top)连线的直线,取与指定方向(to left top)象限相同的那个方向。

理解 4. 渐变线方向的两种指定方式,esp.当指向 corner 的时候

@anjia
Copy link
Owner Author

anjia commented Dec 5, 2018

渐变线上的颜色序列

渐变线上的颜色序列是用<color-stop-list>指定的。它的语法是:

<color-stop-list> = <color-stop>#{2,}

<color-stop> = <color> <length-percentage>?

颜色的个数必须大于等于 2 个。<color-stop> 是颜色和位置的组合

这里,需要注意两点:

  1. <length-percentage>的百分比,是针对渐变线的长度计算的
    • 渐变线的长度,是起始点和结束点之间的线段的长度
    • 它的计算公式是:abs(W * sin(A)) + abs(H * cos(A))
      • A 是渐变线的方向的角度
      • W 是渐变框的宽度
      • H 是渐变框的高度
    • 对其计算公式的推导感兴趣的朋友可以阅读 Dig deep into CSS linear gradients
  2. <length-percentage>的取值,可以是 [0%, 100%] 之外的值
    • 原因:渐变本身是没有固有尺寸的,渐变线的两端也是可以无限延伸的
    • 起始点和结束点,只是渐变线上的两个有特殊意义的位置标识,而已

对于“颜色位置”的实例,这里就不展开讲了。有兴趣的朋友可以自行实践

理解 5. 颜色序列的颜色位置,取值可以在区间 [0%, 100%] 之内,也可以在其之外

@anjia
Copy link
Owner Author

anjia commented Dec 5, 2018

总结

关于线性渐变,理解这五点:

  1. 渐变本身是没有固有尺寸的,虽然渐变框有具体大小
  2. 渐变三元素:渐变线、起始点和结束点、颜色序列
  3. 渐变线方向的两种指定方式,esp.当指向 corner 的时候
  4. 起始点和结束点的位置确定规则
  5. 颜色序列的颜色位置,取值可以在区间 [0%, 100%] 之内,也可以在其之外

参考及更多

@anjia anjia added CSS cascading style sheets 文章 labels Dec 5, 2018
@anjia anjia mentioned this issue Dec 31, 2018
@zhanghe-V
Copy link

greate,it,s helped me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS cascading style sheets 文章
Projects
None yet
Development

No branches or pull requests

2 participants